@liteeditor/editor 1.2.3 → 1.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -8,4 +8,4 @@
8
8
  * available. Redistribution or removal of licensing is prohibited.
9
9
  * See https://liteeditor.com/terms
10
10
  */
11
- !function(e,t){"use strict";const i=t.currentScript;class n{constructor(){this.instances=new Map,this.instanceCounter=0,this.version="1.2.3",this.apiKey=null,this.apiBase=null,this._licensePromises={},this._license=null}configure(e={}){return e.apiKey&&(this.apiKey=String(e.apiKey)),e.apiBase&&(this.apiBase=String(e.apiBase)),this}getLicense(){const e=this._license||{valid:!1};return{valid:!!e.valid,features:e.features||[],token:e.token||null}}static DEFAULT_STYLES={table:"border-collapse: collapse; width: 100%; max-width: 100%; margin: 10px 0;",th:"border: 1px solid #ddd; padding: 8px; background: #f2f2f2; color: #000; text-align: left; font-weight: bold;",td:"border: 1px solid #ddd; padding: 8px;",blockquote:"border-left: 4px solid #ccc; padding: 10px 20px; margin: 10px 0; background: #f9f9f9;",pre:"background: #f4f4f4; padding: 10px; border-radius: 5px; overflow-x: auto; margin: 10px 0; font-family: 'Courier New', Consolas, Monaco, monospace;",code:"background: #f4f4f4; padding: 2px 6px; border-radius: 3px; font-family: 'Courier New', Consolas, Monaco, monospace;",hr:"border: none; border-top: 1px solid #ddd; margin: 15px 0;",img:"max-width: 100%; height: auto;",ul:"margin: 10px 0; padding-left: 40px; list-style-type: disc;",ol:"margin: 10px 0; padding-left: 40px; list-style-type: decimal;",li:"margin: 5px 0;"};static resolveStyles(e){return!1===e?null:e?Object.assign({},n.DEFAULT_STYLES,e):Object.assign({},n.DEFAULT_STYLES)}static sanitizeUrl(e,t={}){if(null==e)return"";const i=String(e).trim();if(!i)return"";const n=i.replace(/[\u0000-\u0020\u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000]/g,"").toLowerCase(),o=(n.match(/^([a-z][a-z0-9+.\-]*):/)||[])[1];if(!o)return i;if("data"===o)return t.allowDataImage&&/^data:image\/(png|jpe?g|gif|webp|bmp|x-icon|svg\+xml)[;,]/.test(n)?i:"";return["http","https","mailto","tel"].includes(o)?i:""}static isAllowedEmbedHost(e){const t=["youtube.com","youtube-nocookie.com","youtu.be","vimeo.com","player.vimeo.com","dailymotion.com","spotify.com","open.spotify.com","soundcloud.com","w.soundcloud.com","codepen.io","codesandbox.io","google.com","maps.google.com"];try{const i=new URL(e,"https://x.invalid").hostname.toLowerCase().replace(/^www\./,"");return t.some(e=>i===e||i.endsWith("."+e))}catch(e){return!1}}static applyDefaultStyles(e,t){const i=void 0===t?n.DEFAULT_STYLES:t;i&&(n._migrateImagesResponsive(e),Object.keys(i).forEach(t=>{const o=i[t];o&&e.querySelectorAll(t).forEach(e=>{const t=n._mergeStyles(o,e.getAttribute("style")||"");t&&e.setAttribute("style",t)})}),e.querySelectorAll("pre > code").forEach(e=>{i.code&&e.getAttribute("style")===i.code&&e.removeAttribute("style")}))}static _migrateImagesResponsive(e){function t(e){return Number.isInteger(e)?String(e):String(parseFloat(e.toFixed(3)))}e.querySelectorAll("img").forEach(e=>{const i=e.getAttribute("style")||"";if(!i)return;const n=i.split(";").map(e=>e.trim()).filter(Boolean);let o=0,r=0,l=!1;if(n.forEach(e=>{const t=e.indexOf(":");if(t<0)return;const i=e.slice(0,t).trim().toLowerCase(),n=e.slice(t+1).trim();if("width"===i||"height"===i){const e=n.match(/^(\d+(?:\.\d+)?)px$/);e&&("width"===i?o=parseFloat(e[1]):r=parseFloat(e[1]))}else"aspect-ratio"===i&&(l=!0)}),!(o>0&&r>0)||l)return;const a=n.filter(e=>"height"!==e.split(":")[0].trim().toLowerCase());a.push(`aspect-ratio: ${t(o)} / ${t(r)}`),a.push("height: auto"),e.setAttribute("style",a.join("; ")),e.removeAttribute("width"),e.removeAttribute("height")})}static _mergeStyles(e,t){const i=e=>{const t={},i=[];return e.split(";").forEach(e=>{if(!(e=e.trim()))return;const n=e.indexOf(":");if(n<0)return;const o=e.slice(0,n).trim().toLowerCase(),r=e.slice(n+1).trim();o&&(o in t||i.push(o),t[o]=r)}),{map:t,order:i}},n=i(e),o=i(t),r=n.order.slice();o.order.forEach(e=>{r.includes(e)||r.push(e)});const l=Object.assign({},n.map,o.map);return r.map(e=>`${e}: ${l[e]}`).join("; ")}applyDefaultStyles(e,i){const o=t.createElement("div");return o.innerHTML=String(null==e?"":e),n.applyDefaultStyles(o,void 0===i?n.DEFAULT_STYLES:i),o.innerHTML}init(e){const i=e.selector||"textarea",n="string"==typeof i?t.querySelectorAll(i):[i],o=[];return n.forEach(t=>{t&&!t.dataset.liteeditorId&&o.push(this.createInstance(t,e))}),this._enforceLicense(e,o),this}_resolveApiKey(e){return e&&e.apiKey?String(e.apiKey):this.apiKey?this.apiKey:this._apiKeyFromScript()}_apiKeyFromScript(){const t=i;if(!t||!t.getAttribute)return null;const n=t.getAttribute("data-key");if(n)return n.trim();const o=t.src||"";if(!o)return null;try{const t=new URL(o,e.location&&e.location.href||void 0),i=t.searchParams.get("key")||t.searchParams.get("apiKey");if(i)return i.trim();const n=t.pathname.match(/\/(le_[a-z0-9_]+)\//i);if(n)return n[1]}catch(e){}return null}_resolveApiBase(e){if(e&&e.apiBase)return String(e.apiBase);if(this.apiBase)return this.apiBase;return(i&&i.getAttribute?i.getAttribute("data-api-base"):null)||"https://app.liteeditor.com"}_validateLicense(e,t){const i=e||"none";if(this._licensePromises[i])return this._licensePromises[i];const n=this._readLicenseCache(e);if(n)return this._licensePromises[i]=Promise.resolve(n),this._licensePromises[i];if("undefined"==typeof fetch)return this._licensePromises[i]=Promise.resolve({valid:!0,_skipped:!0}),this._licensePromises[i];const o=String(t).replace(/\/+$/,"")+"/api/v1/validate";return this._licensePromises[i]=fetch(o,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({key:e||null})}).then(e=>e.json().then(t=>Object.assign({_http:e.status},t))).then(t=>(t&&t.valid&&this._writeLicenseCache(e,t),t)).catch(()=>({valid:!0,_networkError:!0})),this._licensePromises[i]}_enforceLicense(e,t){const i=this._resolveApiKey(e),n=this._resolveApiBase(e);this._validateLicense(i,n).then(e=>{e&&e.valid?this._license={valid:!0,features:e.features||[],token:e.token||null}:(this._license={valid:!1,reason:e&&e.reason||"invalid_key"},t.forEach(e=>{try{e&&e.applyLicenseState(this._license)}catch(e){}}),"undefined"!=typeof console&&console.warn&&console.warn("[LiteEditor] Invalid or missing API key"+(this._license.reason?" ("+this._license.reason+")":"")+". Get a free key at https://liteeditor.com"))})}_readLicenseCache(t){try{const i=e.localStorage.getItem("liteeditor_license_"+(t||"none"));if(!i)return null;const n=JSON.parse(i);if(n&&n.exp&&n.exp>Date.now())return n.res}catch(e){}return null}_writeLicenseCache(t,i){try{e.localStorage.setItem("liteeditor_license_"+(t||"none"),JSON.stringify({exp:Date.now()+6e5,res:i}))}catch(e){}}createInstance(e,t){const i="liteeditor-"+this.instanceCounter++;e.dataset.liteeditorId=i;const n=new o(e,t,i);return this.instances.set(i,n),n}get(e){if(e){if("string"==typeof e&&this.instances.has(e))return this.instances.get(e);if(e&&1===e.nodeType)return this.instances.get(e.dataset.liteeditorId);if("string"==typeof e){const i=t.querySelector(e);return i?this.instances.get(i.dataset.liteeditorId):void 0}}}getAll(e){if(!e)return Array.from(this.instances.values());const i=t.querySelectorAll(e),n=[];return i.forEach(e=>{const t=this.instances.get(e.dataset.liteeditorId);t&&n.push(t)}),n}remove(e){if(!e)return;const i=e=>{const t=this.instances.get(e);t&&(t.destroy(),this.instances.delete(e))};"string"==typeof e&&this.instances.has(e)?i(e):e&&1===e.nodeType?i(e.dataset.liteeditorId):"string"==typeof e&&t.querySelectorAll(e).forEach(e=>i(e.dataset.liteeditorId))}getAllInstances(){return Array.from(this.instances.values())}cleanHTML(e,i){const o=t.createElement("div");return o.innerHTML=String(null==e?"":e),n.stripChromeIn(o),n.normalizePasted(o,i),o.innerHTML}static _convertWordFakeLists(e){const i=e.ownerDocument||t,n=e=>{const t=/margin-left\s*:\s*(-?[\d.]+)\s*(in|pt|px|cm|mm|em)\b/i.exec(e||"");if(!t)return 1;const i=parseFloat(t[1]),n={in:i,pt:i/72,px:i/96,cm:i/2.54,mm:i/25.4,em:16*i/96}[t[2].toLowerCase()];return Math.max(1,Math.round(n/.5))},o=e=>{const t=i.createTreeWalker(e,NodeFilter.SHOW_TEXT,null);let n;for(;n=t.nextNode();)if(n.nodeValue&&n.nodeValue.replace(/[\s ]+/g,""))return n;return null},r=(e,t)=>{const i=o(e);if(!i)return null;const n=new RegExp("^[\\s ]*([•·▪■§○◦o]|\\(?\\d{1,4}[.)]|\\(?[ivxlcdmIVXLCDM]{2,6}[.)]|\\(?[A-Za-z][.)])"+(t?"(?:[\\s ]*[ \\t])[\\s ]*":"[\\s ]+")).exec(i.nodeValue);return n?(i.nodeValue=i.nodeValue.slice(n[0].length),n[1]):null},l=e=>{const t=e.getAttribute("style")||"",i=e.getAttribute("class")||"",o=/mso-list\s*:\s*l(\d+)\s+level(\d+)/i.exec(t),l=!!o||/\bMsoListParagraph/i.test(i);let a;if(l)a=(e=>{const t=Array.from(e.querySelectorAll("span[style]")).find(e=>/mso-list\s*:\s*ignore/i.test(e.getAttribute("style")||""));if(t){const e=t.textContent;return t.remove(),e}const i=Array.from(e.childNodes),n=i.findIndex(e=>8===e.nodeType&&/\[if\s+!supportLists\]/i.test(e.nodeValue));if(n>=0){let e="";for(let t=n;t<i.length;t++){const n=i[t],o=8===n.nodeType&&/\[endif\]/i.test(n.nodeValue);if(8!==n.nodeType&&(e+=n.textContent),n.remove(),o)break}return e}return r(e,!1)||""})(e);else if(a=r(e,!0),null==a)return null;const s=(e=>{const t=(e||"").replace(/[ \s]+/g," ").trim();return t?/^\(?\d{1,4}[.)]$/.test(t)?{ordered:!0,styleType:null}:/^\(?[ivxlcdm]{2,6}[.)]$/.test(t)?{ordered:!0,styleType:"lower-roman"}:/^\(?[IVXLCDM]{2,6}[.)]$/.test(t)?{ordered:!0,styleType:"upper-roman"}:/^\(?[a-z][.)]$/.test(t)?{ordered:!0,styleType:"lower-alpha"}:/^\(?[A-Z][.)]$/.test(t)?{ordered:!0,styleType:"upper-alpha"}:/^[o○◦]$/.test(t)?{ordered:!1,styleType:"circle"}:/^[§▪■]$/.test(t)?{ordered:!1,styleType:"square"}:{ordered:!1,styleType:null}:{ordered:!1,styleType:null}})(a);return{el:e,listId:o?o[1]:null,level:o?Math.max(1,parseInt(o[2],10)):n(t),ordered:s.ordered,styleType:s.styleType,continuation:l&&!o&&!a}},a=new Map;if(e.querySelectorAll("p").forEach(e=>{const t=l(e);t&&a.set(e,t)}),!a.size)return;const s=new Set;a.forEach((e,t)=>{if(s.has(t))return;const n=[];let r=t;for(;r&&a.has(r);){const e=a.get(r);if(n.length&&null!=e.listId){const t=n[n.length-1];if(null!=t.listId&&t.listId!==e.listId)break}s.add(r),n.push(e),r=r.nextElementSibling}(e=>{const t=e[0].el.parentNode;if(!t)return;const n=[],r=[];let l=null;e.forEach(e=>{if(e.continuation&&l){for(l.appendChild(i.createElement("br"));e.el.firstChild;)l.appendChild(e.el.firstChild);return}const t=Math.max(1,e.level||1);for(;r.length>t;)r.pop();for(r.length===t&&t&&r[t-1].tagName!==(e.ordered?"OL":"UL")&&r.pop();r.length<t;){const t=i.createElement(e.ordered?"ol":"ul");if(e.styleType&&t.setAttribute("style","list-style-type: "+e.styleType),r.length){const e=r[r.length-1];let n=e.lastElementChild;n&&"LI"===n.tagName||(n=i.createElement("li"),e.appendChild(n)),n.appendChild(t)}else n.push(t);r.push(t)}const a=i.createElement("li");for(;e.el.firstChild;)a.appendChild(e.el.firstChild);const s=o(a);s&&(s.nodeValue=s.nodeValue.replace(/^[\s ]+/,"")),r[r.length-1].appendChild(a),l=a}),n.forEach(i=>t.insertBefore(i,e[0].el)),e.forEach(e=>e.el.remove())})(n)})}static normalizePasted(e,i){const o=new Set((i||{}).keepClasses||[]),r=e.ownerDocument||t;n._convertWordFakeLists(e);const l=r.createTreeWalker(e,NodeFilter.SHOW_COMMENT,null),a=[];for(;l.nextNode();)a.push(l.currentNode);for(a.forEach(e=>e.parentNode&&e.parentNode.removeChild(e));;){e.querySelector("*");let t=null;if(e.querySelectorAll("*").forEach(e=>{if(t)return;const i=e.tagName?e.tagName.toLowerCase():"";i.includes(":")&&(i.startsWith("o:")||i.startsWith("v:")||i.startsWith("w:")||i.startsWith("x:")||i.startsWith("st1:"))&&(t=e)}),!t)break;for(;t.firstChild;)t.parentNode.insertBefore(t.firstChild,t);t.remove()}const s=["aria-level","aria-hidden","aria-labelledby","aria-describedby","dir","lang","role","data-block-id","data-tag","data-pm-slice","data-id","data-uuid","contenteditable"];e.querySelectorAll("*").forEach(e=>{s.forEach(t=>e.removeAttribute(t)),e.id&&/^docs-internal-guid-/.test(e.id)&&e.removeAttribute("id")}),e.querySelectorAll("[class]").forEach(e=>{if(0===o.size)return void e.removeAttribute("class");const t=(e.getAttribute("class")||"").split(/\s+/).filter(e=>e&&o.has(e));t.length?e.setAttribute("class",t.join(" ")):e.removeAttribute("class")});const c=(e,t)=>{const i=r.createElement(t);for(Array.from(e.attributes).forEach(e=>i.setAttribute(e.name,e.value));e.firstChild;)i.appendChild(e.firstChild);return e.parentNode.replaceChild(i,e),i},d=e=>{for(;e.firstChild;)e.parentNode.insertBefore(e.firstChild,e);e.remove()};e.querySelectorAll("b, strong").forEach(e=>{/font-weight\s*:\s*(normal|400)\b/i.test(e.getAttribute("style")||"")&&d(e)}),e.querySelectorAll("i, em").forEach(e=>{/font-style\s*:\s*normal\b/i.test(e.getAttribute("style")||"")&&d(e)}),e.querySelectorAll("b").forEach(e=>c(e,"strong")),e.querySelectorAll("i").forEach(e=>c(e,"em")),e.querySelectorAll("strike").forEach(e=>c(e,"s")),e.querySelectorAll("font").forEach(e=>{const t=e.getAttribute("color"),i=e.getAttribute("face"),n=[];if(t&&n.push(`color: ${t}`),i&&n.push(`font-family: ${i}`),n.length){const t=r.createElement("span");for(t.setAttribute("style",n.join("; "));e.firstChild;)t.appendChild(e.firstChild);e.parentNode.replaceChild(t,e)}else{for(;e.firstChild;)e.parentNode.insertBefore(e.firstChild,e);e.remove()}}),e.querySelectorAll("center").forEach(e=>{const t=r.createElement("div");for(t.setAttribute("style","text-align: center;");e.firstChild;)t.appendChild(e.firstChild);e.parentNode.replaceChild(t,e)});const h=new Set(["color","background-color","font-weight","font-style","text-decoration","font-size","line-height","text-align","list-style-type","list-style-position","list-style","list-style-image","width","height","max-width","min-width","max-height","min-height","aspect-ratio","object-fit","object-position","border","border-top","border-right","border-bottom","border-left","border-collapse","border-radius","border-color","border-style","border-width","padding","padding-top","padding-right","padding-bottom","padding-left","margin","margin-top","margin-right","margin-bottom","margin-left","display","float","clear","overflow","overflow-x","overflow-y","font-family"]),p={"font-weight":'strong, b, h1, h2, h3, h4, h5, h6, th, [style*="font-weight"]',"font-style":'em, i, [style*="font-style"]',"text-decoration":'u, a, s, strike, [style*="text-decoration"]',color:'[style*="color"]'};e.querySelectorAll("[style]").forEach(e=>{const t=e.getAttribute("style").split(";").map(e=>e.trim()).filter(Boolean).map(t=>{const i=t.indexOf(":");if(i<0)return null;const n=t.slice(0,i).trim().toLowerCase(),o=t.slice(i+1).trim();if(!h.has(n))return null;const r=o.toLowerCase().replace(/\s+/g,"");return("font-weight"===n&&("400"===o||"normal"===o)||"font-style"===n&&"normal"===o||"text-decoration"===n&&"none"===o||"color"===n&&("#000000"===r||"#000"===r||"black"===r||"rgb(0,0,0)"===r))&&!((e,t)=>!(!e.parentElement||!e.parentElement.closest(p[t])))(e,n)?null:"background-color"!==n||"transparent"!==r&&"rgba(0,0,0,0)"!==r?`${n}: ${o}`:null}).filter(Boolean).join("; ");t?e.setAttribute("style",t):e.removeAttribute("style")});const u=/font-weight\s*:\s*(700|800|900|bold|bolder)/i,m=/font-style\s*:\s*italic/i,f=/text-decoration[^:]*:\s*[^;]*underline/i,g=/text-decoration[^:]*:\s*[^;]*line-through/i;e.querySelectorAll("span[style]").forEach(e=>{const t=e.getAttribute("style")||"",i=u.test(t),n=m.test(t),o=f.test(t),l=g.test(t);if(!(i||n||o||l))return;let a=t.split(";").map(e=>e.trim()).filter(Boolean).filter(e=>{const t=e.split(":")[0].trim().toLowerCase();return("font-weight"!==t||!i)&&(("font-style"!==t||!n)&&("text-decoration"!==t||!o&&!l))}).join("; ");a?e.setAttribute("style",a):e.removeAttribute("style");let s=e;const c=e=>{const t=r.createElement(e);s.parentNode.insertBefore(t,s),t.appendChild(s),s=t};l&&c("s"),o&&c("u"),n&&c("em"),i&&c("strong")}),e.querySelectorAll("span").forEach(e=>{if(0===e.attributes.length&&e.parentNode){for(;e.firstChild;)e.parentNode.insertBefore(e.firstChild,e);e.remove()}}),["strong","em","u","s"].forEach(t=>{e.querySelectorAll(`${t} ${t}`).forEach(e=>{if(e.parentNode&&e.parentNode.tagName.toLowerCase()===t){for(;e.firstChild;)e.parentNode.insertBefore(e.firstChild,e);e.remove()}})});const b=/^(P|DIV|UL|OL|LI|TABLE|TBODY|THEAD|TFOOT|TR|TD|TH|H[1-6]|BLOCKQUOTE|PRE|HR|SECTION|ARTICLE|ASIDE|HEADER|FOOTER|NAV|FIGURE|FIGCAPTION|FORM)$/;e.querySelectorAll("div").forEach(e=>{if(Array.from(e.children).some(e=>b.test(e.tagName)))return;const t=r.createElement("p");for(Array.from(e.attributes).forEach(e=>t.setAttribute(e.name,e.value));e.firstChild;)t.appendChild(e.firstChild);e.parentNode.replaceChild(t,e)}),e.querySelectorAll("li").forEach(e=>{for(;e.firstChild&&3===e.firstChild.nodeType&&!e.firstChild.nodeValue.trim();)e.removeChild(e.firstChild);for(;e.lastChild&&3===e.lastChild.nodeType&&!e.lastChild.nodeValue.trim();)e.removeChild(e.lastChild);if(1===e.children.length&&1===e.childNodes.length){const t=e.children[0];if("P"===t.tagName||"DIV"===t.tagName){for(;t.firstChild;)e.insertBefore(t.firstChild,t);t.remove()}}});const y=["utm_source","utm_medium","utm_campaign","utm_term","utm_content","fbclid","gclid","msclkid","mc_cid","mc_eid","_ga","mkt_tok","yclid","dclid"];e.querySelectorAll("a[href]").forEach(e=>{const t=e.getAttribute("href")||"";if(t&&"#"!==t[0]&&!/^(mailto:|tel:|javascript:)/i.test(t))try{const i=new URL(t,"http://x.invalid");let n=!1;if(y.forEach(e=>{i.searchParams.has(e)&&(i.searchParams.delete(e),n=!0)}),n){const n=/^[a-z][a-z0-9+.-]*:\/\//i.test(t)?i.toString():i.pathname+(i.search?i.search:"")+(i.hash?i.hash:"");e.setAttribute("href",n.replace(/\?$/,""))}}catch(e){}})}static stripChromeIn(e){e.querySelectorAll('.liteeditor-image-resizer, [data-liteeditor-chrome="1"].liteeditor-image-resizer').forEach(e=>{const t=e.querySelector("img");t?(t.classList.remove("wrapped"),""===t.getAttribute("class")&&t.removeAttribute("class"),e.parentNode.replaceChild(t,e)):e.remove()});e.querySelectorAll('.liteeditor-table-wrapper, [data-liteeditor-chrome="1"].liteeditor-table-wrapper').forEach(e=>{const t=e.querySelector(":scope > table");t?e.parentNode.replaceChild(t,e):e.remove()}),e.querySelectorAll('.liteeditor-resize-handle, .liteeditor-image-info, [data-liteeditor-chrome="1"]').forEach(e=>e.remove()),e.querySelectorAll("img.wrapped").forEach(e=>{e.classList.remove("wrapped"),""===e.getAttribute("class")&&e.removeAttribute("class")})}}class o{constructor(e,t,i){this.id=i,this.element=e,this.config=t,this.content=e.value||e.textContent||"",this.plugins={},this.toolbar=null,this.editorContainer=null,this.contentArea=null,this.iframe=null,this.iframeDoc=null,this.history={stack:[],currentIndex:-1,maxSize:100},this.selection=null,this.savedRange=null,this.sourceCodeMode=!1,this.sourceTextarea=null,this._defaultStyles=n.resolveStyles(t&&t.default_styles),this._pasteOpts={keepClasses:t&&Array.isArray(t.paste_keep_classes)?t.paste_keep_classes:[]},this._openPickers=new Set,this._activeReaders=new Set,this._activeResize=null,this.init()}init(){this.createEditorStructure(),this.initializePlugins(),this.createToolbar(),this.attachEventListeners(),this.restoreContent(),this.saveState()}saveSelection(){const e=this.iframe.contentWindow.getSelection();e.rangeCount>0&&(this.savedRange=e.getRangeAt(0).cloneRange())}_trackReader(e,t){this._activeReaders.add(e);const i=()=>this._activeReaders.delete(e);return e.addEventListener("load",e=>{i(),t(e)}),e.addEventListener("error",i),e.addEventListener("abort",i),e}restoreSelection(){if(this.savedRange){const e=this.iframe.contentWindow.getSelection();e.removeAllRanges(),e.addRange(this.savedRange)}}showModal(e,i,n){this.saveSelection();const o=t.createElement("div");o.className="liteeditor-modal-overlay active";const r=t.createElement("div");r.className="liteeditor-modal",r.innerHTML='\n <div class="liteeditor-modal-header">\n <h3 class="liteeditor-modal-title"></h3>\n <button class="liteeditor-modal-close" type="button">&times;</button>\n </div>\n <div class="liteeditor-modal-body"></div>\n <div class="liteeditor-modal-footer">\n <button class="liteeditor-modal-btn liteeditor-modal-btn-secondary" data-action="cancel">Cancel</button>\n <button class="liteeditor-modal-btn liteeditor-modal-btn-primary" data-action="confirm">Insert</button>\n </div>\n ',r.querySelector(".liteeditor-modal-title").textContent=String(null==e?"":e),r.querySelector(".liteeditor-modal-body").innerHTML=i,o.appendChild(r),t.body.appendChild(o);const l=()=>{o.remove();try{this.restoreSelection()}catch(e){}this.iframe.contentWindow.focus()};return r.querySelector(".liteeditor-modal-close").addEventListener("click",l),r.querySelector('[data-action="cancel"]').addEventListener("click",l),r.querySelector('[data-action="confirm"]').addEventListener("click",()=>{n(r)&&l()}),o.addEventListener("click",e=>{e.target===o&&l()}),r}showImageModal(e){const i=!!e,n=i?this._readImageFields(e):{url:"",alt:"",width:"",height:"",link:"",linkNewTab:!1},o=e=>String(null==e?"":e).replace(/&/g,"&amp;").replace(/"/g,"&quot;").replace(/</g,"&lt;").replace(/>/g,"&gt;"),r=`\n <div class="liteeditor-tabs">\n <button class="liteeditor-tab active" data-tab="url">URL</button>\n <button class="liteeditor-tab" data-tab="upload">${i?"Replace":"Upload"}</button>\n </div>\n\n <div class="liteeditor-tab-content active" data-content="url">\n <div class="liteeditor-form-group">\n <label class="liteeditor-form-label">Image URL</label>\n <input type="url" class="liteeditor-form-input" id="image-url" placeholder="https://example.com/image.jpg" value="${o(n.url)}">\n </div>\n <div class="liteeditor-form-group">\n <label class="liteeditor-form-label">Alt Text (optional)</label>\n <input type="text" class="liteeditor-form-input" id="image-alt" placeholder="Image description" value="${o(n.alt)}">\n </div>\n <div style="display: flex; gap: 12px;">\n <div class="liteeditor-form-group" style="flex: 1;">\n <label class="liteeditor-form-label">Width (px)</label>\n <input type="number" class="liteeditor-form-input" id="image-width-url" placeholder="Auto" min="1" value="${o(n.width)}">\n </div>\n <div class="liteeditor-form-group" style="flex: 1;">\n <label class="liteeditor-form-label">Height (px)</label>\n <input type="number" class="liteeditor-form-input" id="image-height-url" placeholder="Auto" min="1" value="${o(n.height)}">\n </div>\n </div>\n </div>\n\n <div class="liteeditor-tab-content" data-content="upload">\n <div class="liteeditor-file-upload" id="file-drop-area">\n <div class="liteeditor-file-upload-icon">📁</div>\n <div class="liteeditor-file-upload-text">Click to browse or drag &amp; drop image</div>\n <div class="liteeditor-file-upload-hint">Supports: JPG, PNG, GIF, WebP</div>\n <input type="file" class="liteeditor-file-input" id="image-file" accept="image/*">\n </div>\n <div class="liteeditor-image-preview" id="image-preview" style="display: none;"></div>\n <div class="liteeditor-form-group" style="margin-top: 16px;">\n <label class="liteeditor-form-label">Alt Text (optional)</label>\n <input type="text" class="liteeditor-form-input" id="image-alt-upload" placeholder="Image description" value="${o(n.alt)}">\n </div>\n <div style="display: flex; gap: 12px;">\n <div class="liteeditor-form-group" style="flex: 1;">\n <label class="liteeditor-form-label">Width (px)</label>\n <input type="number" class="liteeditor-form-input" id="image-width-upload" placeholder="Auto" min="1">\n </div>\n <div class="liteeditor-form-group" style="flex: 1;">\n <label class="liteeditor-form-label">Height (px)</label>\n <input type="number" class="liteeditor-form-input" id="image-height-upload" placeholder="Auto" min="1">\n </div>\n </div>\n </div>\n\n <div class="liteeditor-form-group" style="margin-top: 12px; border-top: 1px solid #eee; padding-top: 12px;">\n <label class="liteeditor-form-label">Link URL (optional)</label>\n <input type="url" class="liteeditor-form-input" id="image-link" placeholder="https://example.com — wrap the image in a link" value="${o(n.link)}">\n <label style="display: inline-flex; align-items: center; gap: 6px; margin-top: 6px; font-size: 13px; color: #555;">\n <input type="checkbox" id="image-link-newtab" ${n.linkNewTab?"checked":""}>\n Open in new tab\n </label>\n </div>\n `,l=this.showModal(i?"Edit Image":"Insert Image",r,t=>{const n=t.querySelector(".liteeditor-tab.active").dataset.tab,o=t.querySelector("#image-link").value.trim(),r=t.querySelector("#image-link-newtab").checked;if("url"===n){const n=t.querySelector("#image-url").value.trim(),l=t.querySelector("#image-alt").value,a=t.querySelector("#image-width-url").value,s=t.querySelector("#image-height-url").value;return n?(i?this._updateImage(e,{url:n,alt:l,width:a,height:s,link:o,linkNewTab:r}):this._insertImage({url:n,alt:l,width:a,height:s,link:o,linkNewTab:r}),!0):(alert("Please enter an image URL"),!1)}{const n=t.querySelector("#image-file"),l=t.querySelector("#image-alt-upload").value,a=t.querySelector("#image-width-upload").value,s=t.querySelector("#image-height-upload").value;if(!n.files||!n.files[0])return alert("Please select an image file"),!1;const c=n.files[0];return this._trackReader(new FileReader,t=>{const n={url:t.target.result,alt:l||c.name,width:a,height:s,link:o,linkNewTab:r};i?this._updateImage(e,n):this._insertImage(n)}).readAsDataURL(c),!0}}),a=l.querySelectorAll(".liteeditor-tab"),s=l.querySelectorAll(".liteeditor-tab-content");a.forEach(e=>{e.addEventListener("click",()=>{a.forEach(e=>e.classList.remove("active")),s.forEach(e=>e.classList.remove("active")),e.classList.add("active"),l.querySelector(`[data-content="${e.dataset.tab}"]`).classList.add("active")})});const c=l.querySelector("#file-drop-area"),d=l.querySelector("#image-file"),h=l.querySelector("#image-preview"),p=l.querySelector("#image-width-upload"),u=l.querySelector("#image-height-upload");c.addEventListener("click",()=>d.click()),d.addEventListener("change",e=>{e.target.files&&e.target.files[0]&&b(e.target.files[0])});const m=l.querySelector("#image-url"),f=l.querySelector("#image-width-url"),g=l.querySelector("#image-height-url");m.addEventListener("blur",()=>{const e=m.value;if(!e)return;const t=new Image;t.onload=function(){f.value=this.width,g.value=this.height,f.placeholder=this.width,g.placeholder=this.height},t.onerror=()=>{f.placeholder="Auto",g.placeholder="Auto"},t.src=e}),c.addEventListener("dragover",e=>{e.preventDefault(),c.classList.add("dragover")}),c.addEventListener("dragleave",()=>{c.classList.remove("dragover")}),c.addEventListener("drop",e=>{e.preventDefault(),c.classList.remove("dragover"),e.dataTransfer.files&&e.dataTransfer.files[0]&&(d.files=e.dataTransfer.files,b(e.dataTransfer.files[0]))});const b=e=>{this._trackReader(new FileReader,i=>{const n=new Image;n.onload=function(){p.value=this.width,u.value=this.height,p.placeholder=this.width,u.placeholder=this.height},n.onerror=()=>{},n.src=i.target.result,h.innerHTML="";const o=t.createElement("img");o.src=i.target.result,o.alt="Preview";const r=t.createElement("div");r.className="liteeditor-image-preview-name",r.textContent=e.name,h.appendChild(o),h.appendChild(r),h.style.display="block"}).readAsDataURL(e)}}showTableModal(){const e=this.showModal("Insert Table",'\n <div class="liteeditor-form-group">\n <label class="liteeditor-form-label">Select Table Size</label>\n <div style="text-align: center; margin-top: 16px;">\n <div class="liteeditor-table-grid" id="table-grid"></div>\n <div class="liteeditor-table-size-label" id="table-size-label">0 × 0</div>\n </div>\n </div>\n \n <div style="display: flex; gap: 16px; margin-top: 24px;">\n <div class="liteeditor-form-group" style="flex: 1;">\n <label class="liteeditor-form-label">Rows</label>\n <input type="number" class="liteeditor-form-input" id="table-rows" value="3" min="1" max="20">\n </div>\n <div class="liteeditor-form-group" style="flex: 1;">\n <label class="liteeditor-form-label">Columns</label>\n <input type="number" class="liteeditor-form-input" id="table-cols" value="3" min="1" max="20">\n </div>\n </div>\n \n <div class="liteeditor-form-group">\n <label style="display: flex; align-items: center; gap: 8px; cursor: pointer;">\n <input type="checkbox" id="table-header" checked>\n <span>Include header row</span>\n </label>\n </div>\n ',e=>{const t=parseInt(e.querySelector("#table-rows").value)||3,i=parseInt(e.querySelector("#table-cols").value)||3,n=e.querySelector("#table-header").checked,o=this._defaultStyles,r=o&&o.table?` style="${o.table}" border="1"`:"",l=o&&o.th?` style="${o.th}"`:"",a=o&&o.td?` style="${o.td}"`:"";let s=`<table${r}><tbody>`;for(let e=0;e<t;e++){s+="<tr>";for(let t=0;t<i;t++)s+=n&&0===e?`<th${l}>Header</th>`:`<td${a}>Cell</td>`;s+="</tr>"}return s+="</tbody></table>",this.execCommand("insertHTML",s),!0}),i=e.querySelector("#table-grid"),n=e.querySelector("#table-size-label"),o=e.querySelector("#table-rows"),r=e.querySelector("#table-cols");let l=3,a=3;for(let c=0;c<10;c++){const d=t.createElement("div");d.className="liteeditor-table-grid-row";for(let i=0;i<10;i++){const h=t.createElement("div");h.className="liteeditor-table-grid-cell",h.dataset.row=c+1,h.dataset.col=i+1,h.addEventListener("mouseenter",()=>{l=parseInt(h.dataset.row),a=parseInt(h.dataset.col),s(),n.textContent=`${l} × ${a}`,o.value=l,r.value=a}),h.addEventListener("click",()=>{e.querySelector('[data-action="confirm"]').click()}),d.appendChild(h)}i.appendChild(d)}function s(){i.querySelectorAll(".liteeditor-table-grid-cell").forEach(e=>{const t=parseInt(e.dataset.row),i=parseInt(e.dataset.col);t<=l&&i<=a?e.classList.add("selected"):e.classList.remove("selected")})}o.addEventListener("input",()=>{l=Math.min(Math.max(1,parseInt(o.value)||1),10),o.value=l,s(),n.textContent=`${l} × ${a}`}),r.addEventListener("input",()=>{a=Math.min(Math.max(1,parseInt(r.value)||1),10),r.value=a,s(),n.textContent=`${l} × ${a}`}),s(),n.textContent=`${l} × ${a}`}showLinkModal(){const e=this.iframe.contentWindow.getSelection().toString(),t=`\n <div class="liteeditor-form-group">\n <label class="liteeditor-form-label">URL</label>\n <input type="url" class="liteeditor-form-input" id="link-url" placeholder="https://example.com" required>\n </div>\n <div class="liteeditor-form-group">\n <label class="liteeditor-form-label">Display Text</label>\n <input type="text" class="liteeditor-form-input" id="link-text" placeholder="Link text" value="${e.replace(/&/g,"&amp;").replace(/"/g,"&quot;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}">\n </div>\n <div class="liteeditor-form-group">\n <label style="display: flex; align-items: center; gap: 8px; cursor: pointer;">\n <input type="checkbox" id="link-new-tab" checked>\n <span>Open in new tab</span>\n </label>\n </div>\n `;this.showModal("Insert Link",t,t=>{const i=t.querySelector("#link-url").value.trim(),o=t.querySelector("#link-text").value.trim()||i,r=t.querySelector("#link-new-tab").checked;if(!i)return alert("Please enter a URL"),!1;const l=n.sanitizeUrl(i);if(!l)return alert("This URL scheme is not allowed"),!1;const a=r?' target="_blank" rel="noopener noreferrer"':"";if(e&&o===e){if(this.execCommand("createLink",l),r){this.contentArea.querySelectorAll("a").forEach(e=>{e.getAttribute("href")!==l||e.getAttribute("target")||(e.setAttribute("target","_blank"),e.setAttribute("rel","noopener noreferrer"))})}}else{const e=o.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;"),t=`<a href="${s=l,s.replace(/&/g,"&amp;").replace(/"/g,"&quot;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}"${a}>${e}</a>`;this.execCommand("insertHTML",t)}var s;return!0})}showMediaModal(){const e=this.showModal("Insert Media",'\n <div class="liteeditor-tabs">\n <button class="liteeditor-tab active" data-tab="video-url">Video URL</button>\n <button class="liteeditor-tab" data-tab="embed-code">Embed Code</button>\n </div>\n\n <div class="liteeditor-tab-content active" data-content="video-url">\n <div class="liteeditor-form-group">\n <label class="liteeditor-form-label">Video URL</label>\n <input type="url" class="liteeditor-form-input" id="media-url" placeholder="https://www.youtube.com/watch?v=...">\n </div>\n <div style="display: flex; gap: 12px;">\n <div class="liteeditor-form-group" style="flex: 1;">\n <label class="liteeditor-form-label">Width (px)</label>\n <input type="number" class="liteeditor-form-input" id="media-width" value="560" min="100">\n </div>\n <div class="liteeditor-form-group" style="flex: 1;">\n <label class="liteeditor-form-label">Height (px)</label>\n <input type="number" class="liteeditor-form-input" id="media-height" value="315" min="100">\n </div>\n </div>\n <div id="media-preview" style="display: none; margin-top: 16px; border-radius: 4px; overflow: hidden;"></div>\n </div>\n\n <div class="liteeditor-tab-content" data-content="embed-code">\n <div class="liteeditor-form-group">\n <label class="liteeditor-form-label">Embed Code</label>\n <textarea class="liteeditor-form-input" id="media-embed" rows="6" placeholder="Paste your embed code here..." style="font-family: monospace; resize: vertical;"></textarea>\n </div>\n </div>\n ',e=>{if("video-url"===e.querySelector(".liteeditor-tab.active").dataset.tab){const i=e.querySelector("#media-url").value.trim(),n=e.querySelector("#media-width").value||560,o=e.querySelector("#media-height").value||315;if(!i)return alert("Please enter a video URL"),!1;const r=this.getVideoEmbedUrl(i);if(!r)return alert("Unsupported video URL. Supported: YouTube, Vimeo, Dailymotion"),!1;const l=t.createElement("div");l.style.margin="10px 0";const a=t.createElement("iframe");return a.setAttribute("src",r),a.setAttribute("width",String(parseInt(n,10)||560)),a.setAttribute("height",String(parseInt(o,10)||315)),a.setAttribute("frameborder","0"),a.setAttribute("allowfullscreen",""),a.style.maxWidth="100%",a.style.border="none",l.appendChild(a),this.execCommand("insertHTML",l.outerHTML),!0}{const t=e.querySelector("#media-embed").value.trim();if(!t)return alert("Please enter embed code"),!1;const i=this.sanitizeMediaEmbed(t);return this.execCommand("insertHTML",i),!0}}),i=e.querySelectorAll(".liteeditor-tab"),n=e.querySelectorAll(".liteeditor-tab-content");i.forEach(t=>{t.addEventListener("click",()=>{i.forEach(e=>e.classList.remove("active")),n.forEach(e=>e.classList.remove("active")),t.classList.add("active"),e.querySelector(`[data-content="${t.dataset.tab}"]`).classList.add("active")})});const o=e.querySelector("#media-url"),r=e.querySelector("#media-preview");o.addEventListener("blur",()=>{const e=o.value.trim(),i=this.getVideoEmbedUrl(e);if(i){r.innerHTML="";const e=t.createElement("iframe");e.setAttribute("src",i),e.setAttribute("width","100%"),e.setAttribute("height","200"),e.setAttribute("frameborder","0"),e.setAttribute("allowfullscreen",""),e.style.border="none",r.appendChild(e),r.style.display="block"}else r.style.display="none"})}getVideoEmbedUrl(e){let t=e.match(/(?:youtube\.com\/watch\?v=|youtu\.be\/|youtube\.com\/embed\/)([a-zA-Z0-9_-]{11})/);return t?`https://www.youtube.com/embed/${t[1]}`:(t=e.match(/vimeo\.com\/(\d+)/),t?`https://player.vimeo.com/video/${t[1]}`:(t=e.match(/dailymotion\.com\/video\/([a-zA-Z0-9]+)/),t?`https://www.dailymotion.com/embed/video/${t[1]}`:null))}sanitizeMediaEmbed(e){const i=t.createElement("div");i.innerHTML=e;const o=["IFRAME","VIDEO","AUDIO","SOURCE","EMBED","OBJECT","PARAM"],r=new Set(["IFRAME","EMBED","OBJECT"]);return i.querySelectorAll("*").forEach(e=>{if(!o.includes(e.tagName))return void e.remove();let t=!1;Array.from(e.attributes).forEach(i=>{const o=i.name.toLowerCase();if(o.startsWith("on")||"srcdoc"===o)e.removeAttribute(i.name);else if(["src","href","data"].includes(o)){const o=n.sanitizeUrl(i.value);if(!o)return void e.removeAttribute(i.name);if(r.has(e.tagName)&&!n.isAllowedEmbedHost(o))return void(t=!0);o!==i.value&&e.setAttribute(i.name,o)}}),t&&e.remove()}),i.innerHTML}showCodeSampleModal(){const e=`\n <div class="liteeditor-form-group">\n <label class="liteeditor-form-label">Language</label>\n <select class="liteeditor-form-input" id="codesample-lang">${[{value:"javascript",label:"JavaScript"},{value:"python",label:"Python"},{value:"html",label:"HTML"},{value:"css",label:"CSS"},{value:"php",label:"PHP"},{value:"java",label:"Java"},{value:"cpp",label:"C++"},{value:"ruby",label:"Ruby"},{value:"go",label:"Go"},{value:"bash",label:"Bash"},{value:"plaintext",label:"Plain Text"}].map(e=>`<option value="${e.value}">${e.label}</option>`).join("")}</select>\n </div>\n <div class="liteeditor-form-group">\n <label class="liteeditor-form-label">Code</label>\n <textarea class="liteeditor-form-input" id="codesample-code" rows="10" placeholder="Paste your code here..." style="font-family: 'Courier New', Consolas, Monaco, monospace; font-size: 13px; line-height: 1.5; tab-size: 4; resize: vertical;"></textarea>\n </div>\n `;this.showModal("Insert Code Sample",e,e=>{const t=e.querySelector("#codesample-lang").value,i=e.querySelector("#codesample-code").value;if(!i.trim())return alert("Please enter some code"),!1;const n=i.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;"),o=this._defaultStyles,r=`<pre${o&&o.pre?` style="${o.pre}"`:""}><code class="language-${t}">${n}</code></pre><p><br></p>`;return this.execCommand("insertHTML",r),!0})}showAnchorModal(){this.showModal("Insert Anchor",'\n <div class="liteeditor-form-group">\n <label class="liteeditor-form-label">Anchor Name / ID</label>\n <input type="text" class="liteeditor-form-input" id="anchor-name" placeholder="e.g., section-intro">\n <div style="margin-top: 6px; font-size: 12px; color: #666;">\n Must start with a letter. Only letters, numbers, hyphens, and underscores allowed.\n </div>\n </div>\n ',e=>{let t=e.querySelector("#anchor-name").value.trim();if(!t)return alert("Please enter an anchor name"),!1;if(t=t.replace(/[^a-zA-Z0-9_-]/g,"-").replace(/^[^a-zA-Z]+/,""),!t)return alert("Invalid anchor name"),!1;const i=`<a id="${t}" class="liteeditor-anchor"></a>`;return this.execCommand("insertHTML",i),!0})}showSearchReplace(){if(this.searchPanel)return void this.searchPanel.querySelector("#search-find-input").focus();const e=t.createElement("div");e.className="liteeditor-search-panel",e.innerHTML='\n <div class="liteeditor-search-row">\n <input type="text" class="liteeditor-form-input" id="search-find-input" placeholder="Find...">\n <span class="liteeditor-search-count" id="search-count">0 of 0</span>\n <button type="button" class="liteeditor-search-btn" id="search-prev" title="Previous">&#9650;</button>\n <button type="button" class="liteeditor-search-btn" id="search-next" title="Next">&#9660;</button>\n <button type="button" class="liteeditor-search-btn liteeditor-search-close" id="search-close" title="Close">&times;</button>\n </div>\n <div class="liteeditor-search-row">\n <input type="text" class="liteeditor-form-input" id="search-replace-input" placeholder="Replace with...">\n <button type="button" class="liteeditor-search-btn" id="search-replace" title="Replace">Replace</button>\n <button type="button" class="liteeditor-search-btn" id="search-replace-all" title="Replace All">All</button>\n </div>\n ',this.toolbar.parentNode.insertBefore(e,this.toolbar.nextSibling),this.searchPanel=e;let i=[],n=-1;const o=e.querySelector("#search-find-input"),r=e.querySelector("#search-replace-input"),l=e.querySelector("#search-count"),a=()=>{this.contentArea.querySelectorAll("mark.liteeditor-search-highlight").forEach(e=>{const t=e.parentNode;t.replaceChild(this.iframeDoc.createTextNode(e.textContent),e),t.normalize()}),i=[],n=-1},s=()=>{const e=this._markGroups||[];i.forEach(e=>e.classList.remove("current")),e.forEach((e,t)=>{t===n&&e.forEach(e=>e.classList.add("current"))}),l.textContent=e.length>0?`${n+1} of ${e.length}`:"0 of 0",n>=0&&e[n]&&e[n][0]&&e[n][0].scrollIntoView({block:"center",behavior:"smooth"})},c=()=>{const e=this._markGroups||[];0!==e.length&&(n=(n+1)%e.length,s())},d=()=>{const e=this._markGroups||[];0!==e.length&&(n=(n-1+e.length)%e.length,s())},h=(e,t)=>{if(!e.length)return;const i=e[0],n=this.iframeDoc.createTextNode(t);i.parentNode.replaceChild(n,i);for(let t=1;t<e.length;t++)e[t].parentNode&&e[t].remove();n.parentNode&&n.parentNode.normalize()},p=()=>{a(),e.remove(),this.searchPanel=null,this._closeSearchPanel=null};this._closeSearchPanel=p,o.addEventListener("input",()=>{a();const e=o.value;if(!e)return void(l.textContent="0 of 0");const t=this.iframeDoc.createTreeWalker(this.contentArea,NodeFilter.SHOW_TEXT,{acceptNode:e=>{if(!e.nodeValue)return NodeFilter.FILTER_REJECT;const t=e.parentNode;return t&&t.closest&&t.closest(".liteeditor-image-resizer")?NodeFilter.FILTER_REJECT:NodeFilter.FILTER_ACCEPT}});let r="";const c=[];for(;t.nextNode();){const e=t.currentNode;c.push({node:e,start:r.length,end:r.length+e.nodeValue.length}),r+=e.nodeValue}const d=e.toLowerCase(),h=r.toLowerCase(),p=[];let u=0;for(;u<=h.length-d.length;){const t=h.indexOf(d,u);if(-1===t)break;p.push({start:t,end:t+e.length}),u=t+e.length}const m=e=>{for(let t=0;t<c.length;t++)if(e>=c[t].start&&e<=c[t].end)return{node:c[t].node,offset:e-c[t].start};return null};for(let e=p.length-1;e>=0;e--){const t=p[e],i=m(t.start),n=m(t.end);if(!i||!n)continue;const o=this.iframeDoc.createRange();try{o.setStart(i.node,i.offset),o.setEnd(n.node,n.offset)}catch(e){continue}this.wrapRangeInMark(o)}i=Array.from(this.contentArea.querySelectorAll("mark.liteeditor-search-highlight")),this._markGroups=this.groupMarks(i),n=this._markGroups.length>0?0:-1,s()}),e.querySelector("#search-prev").addEventListener("click",d),e.querySelector("#search-next").addEventListener("click",c),e.querySelector("#search-replace").addEventListener("click",()=>{const e=this._markGroups||[];n<0||!e[n]||(h(e[n],r.value),e.splice(n,1),n>=e.length&&(n=0),0===e.length&&(n=-1),i=Array.from(this.contentArea.querySelectorAll("mark.liteeditor-search-highlight")),s(),this.saveState(),this.syncContent())}),e.querySelector("#search-replace-all").addEventListener("click",()=>{const e=this._markGroups||[];if(0===e.length)return;const t=r.value;e.forEach(e=>h(e,t)),this._markGroups=[],i=[],n=-1,l.textContent="0 of 0",this.saveState(),this.syncContent()}),e.querySelector("#search-close").addEventListener("click",p),o.addEventListener("keydown",e=>{"Enter"===e.key&&(e.preventDefault(),e.shiftKey?d():c()),"Escape"===e.key&&p()}),r.addEventListener("keydown",e=>{"Escape"===e.key&&p()}),o.focus()}createEditorStructure(){this.element.style.display="none",this.editorContainer=t.createElement("div"),this.editorContainer.className="liteeditor-container",this.editorContainer.id=this.id+"-container",this.element.parentNode.insertBefore(this.editorContainer,this.element),this.config.menubar&&this.createMenuBar(),this.toolbar=t.createElement("div"),this.toolbar.className="liteeditor-toolbar",this.editorContainer.appendChild(this.toolbar);const e=t.createElement("div");e.className="liteeditor-editor-wrapper",this.iframe=t.createElement("iframe"),this.iframe.className="liteeditor-content",this.iframe.setAttribute("frameborder","0");const i=this.config.height||150;this.iframe.style.height=i+"px",e.appendChild(this.iframe),this.editorContainer.appendChild(e),this.iframeDoc=this.iframe.contentDocument||this.iframe.contentWindow.document,this.iframeDoc.open(),this.iframeDoc.write('\n <!DOCTYPE html>\n <html>\n <head>\n <style>\n * { margin: 0; padding: 0; box-sizing: border-box; }\n html, body {\n height: 100%;\n }\n body {\n font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;\n font-size: 14px;\n line-height: 1.6;\n color: #333;\n padding: 12px;\n min-height: 100%;\n word-wrap: break-word;\n }\n p { margin: 0 0 10px 0; }\n h1, h2, h3, h4, h5, h6 { margin: 15px 0 10px 0; font-weight: 600; }\n h1 { font-size: 2em; }\n h2 { font-size: 1.5em; }\n h3 { font-size: 1.17em; }\n h4 { font-size: 1em; }\n h5 { font-size: 0.83em; }\n h6 { font-size: 0.67em; }\n ul, ol { margin: 10px 0; padding-left: 40px; }\n li { margin: 5px 0; }\n a { color: #0066cc; text-decoration: underline; }\n img { max-width: 100%; height: auto; }\n table { border-collapse: collapse; width: 100%; margin: 10px 0; }\n table td, table th { border: 1px solid #ddd; padding: 8px; }\n table th { background-color: #f2f2f2; color: #000; font-weight: bold; }\n blockquote { margin: 10px 0; padding: 10px 20px; border-left: 4px solid #ccc; background: #f9f9f9; }\n code { background: #f4f4f4; padding: 2px 6px; border-radius: 3px; font-family: monospace; }\n pre { background: #f4f4f4; padding: 10px; border-radius: 5px; overflow-x: auto; margin: 10px 0; }\n pre code { padding: 0; background: none; }\n hr { border: none; border-top: 1px solid #ddd; margin: 15px 0; }\n .text-left { text-align: left; }\n .text-center { text-align: center; }\n .text-right { text-align: right; }\n .text-justify { text-align: justify; }\n \n /* Image Resize Styles */\n .liteeditor-image-resizer {\n position: relative;\n display: inline-block;\n max-width: 100%;\n margin: 5px;\n }\n .liteeditor-image-resizer img {\n display: block;\n max-width: 100%;\n }\n .liteeditor-image-resizer img[style*="width"] {\n max-width: none;\n }\n .liteeditor-image-resizer.selected {\n outline: 2px solid #667eea;\n outline-offset: 2px;\n }\n .liteeditor-resize-handle {\n position: absolute;\n width: 10px;\n height: 10px;\n background: #667eea;\n border: 2px solid #fff;\n border-radius: 50%;\n display: none;\n z-index: 100;\n }\n .liteeditor-image-resizer.selected .liteeditor-resize-handle {\n display: block;\n }\n .liteeditor-resize-handle.nw { top: -5px; left: -5px; cursor: nw-resize; }\n .liteeditor-resize-handle.ne { top: -5px; right: -5px; cursor: ne-resize; }\n .liteeditor-resize-handle.sw { bottom: -5px; left: -5px; cursor: sw-resize; }\n .liteeditor-resize-handle.se { bottom: -5px; right: -5px; cursor: se-resize; }\n .liteeditor-resize-handle.n { top: -5px; left: 50%; transform: translateX(-50%); cursor: n-resize; }\n .liteeditor-resize-handle.s { bottom: -5px; left: 50%; transform: translateX(-50%); cursor: s-resize; }\n .liteeditor-resize-handle.e { top: 50%; right: -5px; transform: translateY(-50%); cursor: e-resize; }\n .liteeditor-resize-handle.w { top: 50%; left: -5px; transform: translateY(-50%); cursor: w-resize; }\n .liteeditor-image-info {\n position: absolute;\n top: -30px;\n left: 50%;\n transform: translateX(-50%);\n background: rgba(0, 0, 0, 0.8);\n color: #fff;\n padding: 4px 8px;\n border-radius: 4px;\n font-size: 11px;\n white-space: nowrap;\n pointer-events: none;\n display: none;\n }\n .liteeditor-image-resizer.selected .liteeditor-image-info {\n display: block;\n }\n\n /* Floating image toolbar (Edit · Replace · Align · Link · Delete) */\n .liteeditor-image-toolbar {\n position: absolute;\n bottom: calc(100% + 8px);\n left: 50%;\n transform: translateX(-50%);\n display: none;\n background: #2d3748;\n color: #fff;\n padding: 4px;\n border-radius: 6px;\n white-space: nowrap;\n z-index: 200;\n box-shadow: 0 2px 8px rgba(0,0,0,0.2);\n user-select: none;\n font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;\n }\n .liteeditor-image-resizer.selected .liteeditor-image-toolbar {\n display: inline-flex;\n gap: 1px;\n align-items: center;\n }\n .liteeditor-img-toolbar-btn {\n background: transparent;\n color: inherit;\n border: 0;\n width: 30px;\n height: 28px;\n padding: 0;\n cursor: pointer;\n border-radius: 3px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n font-size: 14px;\n line-height: 1;\n }\n .liteeditor-img-toolbar-btn:hover {\n background: rgba(255,255,255,0.18);\n }\n .liteeditor-img-toolbar-sep {\n display: inline-block;\n width: 1px;\n height: 18px;\n background: rgba(255,255,255,0.25);\n margin: 0 3px;\n }\n\n /* Inline link-edit popover under the image */\n .liteeditor-image-link-popover {\n position: absolute;\n top: calc(100% + 8px);\n left: 0;\n background: #fff;\n border: 1px solid #ddd;\n border-radius: 6px;\n padding: 6px;\n box-shadow: 0 4px 12px rgba(0,0,0,0.12);\n z-index: 201;\n display: flex;\n gap: 6px;\n align-items: center;\n user-select: text;\n white-space: nowrap;\n font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;\n font-size: 13px;\n }\n .liteeditor-img-link-input {\n border: 1px solid #ddd;\n outline: 0;\n padding: 6px 8px;\n min-width: 260px;\n font-size: 13px;\n border-radius: 3px;\n }\n .liteeditor-img-link-input:focus {\n border-color: #667eea;\n }\n .liteeditor-img-link-newtab {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n font-size: 12px;\n color: #555;\n cursor: pointer;\n }\n .liteeditor-img-link-save {\n padding: 5px 12px;\n background: #667eea;\n color: #fff;\n border: 0;\n border-radius: 3px;\n cursor: pointer;\n font-size: 13px;\n }\n .liteeditor-img-link-save:hover {\n background: #5563d6;\n }\n .liteeditor-img-link-remove {\n padding: 5px 10px;\n background: transparent;\n color: #c00;\n border: 0;\n cursor: pointer;\n font-size: 13px;\n }\n .liteeditor-img-link-remove:hover {\n background: #fef2f2;\n border-radius: 3px;\n }\n\n /* Table editor chrome (wrapper + floating toolbar) */\n .liteeditor-table-wrapper {\n position: relative;\n display: block;\n /* Reserve 40px above so the floating toolbar always\n sits above the table without clipping into prior\n content or the body padding. Wrapper is editor\n chrome — stripped on save — so this added margin\n never reaches the rendered page. */\n margin: 40px 0 10px 0;\n /* Shrink the wrapper to the table\'s actual rendered\n width so the resize handles + floating toolbar\n (which are positioned at wrapper edges) always\n align with the table edge, no matter how the\n user has sized or aligned the table. */\n width: fit-content;\n /* But never overflow the editor\'s content area. */\n max-width: 100%;\n }\n .liteeditor-table-toolbar {\n position: absolute;\n top: -34px;\n left: 0;\n display: none;\n background: #2d3748;\n color: #fff;\n padding: 3px;\n border-radius: 6px;\n white-space: nowrap;\n z-index: 200;\n box-shadow: 0 2px 8px rgba(0,0,0,0.2);\n user-select: none;\n font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;\n }\n .liteeditor-table-wrapper.active .liteeditor-table-toolbar {\n display: inline-flex;\n gap: 1px;\n align-items: center;\n }\n .liteeditor-tbl-toolbar-btn {\n background: transparent;\n color: inherit;\n border: 0;\n width: 30px;\n height: 28px;\n padding: 0;\n cursor: pointer;\n border-radius: 3px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n font-size: 14px;\n line-height: 1;\n }\n .liteeditor-tbl-toolbar-btn:hover {\n background: rgba(255,255,255,0.18);\n }\n .liteeditor-tbl-toolbar-btn.active {\n background: rgba(102, 126, 234, 0.5);\n }\n .liteeditor-tbl-toolbar-sep {\n display: inline-block;\n width: 1px;\n height: 18px;\n background: rgba(255,255,255,0.25);\n margin: 0 3px;\n }\n /* Inside the wrapper only — collapse the table\'s normal\n vertical margin so the wrapper edge sits flush with\n the table edge. Resize handles are positioned\n relative to the wrapper, so they appear at the\n table\'s border instead of floating in margin space.\n The wrapper is stripped on save, so the table\'s\n original inline margin is preserved in the output. */\n .liteeditor-table-wrapper > table {\n margin-top: 0 !important;\n margin-bottom: 0 !important;\n }\n /* Eight resize handles on the wrapper, visible only when\n the table is active (cursor inside a cell).\n Corners → resize both width and height.\n E / W → width only (most common table edit).\n N / S → height only. */\n .liteeditor-table-resize-handle {\n position: absolute;\n background: #667eea;\n border: 2px solid #fff;\n z-index: 199;\n display: none;\n box-sizing: border-box;\n }\n .liteeditor-table-wrapper.active .liteeditor-table-resize-handle { display: block; }\n /* Corner handles — 10×10 circles. */\n .liteeditor-table-resize-handle.nw,\n .liteeditor-table-resize-handle.ne,\n .liteeditor-table-resize-handle.sw,\n .liteeditor-table-resize-handle.se {\n width: 10px;\n height: 10px;\n border-radius: 50%;\n }\n .liteeditor-table-resize-handle.nw { top: -5px; left: -5px; cursor: nwse-resize; }\n .liteeditor-table-resize-handle.ne { top: -5px; right: -5px; cursor: nesw-resize; }\n .liteeditor-table-resize-handle.sw { bottom: -5px; left: -5px; cursor: nesw-resize; }\n .liteeditor-table-resize-handle.se { bottom: -5px; right: -5px; cursor: nwse-resize; }\n /* Edge handles — bar-shaped so the affordance is clear:\n horizontal bar for vertical drag (N / S), vertical\n bar for horizontal drag (E / W). */\n .liteeditor-table-resize-handle.n,\n .liteeditor-table-resize-handle.s {\n width: 22px;\n height: 6px;\n left: 50%;\n margin-left: -11px;\n border-radius: 3px;\n cursor: ns-resize;\n }\n .liteeditor-table-resize-handle.n { top: -3px; }\n .liteeditor-table-resize-handle.s { bottom: -3px; }\n .liteeditor-table-resize-handle.e,\n .liteeditor-table-resize-handle.w {\n width: 6px;\n height: 22px;\n top: 50%;\n margin-top: -11px;\n border-radius: 3px;\n cursor: ew-resize;\n }\n .liteeditor-table-resize-handle.e { right: -3px; }\n .liteeditor-table-resize-handle.w { left: -3px; }\n\n /* Anchor marker */\n .liteeditor-anchor {\n display: inline-block;\n width: 16px; height: 16px;\n background: #667eea;\n border-radius: 2px;\n position: relative;\n vertical-align: middle;\n cursor: default;\n }\n .liteeditor-anchor::before {\n content: \'\\2693\';\n position: absolute;\n top: 50%; left: 50%;\n transform: translate(-50%, -50%);\n font-size: 11px; color: #fff; line-height: 1;\n }\n .liteeditor-anchor::after {\n content: attr(id);\n position: absolute;\n bottom: 100%; left: 50%;\n transform: translateX(-50%);\n background: rgba(0,0,0,0.8);\n color: #fff; padding: 2px 6px;\n border-radius: 3px; font-size: 10px;\n white-space: nowrap;\n display: none; pointer-events: none;\n }\n .liteeditor-anchor:hover::after { display: block; }\n\n /* Search highlights */\n mark.liteeditor-search-highlight {\n background: #ffeb3b;\n color: inherit;\n padding: 0;\n border-radius: 2px;\n }\n mark.liteeditor-search-highlight.current {\n background: #ff9800;\n color: #fff;\n }\n </style>\n </head>\n <body contenteditable="true"></body>\n </html>\n '),this.iframeDoc.close(),this.contentArea=this.iframeDoc.body,this._injectInstanceStyles(),this.resizeHandle=t.createElement("div"),this.resizeHandle.className="liteeditor-resize-handle-bar",this.resizeHandle.innerHTML='<span class="liteeditor-resize-icon">⋮⋮⋮</span>',this.editorContainer.appendChild(this.resizeHandle),this.setupEditorResize()}initializePlugins(){const e=(this.config.plugins||"").trim();("all"===e||"full"===e?Object.keys(a):e?e.split(/\s+/):[]).forEach(e=>{const t=a[e];t&&(this.plugins[e]=new t(this))})}static FULL_TOOLBAR="undo redo | blocks fontfamily fontsize | bold italic underline strikethrough | forecolor backcolor | link image media table | align lineheight | numlist bullist indent outdent | emoticons charmap | removeformat | sourcecode | searchreplace codesample visualblocks anchor";createToolbar(){let e=this.config.toolbar||"bold italic underline";"full"!==e&&"all"!==e||(e=o.FULL_TOOLBAR);this.parseToolbarConfig(e).forEach(e=>{if("|"===e){const e=t.createElement("div");e.className="liteeditor-separator",this.toolbar.appendChild(e)}else this.createToolbarButton(e)})}parseToolbarConfig(e){return e.split(/\s+/).filter(e=>e)}createToolbarButton(e){const i=l[e];if(!i)return;const n=t.createElement("button");if(n.type="button",n.className="liteeditor-btn",n.title=i.title,n.dataset.command=e,"dropdown"===i.type){if(n.classList.add("liteeditor-dropdown-btn"),i.showValue){n.classList.add("liteeditor-value-btn");const e=t.createElement("span");e.className="liteeditor-btn-label",e.textContent=i.defaultLabel||i.title,n.appendChild(e)}else n.innerHTML=i.icon;const o=this.createDropdown(e,i.options,i.dropdownOpts||{}),r=t.createElement("div");r.className="liteeditor-dropdown-wrapper",r.appendChild(n),r.appendChild(o),this.toolbar.appendChild(r),n.addEventListener("click",e=>{e.stopPropagation();this.toolbar.querySelectorAll(".liteeditor-dropdown").forEach(e=>{e!==o&&e.classList.remove("active")});const t=!o.classList.contains("active");o.classList.toggle("active"),t&&o._refreshActive&&o._refreshActive()})}else if("dialog"===i.type)n.innerHTML=i.icon,n.addEventListener("click",()=>{i.action(this)}),this.toolbar.appendChild(n);else if("split"===i.type){n.classList.add("liteeditor-split-main"),n.innerHTML=i.icon,n.addEventListener("click",()=>{this.execCommand(e,i.value)});const o=t.createElement("button");o.type="button",o.className="liteeditor-btn liteeditor-split-arrow",o.title=i.title+" options",o.dataset.command=e+"-arrow",o.innerHTML='<span class="liteeditor-split-chevron">▾</span>';const r=this.createDropdown(e,i.options,i.dropdownOpts||{});r.classList.add("liteeditor-split-dropdown");const l=t.createElement("div");l.className="liteeditor-split-wrapper liteeditor-dropdown-wrapper",l.appendChild(n),l.appendChild(o),l.appendChild(r),this.toolbar.appendChild(l),o.addEventListener("click",e=>{e.stopPropagation();this.toolbar.querySelectorAll(".liteeditor-dropdown").forEach(e=>{e!==r&&e.classList.remove("active")});const t=!r.classList.contains("active");r.classList.toggle("active"),t&&r._refreshActive&&r._refreshActive()})}else n.innerHTML=i.icon,n.addEventListener("click",()=>{this.execCommand(e,i.value)}),this.toolbar.appendChild(n)}createDropdown(e,i,n={}){const o=t.createElement("div");o.className="liteeditor-dropdown","grid"===n.variant&&o.classList.add("liteeditor-dropdown-grid");const r=n.detectActive;if(i.forEach(i=>{const n=t.createElement("div");n.className="liteeditor-dropdown-item",i.key&&(n.dataset.key=i.key),i.label&&(n.dataset.label=i.label),i.html?n.innerHTML=i.html:i.icon?n.innerHTML=`<span class="liteeditor-dropdown-item-icon">${i.icon}</span><span class="liteeditor-dropdown-item-label">${i.label}</span>`:n.textContent=i.label,n.addEventListener("click",()=>{i.action?i.action(this):this.execCommand(e,i.value),o.classList.remove("active")}),o.appendChild(n)}),n.showActiveLabel){const e=t.createElement("div");e.className="liteeditor-dropdown-active-label",o.appendChild(e)}return o._refreshActive=()=>{if(!r)return;const e=r(this);let t=null;o.querySelectorAll(".liteeditor-dropdown-item").forEach(i=>{const n=i.dataset.key===e;i.classList.toggle("active",n),n&&(t=i.dataset.label||i.textContent.trim())});const i=o.querySelector(".liteeditor-dropdown-active-label");i&&(i.textContent=t||"")},o}_menubarModel(){const t=l,i=e=>e.map(e=>({label:e.label,action:e.action})),n=e=>r.map(t=>({color:t,action:i=>i.execCommand(e,t)})),o=e=>t=>{const i=t._menuTableCell();i&&e(t,i)},a=e=>!e._menuTableCell();return{file:{label:"File",items:[{label:"New document",action:e=>e.menuNewDocument()},"|",{label:"Preview",action:e=>e.showPreview()},{label:"Print…",action:e=>e.printContent()}]},edit:{label:"Edit",items:[{label:"Undo",shortcut:"Ctrl+Z",action:e=>e.undo(),disabled:e=>e.history.currentIndex<=0},{label:"Redo",shortcut:"Ctrl+Y",action:e=>e.redo(),disabled:e=>e.history.currentIndex>=e.history.stack.length-1},"|",{label:"Cut",shortcut:"Ctrl+X",action:e=>e.execCommand("cut")},{label:"Copy",shortcut:"Ctrl+C",action:e=>e.execCommand("copy")},{label:"Paste",shortcut:"Ctrl+V",action:e=>e.menuPaste()},{label:"Select all",shortcut:"Ctrl+A",action:e=>e.execCommand("selectAll")},"|",{label:"Search & Replace…",shortcut:"Ctrl+F",action:e=>e.showSearchReplace()}]},view:{label:"View",items:[{label:"Source code",action:e=>e.toggleSourceCode(),checked:e=>!!e.sourceCodeMode},{label:"Visual blocks",action:t.visualblocks.action,checked:e=>e.contentArea.classList.contains("liteeditor-visualblocks")}]},insert:{label:"Insert",items:[{label:"Link…",action:e=>e.showLinkModal()},{label:"Image…",action:e=>e.showImageModal()},{label:"Media…",action:e=>e.showMediaModal()},{label:"Table…",action:e=>e.showTableModal()},{label:"Code sample…",action:e=>e.showCodeSampleModal()},{label:"Special character",grid:!0,items:i(t.charmap.options)},{label:"Emojis",grid:!0,items:i(t.emoticons.options)},{label:"Anchor…",action:e=>e.showAnchorModal()},"|",{label:"Horizontal line",action:e=>e.execCommand("insertHorizontalRule")}]},format:{label:"Format",items:[{label:"Bold",shortcut:"Ctrl+B",action:e=>e.execCommand("bold")},{label:"Italic",shortcut:"Ctrl+I",action:e=>e.execCommand("italic")},{label:"Underline",shortcut:"Ctrl+U",action:e=>e.execCommand("underline")},{label:"Strikethrough",action:e=>e.execCommand("strikethrough")},"|",{label:"Blocks",items:i(t.blocks.options)},{label:"Fonts",items:i(t.fontfamily.options)},{label:"Font sizes",items:i(t.fontsize.options)},{label:"Align",items:["left","center","right","justify"].map(e=>({label:e[0].toUpperCase()+e.slice(1),action:t=>t.setAlignment(e)}))},{label:"Line height",items:["1","1.15","1.5","1.75","2","2.5","3"].map(e=>({label:e,action:t=>t.setLineHeight(e)}))},"|",{label:"Text color",grid:!0,items:n("foreColor")},{label:"Background color",grid:!0,items:n("hiliteColor")},"|",{label:"Bullet list",action:e=>e.execCommand("bullist")},{label:"Numbered list",action:e=>e.execCommand("numlist")},{label:"Indent",action:e=>e.execCommand("indent")},{label:"Outdent",action:e=>e.execCommand("outdent")},"|",{label:"Clear formatting",action:e=>e.removeFormatting()}]},tools:{label:"Tools",items:[{label:"Source code",action:e=>e.toggleSourceCode(),checked:e=>!!e.sourceCodeMode},{label:"Word count",action:e=>e.showWordCount()}]},table:{label:"Table",items:[{label:"Insert table…",action:e=>e.showTableModal()},"|",{label:"Insert row above",disabled:a,action:o((e,t)=>e._tableInsertRowAbove(t))},{label:"Insert row below",disabled:a,action:o((e,t)=>e._tableInsertRowBelow(t))},{label:"Delete row",disabled:a,action:o((e,t)=>e._tableDeleteRow(t))},"|",{label:"Insert column left",disabled:a,action:o((e,t)=>e._tableInsertColumnLeft(t))},{label:"Insert column right",disabled:a,action:o((e,t)=>e._tableInsertColumnRight(t))},{label:"Delete column",disabled:a,action:o((e,t)=>e._tableDeleteColumn(t))},"|",{label:"Table properties…",disabled:a,action:o((e,t)=>e._showTablePropertiesModal(t.closest("table")))},{label:"Delete table",disabled:a,action:o((e,t)=>e._tableDeleteTable(t))}]},help:{label:"Help",items:[{label:"Keyboard shortcuts…",action:e=>e.showHelpDialog()},{label:"Version",action:t=>t._infoModal("LiteEditor",'<p style="margin:0">LiteEditor v'+(e.liteeditor&&e.liteeditor.version||"")+"</p>")}]}}}createMenuBar(){const e=!0===this.config.menubar?"file edit view insert format tools table help":String(this.config.menubar),i=this._menubarModel(),n=e.split(/\s+/).filter(e=>i[e]);if(!n.length)return;this._menus=i,this._menuPanels={},this._openMenuKey=null;const o=t.createElement("div");o.className="liteeditor-menubar",o.setAttribute("role","menubar"),n.forEach(e=>{const n=t.createElement("button");n.type="button",n.className="liteeditor-menu-btn",n.dataset.menu=e,n.setAttribute("role","menuitem"),n.textContent=i[e].label,o.appendChild(n)}),this.menubar=o,this.editorContainer.appendChild(o),o.addEventListener("click",e=>this._onMenubarClick(e)),o.addEventListener("mouseover",e=>this._onMenubarHover(e)),o.addEventListener("keydown",e=>this._onMenubarKeydown(e))}_menuItemForPath(e){const t=e.split(":");let i=this._menus[t[0]]&&this._menus[t[0]].items,n=null;for(let e=1;i&&e<t.length;e++)n=i[+t[e]],i=n&&n.items;return n}_buildMenuItemEl(e,i){if("|"===e){const e=t.createElement("div");return e.className="liteeditor-menu-sep",e}const n=t.createElement("div");if(n.className="liteeditor-menu-item",n.dataset.path=i,n.setAttribute("role","menuitem"),n.tabIndex=-1,e.color)return n.classList.add("liteeditor-menu-swatch"),n.style.background=e.color,n.title=e.color,n;const o=t.createElement("span");if(o.className="liteeditor-menu-label",o.textContent=e.label,n.appendChild(o),e.shortcut){const i=t.createElement("span");i.className="liteeditor-menu-shortcut",i.textContent=e.shortcut,n.appendChild(i)}return e.items&&n.classList.add("liteeditor-menu-has-sub"),n}_menuPanel(e){let i=this._menuPanels[e];if(i)return i;i=t.createElement("div"),i.className="liteeditor-menu-panel",i.setAttribute("role","menu"),this._menus[e].items.forEach((t,n)=>{i.appendChild(this._buildMenuItemEl(t,e+":"+n))});const n=this.menubar.querySelector(`[data-menu="${e}"]`);return i.style.left=n.offsetLeft+"px",this.menubar.appendChild(i),this._menuPanels[e]=i,i}_openSubmenu(i){let n=i._subPanel;if(!n){const e=this._menuItemForPath(i.dataset.path);if(!e||!e.items)return;n=t.createElement("div"),n.className="liteeditor-menu-panel liteeditor-menu-subpanel",e.grid&&n.classList.add("liteeditor-menu-grid"),n.setAttribute("role","menu"),e.items.forEach((e,t)=>{n.appendChild(this._buildMenuItemEl(e,i.dataset.path+":"+t))}),i.appendChild(n),i._subPanel=n}this._refreshMenuState(n),n.classList.remove("liteeditor-menu-subpanel--left"),n.classList.add("active"),n.getBoundingClientRect().right>(e.innerWidth||0)&&n.classList.add("liteeditor-menu-subpanel--left")}_closeSubmenus(e,t){e.querySelectorAll(".liteeditor-menu-subpanel.active").forEach(e=>{t&&(e.contains(t)||t.contains(e))||e.classList.remove("active")})}_openMenu(e){if(this._openMenuKey===e)return;this._closeMenus();const t=this._menuPanel(e);this._refreshMenuState(t),t.classList.add("active");const i=this.menubar.querySelector(`[data-menu="${e}"]`);i&&i.classList.add("active"),this._openMenuKey=e}_closeMenus(){if(!this._openMenuKey)return;const e=this._menuPanels[this._openMenuKey];e&&(this._closeSubmenus(e),e.classList.remove("active")),this.menubar.querySelectorAll(".liteeditor-menu-btn.active").forEach(e=>e.classList.remove("active")),this._openMenuKey=null}_refreshMenuState(e){e.querySelectorAll(":scope > .liteeditor-menu-item").forEach(e=>{const t=this._menuItemForPath(e.dataset.path);t&&(t.disabled&&e.classList.toggle("disabled",!!t.disabled(this)),t.checked&&e.classList.toggle("checked",!!t.checked(this)))})}_onMenubarClick(e){const t=e.target.closest(".liteeditor-menu-btn");if(t)return e.stopPropagation(),void(this._openMenuKey===t.dataset.menu?this._closeMenus():this._openMenu(t.dataset.menu));const i=e.target.closest(".liteeditor-menu-item");if(!i||i.classList.contains("disabled"))return;const n=this._menuItemForPath(i.dataset.path);n&&(n.items?this._openSubmenu(i):(this._closeMenus(),n.action&&n.action(this)))}_onMenubarHover(e){const t=e.target.closest(".liteeditor-menu-btn");if(t)return void(this._openMenuKey&&t.dataset.menu!==this._openMenuKey&&this._openMenu(t.dataset.menu));if(!this._openMenuKey)return;const i=e.target.closest(".liteeditor-menu-item"),n=this._menuPanels[this._openMenuKey];i&&n&&n.contains(i)&&(this._closeSubmenus(n,i),i.classList.contains("liteeditor-menu-has-sub")&&this._openSubmenu(i))}_onMenubarKeydown(e){if("Escape"===e.key)return void this._closeMenus();if(!this._openMenuKey)return void("ArrowDown"!==e.key&&"Enter"!==e.key||!e.target.classList.contains("liteeditor-menu-btn")||(e.preventDefault(),this._openMenu(e.target.dataset.menu)));const i=this._menuPanels[this._openMenuKey],n=Array.from(i.querySelectorAll(".liteeditor-menu-item:not(.disabled)")).filter(e=>null!==e.offsetParent);if(!n.length)return;const o=n.indexOf(t.activeElement);if("ArrowDown"===e.key||"ArrowUp"===e.key){e.preventDefault();("ArrowDown"===e.key?n[(o+1)%n.length]:n[(o-1+n.length)%n.length]).focus()}else if("Enter"===e.key&&o>=0)e.preventDefault(),n[o].click();else if("ArrowRight"===e.key&&o>=0&&n[o].classList.contains("liteeditor-menu-has-sub"))e.preventDefault(),this._openSubmenu(n[o]);else if("ArrowLeft"===e.key){const t=e.target.closest&&e.target.closest(".liteeditor-menu-subpanel");t&&(e.preventDefault(),t.classList.remove("active"))}}_infoModal(e,t){const i=this.showModal(e,t,()=>!0),n=i.querySelector('[data-action="cancel"]');return n&&(n.style.display="none"),i.querySelector('[data-action="confirm"]').textContent="Close",i}menuNewDocument(){((this.contentArea.textContent||"").trim()||this.contentArea.querySelector("img, table, hr"))&&!e.confirm("Start a new document? Current content will be replaced.")||(this.setContent("<p><br></p>"),this.saveState())}menuPaste(){const e=()=>this._infoModal("Paste",'<p style="margin:0">Your browser blocks pasting from a menu. Use <strong>Ctrl+V</strong> (⌘V on Mac) instead.</p>');navigator.clipboard&&navigator.clipboard.readText?navigator.clipboard.readText().then(e=>{e&&this.execCommand("insertText",e)}).catch(e):e()}_previewDocHTML(){return'<!doctype html><html><head><meta charset="utf-8"><title>Preview</title><style>body{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;font-size:14px;line-height:1.6;color:#333;padding:16px;}img{max-width:100%;height:auto;}a{color:#0066cc;}</style></head><body>'+this.getContent()+"</body></html>"}showPreview(){const e=this._infoModal("Preview",'<div class="liteeditor-preview-holder"></div>');e.classList.add("liteeditor-modal-wide");const i=t.createElement("iframe");i.className="liteeditor-preview-frame",i.setAttribute("sandbox",""),i.setAttribute("srcdoc",this._previewDocHTML()),e.querySelector(".liteeditor-preview-holder").appendChild(i)}printContent(){const e=t.createElement("iframe");e.setAttribute("aria-hidden","true"),e.style.cssText="position:fixed;right:0;bottom:0;width:0;height:0;border:0;",t.body.appendChild(e);const i=e.contentDocument;i.open(),i.write(this._previewDocHTML()),i.close(),setTimeout(()=>{try{e.contentWindow.focus(),e.contentWindow.print()}catch(e){}setTimeout(()=>e.remove(),1e3)},50)}showWordCount(){const e=(this.contentArea.textContent||"").trim(),t=e?e.split(/\s+/).filter(Boolean).length:0,i=(e,t)=>`<tr><td>${e}</td><td style="text-align:right"><strong>${t}</strong></td></tr>`;this._infoModal("Word count",'<table class="liteeditor-help-table">'+i("Words",t)+i("Characters",e.length)+i("Characters (no spaces)",e.replace(/\s/g,"").length)+"</table>")}showHelpDialog(){const t=e.liteeditor&&e.liteeditor.version||"";this._infoModal("Keyboard shortcuts",'<table class="liteeditor-help-table">'+[["Bold","Ctrl + B"],["Italic","Ctrl + I"],["Underline","Ctrl + U"],["Undo","Ctrl + Z"],["Redo","Ctrl + Y / Ctrl + Shift + Z"],["Search & Replace","Ctrl + F"]].map(e=>`<tr><td>${e[0]}</td><td style="text-align:right">${e[1]}</td></tr>`).join("")+"</table>"+`<p style="margin:10px 0 0;color:#888;font-size:12px">LiteEditor v${t}</p>`)}_menuTableCell(){const e=this.iframe&&this.iframe.contentWindow.getSelection();if(!e||!e.rangeCount)return null;let t=e.getRangeAt(0).startContainer;return 3===t.nodeType&&(t=t.parentNode),t&&t.closest?t.closest("td, th"):null}execCommand(e,t=null){this.iframe.contentWindow.focus(),this.restoreSelection();const i={undo:()=>this.undo(),redo:()=>this.redo(),strikethrough:()=>this.iframeDoc.execCommand("strikeThrough",!1,null),removeformat:()=>this.removeFormatting(),align:e=>this.setAlignment(e),lineheight:e=>this.setLineHeight(e),numlist:()=>this._toggleList("ol"),bullist:()=>this._toggleList("ul"),indent:()=>this.iframeDoc.execCommand("indent",!1,null),outdent:()=>this.iframeDoc.execCommand("outdent",!1,null)};i[e]?i[e](t):this.iframeDoc.execCommand(e,!1,t),this.saveState(),this.syncContent(),this.updateToolbarState()}removeFormatting(){this.iframeDoc.execCommand("removeFormat",!1,null),this.iframeDoc.execCommand("unlink",!1,null);const e=this.iframe.contentWindow.getSelection();if(0===e.rangeCount)return;const t=e.getRangeAt(0),i=t.commonAncestorContainer,n=i.nodeType===Node.TEXT_NODE?i.parentNode:i;if(!n||n===this.contentArea.ownerDocument)return;const o=[],r=this.iframeDoc.createTreeWalker(n,NodeFilter.SHOW_ELEMENT,null);for(n.nodeType===Node.ELEMENT_NODE&&t.intersectsNode(n)&&o.push(n);r.nextNode();)t.intersectsNode(r.currentNode)&&o.push(r.currentNode);const l=new Set(["FONT","SPAN","B","I","U","STRIKE","S","EM","STRONG","SUB","SUP","MARK","SMALL"]);o.forEach(e=>{if(e!==this.contentArea&&(e.removeAttribute("style"),e.removeAttribute("color"),e.removeAttribute("face"),e.removeAttribute("size"),e.removeAttribute("bgcolor"),l.has(e.tagName))){const t=e.parentNode;if(!t)return;for(;e.firstChild;)t.insertBefore(e.firstChild,e);t.removeChild(e)}})}setAlignment(e){this.iframeDoc.execCommand({left:"justifyLeft",center:"justifyCenter",right:"justifyRight",justify:"justifyFull"}[e],!1,null)}setFontSize(e){this.iframe.contentWindow.focus();const t=this.iframe.contentWindow.getSelection();if(!t.rangeCount)return;const i=t.getRangeAt(0);if(i.collapsed){this.iframeDoc.execCommand("fontSize",!1,"7");this.iframeDoc.querySelectorAll('font[size="7"]').forEach(t=>{const i=this.iframeDoc.createElement("span");i.style.fontSize=e,i.innerHTML=t.innerHTML||"&nbsp;",t.parentNode.replaceChild(i,t)})}else{const n=i.toString(),o=this.iframeDoc.createElement("span");o.style.fontSize=e;try{const e=i.extractContents();o.appendChild(e),i.insertNode(o),i.selectNodeContents(o),t.removeAllRanges(),t.addRange(i)}catch(t){const i=`<span style="font-size: ${e}">${n}</span>`;this.iframeDoc.execCommand("insertHTML",!1,i)}}this.saveState(),this.syncContent()}showColorPicker(e){this._colorPicker&&(this._colorPicker.remove(),this._colorPicker=null),this.saveSelection();const i="backcolor"===e?"hiliteColor":"foreColor",n=this.toolbar.querySelector(`[data-command="${e}"]`);if(!n)return;const o=r,l=t.createElement("div");l.className="liteeditor-color-picker",l.innerHTML=`\n <div class="liteeditor-color-grid">\n ${o.map(e=>`<button type="button" class="liteeditor-color-swatch" data-color="${e}" style="background:${e}" title="${e}"></button>`).join("")}\n </div>\n <div class="liteeditor-color-actions">\n <button type="button" class="liteeditor-color-clear" data-action="clear">Remove</button>\n <label class="liteeditor-color-custom">\n Custom\n <input type="color" class="liteeditor-color-input" value="#000000">\n </label>\n </div>\n `,this.anchorPopover(l,n),this._colorPicker=l;const a=t=>{if(this.iframe.contentWindow.focus(),this.restoreSelection(),null===t){this.iframeDoc.execCommand(i,!1,"transparent");const t=this.iframe.contentWindow.getSelection();if(t.rangeCount>0){const i=t.getRangeAt(0);(i.commonAncestorContainer.nodeType===Node.TEXT_NODE?i.commonAncestorContainer.parentNode:i.commonAncestorContainer).querySelectorAll("font, span").forEach(t=>{"forecolor"===e?(t.removeAttribute("color"),t.style.color=""):t.style.backgroundColor="",t.getAttribute("style")||t.removeAttribute("style")})}}else this.iframeDoc.execCommand(i,!1,t);this.saveState(),this.syncContent(),c()};let s=0;const c=()=>{s&&(clearTimeout(s),s=0),this._colorPicker&&(this._colorPicker.remove(),this._colorPicker=null),t.removeEventListener("mousedown",d,!0),this.iframeDoc.removeEventListener("mousedown",h,!0),this._openPickers.delete(c)};this._openPickers.add(c);const d=e=>{l.contains(e.target)||e.target===n||c()},h=()=>c();s=setTimeout(()=>{s=0,t.addEventListener("mousedown",d,!0),this.iframeDoc.addEventListener("mousedown",h,!0)},0),l.querySelectorAll(".liteeditor-color-swatch").forEach(e=>{e.addEventListener("click",()=>a(e.dataset.color))}),l.querySelector('[data-action="clear"]').addEventListener("click",()=>a(null)),l.querySelector(".liteeditor-color-input").addEventListener("input",e=>a(e.target.value))}detectCurrentListStyle(e){const t=this.iframe.contentWindow.getSelection();if(0===t.rangeCount)return null;let i=t.getRangeAt(0).startContainer;i.nodeType===Node.TEXT_NODE&&(i=i.parentNode);const n=i&&i.closest?i.closest(e):null;if(!n)return"none";let o=n,r=n.parentNode;for(;r&&r!==this.contentArea;)r.nodeType===Node.ELEMENT_NODE&&r.tagName&&r.tagName.toLowerCase()===e&&(o=r),r=r.parentNode;const l=o.style.listStyleType;return l||("ul"===e?"default":"decimal")}detectCurrentAlignment(){const e=this.iframe.contentWindow.getSelection();if(0===e.rangeCount)return null;let t=e.getRangeAt(0).startContainer;t.nodeType===Node.TEXT_NODE&&(t=t.parentNode);const i=new Set(["P","H1","H2","H3","H4","H5","H6","DIV","BLOCKQUOTE","LI","TD","TH","PRE"]);for(;t&&t!==this.contentArea;){if(t.nodeType===Node.ELEMENT_NODE&&i.has(t.tagName)){const e=t.style.textAlign;if(e)return e;const i=this.iframe.contentWindow.getComputedStyle(t);if(i.textAlign&&"start"!==i.textAlign)return i.textAlign;break}t=t.parentNode}return"left"}removeList(){const e=this.iframe.contentWindow.getSelection();if(!e||0===e.rangeCount)return;let t=e.getRangeAt(0).startContainer;t.nodeType===Node.TEXT_NODE&&(t=t.parentNode);const i=t&&t.closest?t.closest("li"):null,n=i&&i.parentElement?i.parentElement.tagName:null;"OL"===n?this.execCommand("numlist"):"UL"===n&&this.execCommand("bullist")}_toggleList(e){const t=this.iframe.contentWindow.getSelection();if(!t||0===t.rangeCount)return;const i=t.getRangeAt(0);let n=i.startContainer;n.nodeType===Node.TEXT_NODE&&(n=n.parentNode);const o=n&&n.closest?n.closest("li"):null;let r=o?o.parentElement:null;if(!r){r=(n&&n.childNodes?Array.from(n.childNodes):[]).find(e=>e.nodeType===Node.ELEMENT_NODE&&/^(UL|OL)$/.test(e.tagName)&&(i.intersectsNode?i.intersectsNode(e):e.contains(i.startContainer)))||null}if(r&&r.tagName.toLowerCase()===e)this._unwrapListItems(r);else if(r){const t=this.iframeDoc.createElement(e);for(;r.firstChild;)t.appendChild(r.firstChild);r.parentNode.replaceChild(t,r),this._selectNodeContents(t)}else this._wrapBlocksInList(e)}_wrapBlocksInList(e){const t=this.iframe.contentWindow.getSelection().getRangeAt(0);let i=t.commonAncestorContainer;i.nodeType===Node.TEXT_NODE&&(i=i.parentNode),i=i.closest&&i.closest("td, th, blockquote")||this.contentArea;const n=this.iframeDoc.createElement(e);let o=null,r=!1;const l=[];Array.from(i.childNodes).forEach(e=>{if(!(t.intersectsNode?t.intersectsNode(e):e.contains(t.startContainer)||e.contains(t.endContainer)))return void(o=null);r||(i.insertBefore(n,e),r=!0);const a=e.nodeType===Node.ELEMENT_NODE?e.tagName.toLowerCase():"",s=e.nodeType!==Node.ELEMENT_NODE||0===this.iframe.contentWindow.getComputedStyle(e).display.indexOf("inline");if("ul"===a||"ol"===a){for(;e.firstChild;)n.appendChild(e.firstChild);l.push(e),o=null}else if("p"===a||"div"===a){const t=this.iframeDoc.createElement("li");for(;e.firstChild;)t.appendChild(e.firstChild);n.appendChild(t),l.push(e),o=null}else if(s)o||(o=this.iframeDoc.createElement("li"),n.appendChild(o)),o.appendChild(e),l.push(null);else{const t=this.iframeDoc.createElement("li");t.appendChild(e),n.appendChild(t),l.push(null),o=null}}),n.childNodes.length?(l.forEach(e=>{e&&e.parentNode&&e.parentNode.removeChild(e)}),this._selectNodeContents(n)):r&&n.remove()}_unwrapListItems(e){const t=this.iframe.contentWindow.getSelection(),i=t.getRangeAt(0),n=Array.from(e.children).filter(e=>"LI"===e.tagName),o=n.filter(e=>i.intersectsNode?i.intersectsNode(e):e.contains(i.startContainer)||e.contains(i.endContainer));if(!o.length)return;const r=e.parentNode,l=n.slice(n.indexOf(o[o.length-1])+1),a=[],s=/^(H[1-6]|PRE|BLOCKQUOTE|TABLE|HR|FIGURE|P|DIV)$/;o.forEach(e=>{if(1===e.children.length&&1===e.childNodes.length&&s.test(e.children[0].tagName))return a.push(e.children[0]),void e.remove();const t=this.iframeDoc.createElement("p");for(;e.firstChild;)t.appendChild(e.firstChild);a.push(t),e.remove()});let c=null;l.length&&(c=this.iframeDoc.createElement(e.tagName.toLowerCase()),l.forEach(e=>c.appendChild(e)));const d=e.nextSibling;a.forEach(e=>r.insertBefore(e,d)),c&&r.insertBefore(c,d),e.children.length||e.remove();const h=this.iframeDoc.createRange();h.setStartBefore(a[0]),h.setEndAfter(a[a.length-1]),t.removeAllRanges(),t.addRange(h)}_selectNodeContents(e){const t=this.iframe.contentWindow.getSelection(),i=this.iframeDoc.createRange();i.selectNodeContents(e),t.removeAllRanges(),t.addRange(i)}setListStyle(e,t){this.iframe.contentWindow.focus(),this.restoreSelection();const i=this.iframe.contentWindow.getSelection();if(0===i.rangeCount)return;const n=()=>{let t=i.getRangeAt(0).startContainer;return t.nodeType===Node.TEXT_NODE&&(t=t.parentNode),t&&t.closest?t.closest(e):null};let o=n();if(o||(this._toggleList(e),o=n()),!o)return;let r=o,l=o.parentNode;for(;l&&l!==this.contentArea;)l.nodeType===Node.ELEMENT_NODE&&l.tagName&&l.tagName.toLowerCase()===e&&(r=l),l=l.parentNode;"default"===t?(r.style.listStyleType="",r.getAttribute("style")||r.removeAttribute("style"),r.querySelectorAll(e).forEach(e=>{e.style.listStyleType="",e.getAttribute("style")||e.removeAttribute("style")})):r.style.listStyleType=t,this.saveState(),this.syncContent()}anchorPopover(e,t){e.style.position="absolute",e.style.visibility="hidden",this.editorContainer.appendChild(e);const i=this.editorContainer.getBoundingClientRect(),n=t.getBoundingClientRect(),o=n.bottom-i.top+4;let r=n.left-i.left;const l=e.offsetWidth,a=this.editorContainer.clientWidth;r+l>a-4&&(r=Math.max(4,a-l-4)),r<4&&(r=4),e.style.top=o+"px",e.style.left=r+"px",e.style.zIndex="10000",e.style.visibility=""}showLineHeightPicker(){if(this._lineHeightPicker)return this._lineHeightPicker.remove(),void(this._lineHeightPicker=null);this.saveSelection();const e=this.toolbar.querySelector('[data-command="lineheight"]');if(!e)return;const i=this.detectCurrentLineHeight()||"1.5",n=t.createElement("div");n.className="liteeditor-lineheight-picker",n.innerHTML=`\n <div class="liteeditor-lh-section">\n <div class="liteeditor-lh-label">Presets</div>\n <div class="liteeditor-lh-presets">\n ${["1","1.15","1.5","1.75","2","2.5","3"].map(e=>`<button type="button" class="liteeditor-lh-preset" data-value="${e}">${e}</button>`).join("")}\n </div>\n </div>\n <div class="liteeditor-lh-section">\n <div class="liteeditor-lh-label">\n <span>Slider</span>\n <span class="liteeditor-lh-value">${i}</span>\n </div>\n <input type="range" class="liteeditor-lh-slider" min="0.5" max="4" step="0.05" value="${i}">\n <div class="liteeditor-lh-slider-range"><span>0.5</span><span>4.0</span></div>\n </div>\n <div class="liteeditor-lh-section liteeditor-lh-custom">\n <input type="number" class="liteeditor-lh-input" min="0" step="0.05" value="${i}" placeholder="1.5">\n <button type="button" class="liteeditor-lh-apply">Apply</button>\n <button type="button" class="liteeditor-lh-reset">Reset</button>\n </div>\n `,this.anchorPopover(n,e),this._lineHeightPicker=n;const o=n.querySelector(".liteeditor-lh-slider"),r=n.querySelector(".liteeditor-lh-value"),l=n.querySelector(".liteeditor-lh-input"),a=e=>{this.iframe.contentWindow.focus(),this.restoreSelection(),this.setLineHeight(e),this.saveSelection()},s=e=>{a(e),this.saveState()};n.querySelectorAll(".liteeditor-lh-preset").forEach(e=>{e.addEventListener("click",()=>{const t=e.dataset.value;o.value=t,l.value=t,r.textContent=t,s(t)})}),o.addEventListener("input",()=>{const e=o.value;r.textContent=e,l.value=e,a(e)}),o.addEventListener("change",()=>{this.saveState()});const c=()=>{const e=l.value.trim();if(""===e)return;const t=parseFloat(e);if(isNaN(t)||t<0)return;const i=t.toString();o.value=Math.min(Math.max(t,.5),4),r.textContent=i,s(i)};l.addEventListener("keydown",e=>{"Enter"===e.key&&(e.preventDefault(),c())}),n.querySelector(".liteeditor-lh-apply").addEventListener("click",c),n.querySelector(".liteeditor-lh-reset").addEventListener("click",()=>{o.value="1.5",l.value="",r.textContent="default",s(null)});let d=0;const h=()=>{d&&(clearTimeout(d),d=0),this._lineHeightPicker&&(this._lineHeightPicker.remove(),this._lineHeightPicker=null),t.removeEventListener("mousedown",p,!0),t.removeEventListener("keydown",m,!0),this.iframeDoc.removeEventListener("mousedown",u,!0),this.iframeDoc.removeEventListener("keydown",m,!0),this._openPickers.delete(h)};this._openPickers.add(h);const p=t=>{n.contains(t.target)||t.target===e||e.contains(t.target)||h()},u=()=>h(),m=e=>{"Escape"===e.key&&h()};d=setTimeout(()=>{d=0,t.addEventListener("mousedown",p,!0),t.addEventListener("keydown",m,!0),this.iframeDoc.addEventListener("mousedown",u,!0),this.iframeDoc.addEventListener("keydown",m,!0)},0)}detectCurrentLineHeight(){const e=this.iframe.contentWindow.getSelection();if(0===e.rangeCount)return null;const t=e.getRangeAt(0).commonAncestorContainer,i=t.nodeType===Node.TEXT_NODE?t.parentNode:t;if(!i)return null;const n=i.style&&i.style.lineHeight;if(n&&!n.endsWith("px"))return n;const o=this.iframe.contentWindow.getComputedStyle(i),r=o.lineHeight;if(r&&r.endsWith("px")){const e=parseFloat(o.fontSize);if(e>0)return(parseFloat(r)/e).toFixed(2)}return null}setLineHeight(e){const t=this.iframe.contentWindow.getSelection();if(0===t.rangeCount)return;const i=t.getRangeAt(0),n=new Set(["P","H1","H2","H3","H4","H5","H6","DIV","BLOCKQUOTE","LI","TD","TH","PRE"]),o=new Set,r=e=>{for(;e&&e!==this.contentArea;){if(e.nodeType===Node.ELEMENT_NODE&&n.has(e.tagName))return e;e=e.parentNode}return null},l=r(i.startContainer),a=r(i.endContainer);l&&o.add(l),a&&o.add(a);const s=this.iframeDoc.createTreeWalker(this.contentArea,NodeFilter.SHOW_ELEMENT,{acceptNode:e=>n.has(e.tagName)?i.intersectsNode(e)?NodeFilter.FILTER_ACCEPT:NodeFilter.FILTER_REJECT:NodeFilter.FILTER_SKIP});for(;s.nextNode();)o.add(s.currentNode);const c=t=>{null===e||""===e||void 0===e?(t.style.lineHeight="",t.getAttribute("style")||t.removeAttribute("style")):t.style.lineHeight=e};0===o.size?c(this.contentArea):o.forEach(c),this.syncContent()}attachEventListeners(){this.contentArea.addEventListener("input",()=>{this.syncContent(),this._scheduleSaveState(),this.onContentChanged()}),this.contentArea.addEventListener("keydown",e=>{(e.ctrlKey||e.metaKey)&&("z"===e.key?(e.preventDefault(),this.undo()):"y"===e.key||e.shiftKey&&"z"===e.key?(e.preventDefault(),this.redo()):"b"===e.key?(e.preventDefault(),this.execCommand("bold")):"i"===e.key?(e.preventDefault(),this.execCommand("italic")):"u"===e.key?(e.preventDefault(),this.execCommand("underline")):"f"!==e.key&&"h"!==e.key||(e.preventDefault(),this.showSearchReplace()))}),this.contentArea.addEventListener("mouseup",()=>{this.updateToolbarState()}),this.contentArea.addEventListener("keyup",()=>{this.updateToolbarState()}),this._onToolbarMouseDown=e=>{const t=e.target;"INPUT"===t.tagName||"TEXTAREA"===t.tagName||"SELECT"===t.tagName||t.isContentEditable||t.closest(".liteeditor-btn, .liteeditor-dropdown-item")&&(this.saveSelection(),e.preventDefault())},this.toolbar.addEventListener("mousedown",this._onToolbarMouseDown);let e=0;this._onSelectionChange=()=>{if(e)return;if(!this.toolbar||!this.iframe||!this.iframe.contentWindow)return;const t=this.iframe.contentWindow.requestAnimationFrame||(e=>this.iframe.contentWindow.setTimeout(e,16));e=t.call(this.iframe.contentWindow,()=>{e=0,this.toolbar&&this.iframe&&this.iframe.contentWindow&&(this.updateToolbarState(),this._syncTableActiveState())})},this.iframeDoc.addEventListener("selectionchange",this._onSelectionChange),this._closeDropdowns=e=>{this.toolbar.querySelectorAll(".liteeditor-dropdown").forEach(e=>e.classList.remove("active")),!this.menubar||e&&e.target&&this.menubar.contains(e.target)||this._closeMenus()},t.addEventListener("click",this._closeDropdowns),this.contentArea.addEventListener("click",this._closeDropdowns),this.iframeDoc.addEventListener("click",this._closeDropdowns),this.contentArea.addEventListener("paste",e=>{e.preventDefault();const t=e.clipboardData;if(!t)return;const i=t.getData("text/html"),n=t.getData("text/plain");if(i)try{return void this.iframeDoc.execCommand("insertHTML",!1,this.sanitizeHTML(i))}catch(e){}if(n)try{this.iframeDoc.execCommand("insertHTML",!1,n.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/\n/g,"<br>"))}catch(e){}}),this.setupImageResize(),this.setupFormSubmitHook()}setupFormSubmitHook(){const e=this.element&&this.element.form;e&&(this._onFormSubmit=()=>{try{this.syncContent()}catch(e){}},e.addEventListener("submit",this._onFormSubmit,!0))}setupEditorResize(){let e=!1,i=0,n=0;this.resizeHandle.addEventListener("mousedown",o=>{e=!0,i=o.clientY,n=this.iframe.offsetHeight,t.body.style.cursor="ns-resize",t.body.style.userSelect="none",o.preventDefault()}),this._onResizeMove=t=>{if(!e)return;const o=t.clientY-i,r=Math.max(100,Math.min(1e3,n+o));this.iframe.style.height=r+"px"},this._onResizeUp=()=>{e&&(e=!1,t.body.style.cursor="",t.body.style.userSelect="")},t.addEventListener("mousemove",this._onResizeMove),t.addEventListener("mouseup",this._onResizeUp)}setupImageResize(){this.contentArea.addEventListener("click",e=>{if("IMG"===e.target.tagName)this.selectImage(e.target);else if(e.target.closest(".liteeditor-image-resizer")){const t=e.target.closest(".liteeditor-image-resizer").querySelector("img");t&&this.selectImage(t)}else this.deselectImage()}),this.contentArea.addEventListener("dblclick",e=>{let t=null;if("IMG"===e.target.tagName)t=e.target;else{const i=e.target.closest&&e.target.closest(".liteeditor-image-resizer");i&&(t=i.querySelector("img"))}t&&(e.preventDefault(),e.stopPropagation(),this.showImageModal(t))}),this._imageObserver=new MutationObserver(()=>{this.contentArea.querySelectorAll("img:not(.wrapped)").forEach(e=>{e.parentElement.classList.contains("liteeditor-image-resizer")||this.wrapImage(e)});this.contentArea.querySelectorAll("table").forEach(e=>{e.parentElement&&e.parentElement.classList.contains("liteeditor-table-wrapper")||this.wrapTable(e)})}),this._imageObserver.observe(this.contentArea,{childList:!0,subtree:!0})}_injectInstanceStyles(){const e=this._defaultStyles;if(!e)return;const t={table:"table",th:"table th",td:"table td",blockquote:"blockquote",pre:"pre",code:"code",hr:"hr",img:"img",ul:"ul",ol:"ol",li:"li"},i=Object.keys(t).filter(t=>e[t]).map(i=>`${t[i]} { ${e[i]} }`).join("\n");if(!i)return;const n=this.iframeDoc.createElement("style");n.setAttribute("data-liteeditor-instance-styles","1"),n.textContent=i,this.iframeDoc.head.appendChild(n)}_buildImageStyle(e,t,i){const n=this._defaultStyles&&this._defaultStyles.img?this._defaultStyles.img:"",o=n?[n.replace(/;?\s*$/,";")]:[],r=e?parseInt(e,10):0,l=t?parseInt(t,10):0;return r&&l?(o.push(` width: ${r}px;`),o.push(` aspect-ratio: ${r} / ${l};`)):r?o.push(` width: ${r}px;`):l&&(o.push(` height: ${l}px;`),o.push(" width: auto;")),i&&o.push(" "+i.replace(/^\s*;?\s*/,"").replace(/;?\s*$/,";")),o.join("").trim()}_readImageFields(e){const t=(e.style&&e.style.width||"").match(/(\d+)/),i=(e.style&&e.style.height||"").match(/(\d+)/),n=e.closest&&e.closest("a");return{url:e.getAttribute("src")||"",alt:e.getAttribute("alt")||"",width:t?t[1]:e.getAttribute("width")||"",height:i?i[1]:e.getAttribute("height")||"",link:n&&n.getAttribute("href")||"",linkNewTab:!(!n||"_blank"!==n.getAttribute("target"))}}_insertImage(e){const t=e=>String(null==e?"":e).replace(/&/g,"&amp;").replace(/"/g,"&quot;").replace(/</g,"&lt;").replace(/>/g,"&gt;"),i=n.sanitizeUrl(e.url,{allowDataImage:!0}),o=this._buildImageStyle(e.width,e.height);let r=`<img src="${t(i)}" alt="${t(e.alt||"")}"`;if(o&&(r+=` style="${o}"`),r+=" />",e.link){const i=n.sanitizeUrl(e.link);if(i){const n=e.linkNewTab?' target="_blank" rel="noopener noreferrer"':"";r=`<a href="${t(i)}"${n}>${r}</a>`}}this.execCommand("insertHTML",r)}_updateImage(e,t){void 0!==t.url&&e.setAttribute("src",n.sanitizeUrl(t.url,{allowDataImage:!0})),void 0!==t.alt&&e.setAttribute("alt",t.alt||"");const i=e.getAttribute("style")||"",o=["float","display","margin","margin-left","margin-right","margin-top","margin-bottom"],r=i.split(";").map(e=>e.trim()).filter(Boolean).filter(e=>{const t=e.split(":")[0].trim().toLowerCase();return o.includes(t)}).join("; ");e.setAttribute("style",this._buildImageStyle(t.width,t.height,r)),this._setImageLink(e,t.link,t.linkNewTab),this.syncContent(),this.saveState(),this.onContentChanged(),this.updateImageInfo(e.closest(".liteeditor-image-resizer"),e)}_setImageAlign(e,t){const i=new Set(["float","display","margin","margin-left","margin-right","margin-top","margin-bottom"]),n=(e.getAttribute("style")||"").split(";").map(e=>e.trim()).filter(Boolean).filter(e=>!i.has(e.split(":")[0].trim().toLowerCase())),o=new Set(n.map(e=>e.split(":")[0].trim().toLowerCase()));o.has("max-width")||n.unshift("max-width: 100%"),o.has("height")||n.push("height: auto"),"left"===t?(n.push("float: left"),n.push("margin: 0 16px 8px 0")):"right"===t?(n.push("float: right"),n.push("margin: 0 0 8px 16px")):"center"===t&&(n.push("display: block"),n.push("margin-left: auto"),n.push("margin-right: auto")),e.setAttribute("style",n.join("; ")),this.syncContent(),this.saveState(),this.onContentChanged()}_setImageLink(e,t,i){const o=e.closest(".liteeditor-image-resizer")||e,r=o.parentNode,l=r&&"A"===r.tagName,a=t?n.sanitizeUrl(t):"";if(a){let e;l?e=r:(e=this.iframeDoc.createElement("a"),r.insertBefore(e,o),e.appendChild(o)),e.setAttribute("href",a),i?(e.setAttribute("target","_blank"),e.setAttribute("rel","noopener noreferrer")):(e.removeAttribute("target"),e.removeAttribute("rel"))}else if(l){for(;r.firstChild;)r.parentNode.insertBefore(r.firstChild,r);r.remove()}}_replaceImageFile(e){const t=this.iframeDoc.createElement("input");t.type="file",t.accept="image/*",t.style.display="none",t.addEventListener("change",()=>{const i=t.files&&t.files[0];if(!i)return void t.remove();this._trackReader(new FileReader,n=>{e.isConnected?(e.setAttribute("src",n.target.result),e.getAttribute("alt")||e.setAttribute("alt",i.name),this.syncContent(),this.saveState(),this.onContentChanged(),t.remove()):t.remove()}).readAsDataURL(i)}),this.iframeDoc.body.appendChild(t),t.click()}_deleteImage(e){const t=e.closest(".liteeditor-image-resizer")||e,i=t.closest&&t.closest("a");(i&&1===i.childNodes.length&&i.childNodes[0]===t?i:t).remove(),this.syncContent(),this.saveState(),this.onContentChanged()}_showImageLinkPopover(e,t){const i=e.querySelector(".liteeditor-image-link-popover");if(i)return void i.remove();const n=t.closest("a"),o=n&&n.getAttribute("href")||"",r=!(!n||"_blank"!==n.getAttribute("target")),l=this.iframeDoc.createElement("div");var a;l.className="liteeditor-image-link-popover",l.setAttribute("data-liteeditor-chrome","1"),l.contentEditable="false",l.innerHTML=`\n <input type="url" class="liteeditor-img-link-input" placeholder="https://example.com" value="${a=o,String(null==a?"":a).replace(/&/g,"&amp;").replace(/"/g,"&quot;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}">\n <label class="liteeditor-img-link-newtab"><input type="checkbox" ${r?"checked":""}>New tab</label>\n <button type="button" class="liteeditor-img-link-save" data-action="save">Save</button>\n ${o?'<button type="button" class="liteeditor-img-link-remove" data-action="remove">Remove</button>':""}\n `;const s=l.querySelector('input[type="url"]'),c=l.querySelector('input[type="checkbox"]'),d=()=>{this._setImageLink(t,s.value.trim(),c.checked),this.syncContent(),this.saveState(),this.onContentChanged(),l.remove()};l.querySelector('[data-action="save"]').addEventListener("click",d);const h=l.querySelector('[data-action="remove"]');h&&h.addEventListener("click",()=>{this._setImageLink(t,"",!1),this.syncContent(),this.saveState(),this.onContentChanged(),l.remove()}),s.addEventListener("keydown",e=>{"Enter"===e.key&&(e.preventDefault(),d()),"Escape"===e.key&&(e.preventDefault(),l.remove())}),l.addEventListener("mousedown",e=>e.stopPropagation()),l.addEventListener("click",e=>e.stopPropagation()),e.appendChild(l),s.focus(),s.select()}_buildImageToolbar(e,t){const i=this.iframeDoc.createElement("div");i.className="liteeditor-image-toolbar",i.setAttribute("data-liteeditor-chrome","1"),i.contentEditable="false";const n=(e,t,i)=>{const n=this.iframeDoc.createElement("button");return n.type="button",n.className="liteeditor-img-toolbar-btn",n.title=t,n.innerHTML=e,n.setAttribute("data-liteeditor-chrome","1"),n.addEventListener("mousedown",e=>{e.preventDefault()}),n.addEventListener("click",e=>{e.preventDefault(),e.stopPropagation(),i()}),n},o=()=>{const e=this.iframeDoc.createElement("span");return e.className="liteeditor-img-toolbar-sep",e.setAttribute("data-liteeditor-chrome","1"),e},r='<svg viewBox="0 0 16 16" width="14" height="14"><path fill="currentColor" d="M11.7 1.3a1 1 0 0 1 1.4 0l1.6 1.6a1 1 0 0 1 0 1.4l-9 9-3.7.7.7-3.7 9-9zM10.6 3.4l2 2"/></svg>',l='<svg viewBox="0 0 16 16" width="14" height="14"><path fill="currentColor" d="M8 2a6 6 0 0 1 5.7 4.1l1.3-.4-1.5 3-3-1.5 1.3-.4A4 4 0 0 0 4.5 9H2.5A6 6 0 0 1 8 2zM2.5 7.4l3 1.5-1.3.4A4 4 0 0 0 11.5 7h2A6 6 0 0 1 2.3 10.4l-1.3.4 1.5-3.4z"/></svg>',a='<svg viewBox="0 0 16 16" width="14" height="14"><rect fill="currentColor" x="1" y="2" width="6" height="6"/><rect fill="currentColor" x="1" y="10" width="14" height="1.4"/><rect fill="currentColor" x="1" y="13" width="14" height="1.4"/></svg>',s='<svg viewBox="0 0 16 16" width="14" height="14"><rect fill="currentColor" x="5" y="2" width="6" height="6"/><rect fill="currentColor" x="1" y="10" width="14" height="1.4"/><rect fill="currentColor" x="1" y="13" width="14" height="1.4"/></svg>',c='<svg viewBox="0 0 16 16" width="14" height="14"><rect fill="currentColor" x="9" y="2" width="6" height="6"/><rect fill="currentColor" x="1" y="10" width="14" height="1.4"/><rect fill="currentColor" x="1" y="13" width="14" height="1.4"/></svg>',d='<svg viewBox="0 0 16 16" width="14" height="14"><path fill="none" stroke="currentColor" stroke-width="1.6" d="M6 9a3 3 0 0 0 4 0l2-2a3 3 0 0 0-4-4l-1 1M10 7a3 3 0 0 0-4 0L4 9a3 3 0 0 0 4 4l1-1"/></svg>',h='<svg viewBox="0 0 16 16" width="14" height="14"><path fill="currentColor" d="M6 1h4l1 1h3v2H2V2h3l1-1zm-3 4h10l-1 9.5a1 1 0 0 1-1 .9H5a1 1 0 0 1-1-.9L3 5z"/></svg>';i.appendChild(n(r,"Edit image",()=>this.showImageModal(t))),i.appendChild(n(l,"Replace image",()=>this._replaceImageFile(t))),i.appendChild(o()),i.appendChild(n(a,"Align left",()=>this._setImageAlign(t,"left"))),i.appendChild(n(s,"Align center",()=>this._setImageAlign(t,"center"))),i.appendChild(n(c,"Align right",()=>this._setImageAlign(t,"right"))),i.appendChild(o()),i.appendChild(n(d,"Add or edit link",()=>this._showImageLinkPopover(e,t))),i.appendChild(o()),i.appendChild(n(h,"Remove image",()=>this._deleteImage(t))),e.appendChild(i)}wrapTable(e){const t=this.iframeDoc.createElement("div");t.className="liteeditor-table-wrapper",t.setAttribute("data-liteeditor-chrome","1"),e.parentNode.insertBefore(t,e),t.appendChild(e),this._buildTableToolbar(t),this._attachTableResizeHandles(t,e),this._syncWrapperAlignment(t,e),this._syncWrapperWidth(t,e),this.syncContent()}_attachTableResizeHandles(e,t){const i=this.iframeDoc;["nw","n","ne","e","se","s","sw","w"].forEach(n=>{const o=i.createElement("span");o.className=`liteeditor-table-resize-handle ${n}`,o.setAttribute("data-liteeditor-chrome","1"),o.setAttribute("contenteditable","false"),o.addEventListener("mousedown",i=>{i.preventDefault(),i.stopPropagation(),this._startTableResize(i,e,t,n)}),e.appendChild(o)})}_startTableResize(e,i,n,o){const r=e.clientX,l=e.clientY,a=n.offsetWidth,s=n.offsetHeight,c="nw"===o||"w"===o||"sw"===o,d="nw"===o||"n"===o||"ne"===o,h=c||("ne"===o||"e"===o||"se"===o),p=d||("sw"===o||"s"===o||"se"===o),u=e=>{e.preventDefault();const t=e.clientX-r,o=e.clientY-l;if(h){const e=Math.max(80,c?a-t:a+t);n.style.width=e+"px","100%"===n.style.maxWidth&&(n.style.maxWidth=""),this._syncWrapperWidth(i,n)}if(p){const e=Math.max(30,d?s-o:s+o);n.style.height=e+"px"}},m=()=>{this.iframeDoc.removeEventListener("mousemove",u),this.iframeDoc.removeEventListener("mouseup",f),t.removeEventListener("mousemove",u),t.removeEventListener("mouseup",f),this._activeResize===m&&(this._activeResize=null)},f=()=>{m(),this.syncContent(),this.saveState(),this.onContentChanged()};this._activeResize=m,this.iframeDoc.addEventListener("mousemove",u),this.iframeDoc.addEventListener("mouseup",f),t.addEventListener("mousemove",u),t.addEventListener("mouseup",f)}_buildTableToolbar(e){const t=this.iframeDoc,i=t.createElement("div");i.className="liteeditor-table-toolbar",i.setAttribute("data-liteeditor-chrome","1"),i.contentEditable="false";const n=(i,n,o)=>{const r=t.createElement("button");return r.type="button",r.className="liteeditor-tbl-toolbar-btn",r.title=n,r.innerHTML=i,r.setAttribute("data-liteeditor-chrome","1"),r.addEventListener("mousedown",e=>e.preventDefault()),r.addEventListener("click",t=>{t.preventDefault(),t.stopPropagation();const i=e._activeCell;i&&i.isConnected&&o(i)}),r},o=()=>{const e=t.createElement("span");return e.className="liteeditor-tbl-toolbar-sep",e.setAttribute("data-liteeditor-chrome","1"),e},r='<svg viewBox="0 0 16 16" width="14" height="14"><rect x="1" y="6" width="14" height="3" fill="currentColor"/><rect x="1" y="11" width="14" height="3" fill="currentColor" opacity="0.45"/><path d="M8 1v3M6.5 2.5L8 1l1.5 1.5" stroke="currentColor" stroke-width="1.4" fill="none" stroke-linecap="round" stroke-linejoin="round"/></svg>',l='<svg viewBox="0 0 16 16" width="14" height="14"><rect x="1" y="2" width="14" height="3" fill="currentColor" opacity="0.45"/><rect x="1" y="7" width="14" height="3" fill="currentColor"/><path d="M8 15v-3M6.5 13.5L8 15l1.5-1.5" stroke="currentColor" stroke-width="1.4" fill="none" stroke-linecap="round" stroke-linejoin="round"/></svg>',a='<svg viewBox="0 0 16 16" width="14" height="14"><rect x="1" y="7" width="14" height="3" fill="currentColor"/><path d="M3 4l3 3M6 4L3 7M10 4l3 3M13 4l-3 3" stroke="currentColor" stroke-width="1.4" fill="none" stroke-linecap="round"/></svg>',s='<svg viewBox="0 0 16 16" width="14" height="14"><rect x="6" y="1" width="3" height="14" fill="currentColor"/><rect x="11" y="1" width="3" height="14" fill="currentColor" opacity="0.45"/><path d="M1 8h3M2.5 6.5L1 8l1.5 1.5" stroke="currentColor" stroke-width="1.4" fill="none" stroke-linecap="round" stroke-linejoin="round"/></svg>',c='<svg viewBox="0 0 16 16" width="14" height="14"><rect x="2" y="1" width="3" height="14" fill="currentColor" opacity="0.45"/><rect x="7" y="1" width="3" height="14" fill="currentColor"/><path d="M15 8h-3M13.5 6.5L15 8l-1.5 1.5" stroke="currentColor" stroke-width="1.4" fill="none" stroke-linecap="round" stroke-linejoin="round"/></svg>',d='<svg viewBox="0 0 16 16" width="14" height="14"><rect x="7" y="1" width="3" height="14" fill="currentColor"/><path d="M4 3l3 3M7 3L4 6M4 10l3 3M7 10l-3 3M12 3l-3 3M9 3l3 3M12 10l-3 3M9 10l3 3" stroke="currentColor" stroke-width="1.2" fill="none" stroke-linecap="round"/></svg>',h='<svg viewBox="0 0 16 16" width="14" height="14"><rect x="1" y="2" width="14" height="12" fill="none" stroke="currentColor" stroke-width="1.4"/><path d="M1 6h14M1 10h14M6 2v12M10 2v12" stroke="currentColor" stroke-width="1.4" fill="none"/><path d="M3 3l10 10M13 3L3 13" stroke="#e53935" stroke-width="1.6" fill="none" stroke-linecap="round"/></svg>',p='<svg viewBox="0 0 16 16" width="14" height="14"><circle cx="8" cy="8" r="2" fill="currentColor"/><path d="M8 1v2M8 13v2M1 8h2M13 8h2M3.1 3.1l1.4 1.4M11.5 11.5l1.4 1.4M12.9 3.1l-1.4 1.4M4.5 11.5l-1.4 1.4" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" fill="none"/></svg>',u='<svg viewBox="0 0 16 16" width="14" height="14"><rect x="1" y="5" width="14" height="6" fill="none" stroke="currentColor" stroke-width="1.4"/><path d="M3 8h2M11 8h2M4.5 6.5L3 8l1.5 1.5M11.5 6.5L13 8l-1.5 1.5" stroke="currentColor" stroke-width="1.4" fill="none" stroke-linecap="round" stroke-linejoin="round"/></svg>';i.appendChild(n(r,"Insert row above",e=>this._tableInsertRowAbove(e))),i.appendChild(n(l,"Insert row below",e=>this._tableInsertRowBelow(e))),i.appendChild(n(a,"Delete row",e=>this._tableDeleteRow(e))),i.appendChild(o()),i.appendChild(n(s,"Insert column left",e=>this._tableInsertColumnLeft(e))),i.appendChild(n(c,"Insert column right",e=>this._tableInsertColumnRight(e))),i.appendChild(n(d,"Delete column",e=>this._tableDeleteColumn(e))),i.appendChild(o()),i.appendChild(n(h,"Delete table",e=>this._tableDeleteTable(e))),i.appendChild(o()),i.appendChild(n(p,"Table properties",e=>this._showTablePropertiesModal(e.closest("table"))));const m=n(u,"Toggle full width (100%)",e=>this._tableToggleFullWidth(e));m.classList.add("liteeditor-tbl-fullwidth-btn"),i.appendChild(m),e.appendChild(i)}_syncTableActiveState(){const e=this.iframe.contentWindow.getSelection();if(!e||0===e.rangeCount)return void this.contentArea.querySelectorAll(".liteeditor-table-wrapper.active").forEach(e=>{e.classList.remove("active"),e._activeCell=null});let t=e.anchorNode;t&&3===t.nodeType&&(t=t.parentNode);const i=t&&t.closest&&t.closest(".liteeditor-table-wrapper"),n=t&&t.closest&&t.closest("td, th");if(this.contentArea.querySelectorAll(".liteeditor-table-wrapper.active").forEach(e=>{e!==i&&(e.classList.remove("active"),e._activeCell=null)}),i){i.classList.add("active"),n&&i.contains(n)&&(i._activeCell=n);const e=i.querySelector(":scope > table"),t=i.querySelector(".liteeditor-tbl-fullwidth-btn");if(e&&t){const i=(e.style.width||"").trim().toLowerCase();t.classList.toggle("active","100%"===i)}}}_placeTableCursor(e){if(!e||!e.isConnected)return;const t=this.iframeDoc.createRange();t.selectNodeContents(e),t.collapse(!0);const i=this.iframe.contentWindow.getSelection();i.removeAllRanges(),i.addRange(t),this.savedRange=t.cloneRange()}_makeCellLike(e,t){const i=this.iframeDoc,n=e?e.tagName.toLowerCase():t||"td",o=i.createElement(n),r=e&&e.getAttribute("style");return r?o.setAttribute("style",r):this._defaultStyles&&this._defaultStyles[n]&&o.setAttribute("style",this._defaultStyles[n]),o.innerHTML="<br>",o}_afterTableMutation(e){this._placeTableCursor(e),this.syncContent(),this.saveState(),this.onContentChanged(),this.updateToolbarState()}_tableRemoveIfEmpty(e){if(e.querySelector("td, th"))return!1;const t=e.closest(".liteeditor-table-wrapper")||e,i=t.nextSibling||t.previousSibling;if(t.remove(),i&&1===i.nodeType){const e=this.iframeDoc.createRange();e.selectNodeContents(i),e.collapse(!0);const t=this.iframe.contentWindow.getSelection();t.removeAllRanges(),t.addRange(e)}return this.syncContent(),this.saveState(),this.onContentChanged(),!0}_tableInsertRow(e,t){const i=e.closest("tr");if(!i)return;const n=this.iframeDoc.createElement("tr");Array.from(i.cells).forEach(e=>{const t=this._makeCellLike(e);e.hasAttribute("colspan")&&t.setAttribute("colspan",e.getAttribute("colspan")),n.appendChild(t)}),"above"===t?i.parentNode.insertBefore(n,i):i.parentNode.insertBefore(n,i.nextSibling),this._afterTableMutation(n.cells[Array.from(i.cells).indexOf(e)]||n.cells[0])}_tableInsertRowAbove(e){this._tableInsertRow(e,"above")}_tableInsertRowBelow(e){this._tableInsertRow(e,"below")}_tableDeleteRow(e){const t=e.closest("tr");if(!t)return;const i=t.closest("table"),n=t.parentNode,o=t.nextElementSibling||t.previousElementSibling;if(t.remove(),n&&!n.querySelector("tr")&&"TABLE"!==n.tagName&&i.querySelectorAll("tr").length>0&&n.remove(),this._tableRemoveIfEmpty(i))return;const r=o&&o.cells[Array.from(t.cells||[]).indexOf(e)]||o&&o.cells[0];this._afterTableMutation(r)}_tableInsertColumn(e,t){const i=e.closest("tr");if(!i)return;const n=Array.from(i.cells).indexOf(e),o=i.closest("table"),r=[];o.querySelectorAll("tr").forEach(e=>{const o=e.cells[n],l=this._makeCellLike(o,e.parentNode&&"THEAD"===e.parentNode.tagName?"th":"td");o?"left"===t?e.insertBefore(l,o):e.insertBefore(l,o.nextSibling):e.appendChild(l),e===i&&r.push(l)}),this._afterTableMutation(r[0]||e)}_tableInsertColumnLeft(e){this._tableInsertColumn(e,"left")}_tableInsertColumnRight(e){this._tableInsertColumn(e,"right")}_tableDeleteColumn(e){const t=e.closest("tr");if(!t)return;const i=Array.from(t.cells).indexOf(e),n=t.closest("table");if(n.querySelectorAll("tr").forEach(e=>{e.cells[i]&&e.cells[i].remove()}),this._tableRemoveIfEmpty(n))return;const o=t.cells[i]||t.cells[t.cells.length-1];this._afterTableMutation(o)}_tableToggleFullWidth(e){const t=e.closest("table");if(!t)return;const i=t.closest(".liteeditor-table-wrapper");"100%"===(t.style.width||"").trim().toLowerCase()?t.style.removeProperty("width"):(t.style.width="100%",t.style.maxWidth="100%"),this._syncWrapperWidth(i,t),this._afterTableMutation(e)}_tableDeleteTable(e){const t=e.closest("table");if(!t)return;const i=t.closest(".liteeditor-table-wrapper")||t,n=i.nextSibling||i.previousSibling;i.remove();const o=this.iframe.contentWindow.getSelection();if(o.removeAllRanges(),n&&1===n.nodeType){const e=this.iframeDoc.createRange();e.selectNodeContents(n),e.collapse(!0),o.addRange(e)}this.syncContent(),this.saveState(),this.onContentChanged(),this.updateToolbarState()}_readTableProperties(e){const t=t=>{const i=(e.getAttribute("style")||"").match(new RegExp(`(?:^|;)\\s*${t}\\s*:\\s*([^;]+)`,"i"));return i?i[1].trim():""},i=t("width"),n=t("height"),o=e.querySelector("th, td"),r=o&&o.style.padding||"",l=o&&(o.style.borderWidth||(o.style.border&&o.style.border.match(/^(\d+(?:\.\d+)?)px/)||[,""])[1])||"",a=t("border-spacing"),s=e.querySelector(":scope > caption"),c=t("float").toLowerCase(),d=t("margin-left").toLowerCase(),h=t("margin-right").toLowerCase();let p="none";return"left"===c?p="left":"right"===c?p="right":"auto"===d&&"auto"===h&&(p="center"),{width:i||(e.offsetWidth?e.offsetWidth+"px":""),height:n||"",cellPadding:this._extractPxNumber(r),borderWidth:this._extractPxNumber(l),cellSpacing:this._extractPxNumber(a),hasCaption:!!s,captionText:s?s.textContent:"",alignment:p}}_extractPxNumber(e){if(null==e||""===e)return"";const t=String(e).match(/(-?\d+(?:\.\d+)?)/);return t?t[1]:""}_parseDimension(e,t){if(null==e)return"";const i=String(e).trim();if(!i)return"";const n=i.match(/^(-?\d+(?:\.\d+)?)\s*(px|%)?$/i);if(!n)return"";const o=parseFloat(n[1]);if(!isFinite(o)||o<0)return"";return o+(n[2]||t||"px").toLowerCase()}_applyTableProperties(e,t){const i=(e,t,i)=>{""===i||null==i?e.style.removeProperty(t):e.style.setProperty(t,i)},n=this._parseDimension(t.width,"px");i(e,"width",n),"100%"===n?i(e,"max-width","100%"):n&&i(e,"max-width","");const o=e.closest(".liteeditor-table-wrapper");this._syncWrapperWidth(o,e);i(e,"height",this._parseDimension(t.height,"px"));const r=null==t.cellSpacing||""===t.cellSpacing?"":parseInt(t.cellSpacing,10);if(""===r||isNaN(r)?(i(e,"border-spacing",""),i(e,"border-collapse","collapse")):r>0?(i(e,"border-spacing",r+"px"),i(e,"border-collapse","separate")):(i(e,"border-spacing","0"),i(e,"border-collapse","collapse")),""!==t.cellPadding&&null!=t.cellPadding){const i=parseInt(t.cellPadding,10);!isNaN(i)&&i>=0&&e.querySelectorAll("th, td").forEach(e=>{e.style.padding=i+"px"})}if(""!==t.borderWidth&&null!=t.borderWidth){const i=parseInt(t.borderWidth,10);if(!isNaN(i)&&i>=0){const t=e=>{const t=e.style.borderStyle||"solid",n=e.style.borderColor||"#ddd";0===i?e.style.border="0":(e.style.borderWidth=i+"px",e.style.borderStyle=t,e.style.borderColor=n)};t(e),e.querySelectorAll("th, td").forEach(t)}}const l=e.querySelector(":scope > caption");if(t.hasCaption){const i=(t.captionText||"").trim()||"Caption";if(l)l.textContent=i;else{const t=this.iframeDoc.createElement("caption");t.textContent=i,e.insertBefore(t,e.firstChild)}}else l&&l.remove();this._setTableAlign(e,t.alignment||"none")}_setTableAlign(e,t){const i=e.closest&&e.closest(".liteeditor-table-wrapper");if(["float","margin-left","margin-right"].forEach(t=>{e.style.removeProperty(t),i&&i.style.removeProperty(t)}),"center"===t){const t=(e.style.width||"").trim();t&&"100%"!==t||(e.style.width=e.offsetWidth+"px",e.style.maxWidth=""),e.style.marginLeft="auto",e.style.marginRight="auto",i&&(i.style.marginLeft="auto",i.style.marginRight="auto")}else"left"===t?(e.style.float="left",e.style.marginRight="12px",i&&(i.style.float="left",i.style.marginRight="12px")):"right"===t&&(e.style.float="right",e.style.marginLeft="12px",i&&(i.style.float="right",i.style.marginLeft="12px"))}_syncWrapperWidth(e,t){if(!e||!t)return;const i=(t.style.width||"").trim();i?e.style.width=i:e.style.removeProperty("width")}_syncWrapperAlignment(e,t){["float","margin-left","margin-right"].forEach(t=>e.style.removeProperty(t));const i=t.getAttribute("style")||"",n=e=>{const t=i.match(new RegExp(`(?:^|;)\\s*${e}\\s*:\\s*([^;]+)`,"i"));return t?t[1].trim().toLowerCase():""},o=n("float"),r=n("margin-left"),l=n("margin-right");"left"===o?(e.style.float="left",e.style.marginRight="12px"):"right"===o?(e.style.float="right",e.style.marginLeft="12px"):"auto"===r&&"auto"===l&&(e.style.marginLeft="auto",e.style.marginRight="auto")}_showTablePropertiesModal(e){if(!e)return;const t=this._readTableProperties(e),i=e=>String(null==e?"":e).replace(/&/g,"&amp;").replace(/"/g,"&quot;").replace(/</g,"&lt;").replace(/>/g,"&gt;"),n=`\n <div class="liteeditor-tabs">\n <button class="liteeditor-tab active" data-tab="general">General</button>\n </div>\n <div class="liteeditor-tab-content active" data-content="general">\n <div style="display: flex; gap: 12px;">\n <div class="liteeditor-form-group" style="flex: 1;">\n <label class="liteeditor-form-label">Width</label>\n <input type="text" class="liteeditor-form-input" id="tprop-width"\n placeholder="auto, 300px, 50%" value="${i(t.width)}">\n </div>\n <div class="liteeditor-form-group" style="flex: 1;">\n <label class="liteeditor-form-label">Height</label>\n <input type="text" class="liteeditor-form-input" id="tprop-height"\n placeholder="auto or 400px" value="${i(t.height)}">\n </div>\n </div>\n <div style="display: flex; gap: 12px;">\n <div class="liteeditor-form-group" style="flex: 1;">\n <label class="liteeditor-form-label">Cell spacing</label>\n <input type="number" class="liteeditor-form-input" id="tprop-spacing"\n min="0" placeholder="0" value="${i(t.cellSpacing)}">\n </div>\n <div class="liteeditor-form-group" style="flex: 1;">\n <label class="liteeditor-form-label">Cell padding</label>\n <input type="number" class="liteeditor-form-input" id="tprop-padding"\n min="0" placeholder="8" value="${i(t.cellPadding)}">\n </div>\n </div>\n <div style="display: flex; gap: 12px;">\n <div class="liteeditor-form-group" style="flex: 1;">\n <label class="liteeditor-form-label">Border width</label>\n <input type="number" class="liteeditor-form-input" id="tprop-border"\n min="0" placeholder="1" value="${i(t.borderWidth)}">\n </div>\n <div class="liteeditor-form-group" style="flex: 1;">\n <label class="liteeditor-form-label">Caption</label>\n <label style="display: inline-flex; align-items: center; gap: 8px; margin-top: 8px; font-size: 13px; color: #555;">\n <input type="checkbox" id="tprop-caption-on" ${t.hasCaption?"checked":""}>\n Show caption\n </label>\n </div>\n </div>\n <div class="liteeditor-form-group" id="tprop-caption-row" style="${t.hasCaption?"":"display: none;"}">\n <label class="liteeditor-form-label">Caption text</label>\n <input type="text" class="liteeditor-form-input" id="tprop-caption-text"\n placeholder="Caption" value="${i(t.captionText)}">\n </div>\n <div class="liteeditor-form-group">\n <label class="liteeditor-form-label">Alignment</label>\n <select class="liteeditor-form-input" id="tprop-align">\n ${o=t.alignment,r=[{v:"none",label:"None"},{v:"left",label:"Left"},{v:"center",label:"Center"},{v:"right",label:"Right"}],r.map(e=>`<option value="${e.v}"${e.v===o?" selected":""}>${e.label}</option>`).join("")}\n </select>\n </div>\n </div>\n `;var o,r;const l=this.showModal("Table properties",n,t=>{const i={width:t.querySelector("#tprop-width").value.trim(),height:t.querySelector("#tprop-height").value.trim(),cellSpacing:t.querySelector("#tprop-spacing").value.trim(),cellPadding:t.querySelector("#tprop-padding").value.trim(),borderWidth:t.querySelector("#tprop-border").value.trim(),hasCaption:t.querySelector("#tprop-caption-on").checked,captionText:t.querySelector("#tprop-caption-text").value.trim(),alignment:t.querySelector("#tprop-align").value};return this._applyTableProperties(e,i),this.syncContent(),this.saveState(),this.onContentChanged(),!0}),a=l.querySelector("#tprop-caption-on"),s=l.querySelector("#tprop-caption-row");a.addEventListener("change",()=>{s.style.display=a.checked?"":"none"});const c=l.querySelector('[data-action="confirm"]');c&&(c.textContent="Save")}wrapImage(e){e.classList.add("wrapped");const t=this.iframeDoc.createElement("span");t.className="liteeditor-image-resizer",t.contentEditable="false",t.setAttribute("data-liteeditor-chrome","1"),e.parentNode.insertBefore(t,e),t.appendChild(e);["nw","ne","sw","se","n","s","e","w"].forEach(i=>{const n=this.iframeDoc.createElement("span");n.className=`liteeditor-resize-handle ${i}`,n.dataset.position=i,n.setAttribute("data-liteeditor-chrome","1"),t.appendChild(n),n.addEventListener("mousedown",n=>{n.preventDefault(),n.stopPropagation(),this.startResize(n,t,e,i)})});const i=this.iframeDoc.createElement("span");i.className="liteeditor-image-info",i.setAttribute("data-liteeditor-chrome","1"),t.appendChild(i),this.updateImageInfo(t,e),this._buildImageToolbar(t,e),this.syncContent()}selectImage(e){this.deselectImage();const t=e.closest(".liteeditor-image-resizer");t&&t.classList.add("selected")}deselectImage(){this.contentArea.querySelectorAll(".liteeditor-image-resizer.selected").forEach(e=>e.classList.remove("selected"))}startResize(e,i,n,o){const r=e.clientX,l=e.clientY,a=n.offsetWidth,s=n.offsetHeight,c=a/s,d=e=>{e.preventDefault();let t=a,d=s;const h=e.clientX-r,p=e.clientY-l;switch(o){case"se":case"ne":case"e":t=Math.max(50,a+h),d=t/c;break;case"sw":case"nw":case"w":t=Math.max(50,a-h),d=t/c;break;case"s":d=Math.max(50,s+p),t=d*c;break;case"n":d=Math.max(50,s-p),t=d*c}n.style.width=t+"px",n.style.height="auto",n.style.maxWidth="100%",n.removeAttribute("width"),n.removeAttribute("height"),this.updateImageInfo(i,n)},h=()=>{this.iframeDoc.removeEventListener("mousemove",d),this.iframeDoc.removeEventListener("mouseup",p),t.removeEventListener("mousemove",d),t.removeEventListener("mouseup",p),this._activeResize===h&&(this._activeResize=null)},p=()=>{h(),this.syncContent(),this.saveState(),this.onContentChanged()};this._activeResize=h,this.iframeDoc.addEventListener("mousemove",d),this.iframeDoc.addEventListener("mouseup",p),t.addEventListener("mousemove",d),t.addEventListener("mouseup",p)}updateImageInfo(e,t){const i=e.querySelector(".liteeditor-image-info");if(i){const e=t.offsetWidth||t.naturalWidth,n=t.offsetHeight||t.naturalHeight;i.textContent=`${Math.round(e)} × ${Math.round(n)}`}}wrapRangeInMark(e){const t=this.iframeDoc,i="g"+(++this._searchGroupCounter||(this._searchGroupCounter=1));let n=e.startContainer,o=e.startOffset,r=e.endContainer,l=e.endOffset;if(n===r&&n.nodeType===Node.TEXT_NODE){n.splitText(l);const e=n.splitText(o),r=t.createElement("mark");return r.className="liteeditor-search-highlight",r.dataset.group=i,r.textContent=e.nodeValue,void e.parentNode.replaceChild(r,e)}const a=e.commonAncestorContainer,s=t.createTreeWalker(a.nodeType===Node.TEXT_NODE?a.parentNode:a,NodeFilter.SHOW_TEXT,null),c=[];for(;s.nextNode();){const t=s.currentNode;e.intersectsNode(t)&&c.push(t)}c.forEach(e=>{let a=0,s=e.nodeValue.length;if(e===n&&(a=o),e===r&&(s=l),a>=s)return;let c=e;s<e.nodeValue.length&&c.splitText(s),a>0&&(c=c.splitText(a));const d=t.createElement("mark");d.className="liteeditor-search-highlight",d.dataset.group=i,d.textContent=c.nodeValue,c.parentNode.replaceChild(d,c)})}groupMarks(e){const t=new Map;return e.forEach(e=>{const i=e.dataset.group||e;t.has(i)||t.set(i,[]),t.get(i).push(e)}),Array.from(t.values())}sanitizeHTML(e){const i=t.createElement("div");i.innerHTML=e,n.stripChromeIn(i),n.normalizePasted(i,this._pasteOpts),n.applyDefaultStyles(i,this._defaultStyles);["script","iframe","object","embed","applet","svg","math","form","base","meta","link","style","template","noscript","title"].forEach(e=>{i.querySelectorAll(e).forEach(e=>e.remove())});const o=["href","src","action","poster","xlink:href","background","data","ping","formaction"];return i.querySelectorAll("*").forEach(e=>{Array.from(e.attributes).forEach(t=>{const i=t.name.toLowerCase();if(i.startsWith("on")||"srcdoc"===i)e.removeAttribute(t.name);else if(o.includes(i)){const o="IMG"===e.tagName&&"src"===i,r=n.sanitizeUrl(t.value,{allowDataImage:o});r?r!==t.value&&e.setAttribute(t.name,r):e.removeAttribute(t.name)}})}),i.innerHTML}getActiveFormats(){const e={bold:!1,italic:!1,underline:!1,strikethrough:!1,block:null},t=this.iframe&&this.iframe.contentWindow;if(!t)return e;const i=t.getSelection();if(!i||0===i.rangeCount)return e;let n=i.anchorNode;n&&3===n.nodeType&&(n=n.parentNode);const o={p:"p",h1:"h1",h2:"h2",h3:"h3",h4:"h4",h5:"h5",h6:"h6",blockquote:"blockquote",pre:"pre"};for(;n&&n!==this.contentArea;){if(1===n.nodeType){const i=n.tagName.toLowerCase();"strong"!==i&&"b"!==i||(e.bold=!0),"em"!==i&&"i"!==i||(e.italic=!0),"u"===i&&(e.underline=!0),"s"!==i&&"strike"!==i&&"del"!==i||(e.strikethrough=!0),!e.block&&o[i]&&(e.block=o[i]);try{const i=t.getComputedStyle(n);if(i){if(!e.bold){const t=parseInt(i.fontWeight,10);!isNaN(t)&&t>=700?e.bold=!0:"bold"!==i.fontWeight&&"bolder"!==i.fontWeight||(e.bold=!0)}e.italic||"italic"!==i.fontStyle||(e.italic=!0);const t=i.textDecorationLine||i.textDecoration||"";!e.underline&&t.indexOf("underline")>=0&&(e.underline=!0),!e.strikethrough&&t.indexOf("line-through")>=0&&(e.strikethrough=!0)}}catch(e){}}n=n.parentNode}try{e.bold||(e.bold=this.iframeDoc.queryCommandState("bold")),e.italic||(e.italic=this.iframeDoc.queryCommandState("italic")),e.underline||(e.underline=this.iframeDoc.queryCommandState("underline")),e.strikethrough||(e.strikethrough=this.iframeDoc.queryCommandState("strikeThrough"))}catch(e){}return e}updateToolbarState(){const e=this.getActiveFormats();if(this.toolbar.querySelectorAll(".liteeditor-btn").forEach(t=>{const i=t.dataset.command;if("bold"===i)t.classList.toggle("active",e.bold);else if("italic"===i)t.classList.toggle("active",e.italic);else if("underline"===i)t.classList.toggle("active",e.underline);else if("strikethrough"===i)t.classList.toggle("active",e.strikethrough);else if("numlist"===i||"bullist"===i){const e="numlist"===i?"insertOrderedList":"insertUnorderedList";t.classList.toggle("active",this.iframeDoc.queryCommandState(e))}}),e.block){const t={p:"Paragraph",h1:"Heading 1",h2:"Heading 2",h3:"Heading 3",h4:"Heading 4",h5:"Heading 5",h6:"Heading 6",blockquote:"Quote",pre:"Preformatted"},i=this.toolbar.querySelector('[data-command="blocks"] .liteeditor-btn-label');i&&t[e.block]&&(i.textContent=t[e.block])}}saveState(){const e=this.contentArea.innerHTML;this.history.stack[this.history.currentIndex]!==e&&(this.history.stack=this.history.stack.slice(0,this.history.currentIndex+1),this.history.stack.push(e),this.history.currentIndex++,this.history.stack.length>this.history.maxSize&&(this.history.stack.shift(),this.history.currentIndex--))}_scheduleSaveState(){this._saveStateTimer&&clearTimeout(this._saveStateTimer),this._saveStateTimer=setTimeout(()=>{this._saveStateTimer=null,this.saveState()},400)}_flushSaveState(){this._saveStateTimer&&(clearTimeout(this._saveStateTimer),this._saveStateTimer=null,this.saveState())}undo(){this._flushSaveState(),this.history.currentIndex>0&&(this.history.currentIndex--,this.contentArea.innerHTML=this.history.stack[this.history.currentIndex],this.rebindImageHandles(),this.syncContent(),this.onContentChanged())}redo(){this._flushSaveState(),this.history.currentIndex<this.history.stack.length-1&&(this.history.currentIndex++,this.contentArea.innerHTML=this.history.stack[this.history.currentIndex],this.rebindImageHandles(),this.syncContent(),this.onContentChanged())}rebindImageHandles(){this.contentArea.querySelectorAll('.liteeditor-image-resizer, [data-liteeditor-chrome="1"].liteeditor-image-resizer').forEach(e=>{const t=e.querySelector("img");t?(t.classList.remove("wrapped"),e.parentNode.replaceChild(t,e)):e.remove()});this.contentArea.querySelectorAll(".liteeditor-table-wrapper").forEach(e=>{const t=e.querySelector(":scope > table");t?e.parentNode.replaceChild(t,e):e.remove()}),this.contentArea.querySelectorAll('.liteeditor-resize-handle, .liteeditor-image-info, [data-liteeditor-chrome="1"]').forEach(e=>e.remove())}onContentChanged(){this._contentListeners&&this._contentListeners.forEach(e=>{try{e()}catch(e){}})}addContentListener(e){this._contentListeners||(this._contentListeners=[]),this._contentListeners.push(e)}syncContent(){this.element.value=this.getCleanHTML(this.contentArea);const e=new Event("change",{bubbles:!0});this.element.dispatchEvent(e)}restoreContent(){this.contentArea.innerHTML=this.sanitizeHTML(this.content),n.stripChromeIn(this.contentArea),n.normalizePasted(this.contentArea,this._pasteOpts),n.applyDefaultStyles(this.contentArea,this._defaultStyles)}applyLicenseState(i){if(!i||i.valid||this._licenseInvalid)return;this._licenseInvalid=!0;try{this.contentArea&&this.contentArea.setAttribute("contenteditable","false")}catch(e){}if(this.toolbar&&(this.toolbar.style.pointerEvents="none",this.toolbar.style.opacity="0.5"),!this.editorContainer||this._licenseNotice)return;const n=this.config&&this.config.portalUrl||"https://app.liteeditor.com",o={domain_not_allowed:{level:"warning",text:'The domain "'+(e.location&&e.location.hostname||"this domain")+'" is not registered for this LiteEditor API key.',label:"Register this domain",href:n+"/dashboard"},invalid_key:{level:"error",text:"This LiteEditor API key could not be validated.",label:"Get a free API key",href:n+"/register"},missing_key:{level:"warning",text:"No LiteEditor API key was found. Add your key to the editor script.",label:"View setup docs",href:"https://liteeditor.com/docs#installation"},inactive_subscription:{level:"error",text:"This LiteEditor API key's plan is inactive.",label:"Manage billing",href:n+"/dashboard"}},r=o[i.reason||"invalid_key"]||o.invalid_key,l=t.createElement("div");l.className="liteeditor-license-notice liteeditor-license-notice--"+r.level,l.setAttribute("data-liteeditor-chrome","1"),l.setAttribute("role","alert"),l.style.cssText='display:flex;align-items:center;gap:8px;padding:10px 14px;font:13px/1.45 -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;'+("error"===r.level?"background:#fef2f2;color:#991b1b;border-bottom:1px solid #fecaca;":"background:#fffbeb;color:#92400e;border-bottom:1px solid #fde68a;");const a=t.createElement("span");a.textContent="⚠",a.style.cssText="font-size:15px;line-height:1;",l.appendChild(a);const s=t.createElement("span");s.textContent=r.text,s.style.flex="1",l.appendChild(s);const c=t.createElement("a");c.href=r.href,c.target="_blank",c.rel="noopener noreferrer",c.textContent=r.label+" →",c.style.cssText="font-weight:600;color:inherit;text-decoration:underline;white-space:nowrap;",l.appendChild(c),this.toolbar&&this.toolbar.parentNode===this.editorContainer?this.toolbar.insertAdjacentElement("afterend",l):this.editorContainer.insertBefore(l,this.editorContainer.firstChild),this._licenseNotice=l}getContent(){return this.sanitizeHTML(this.getCleanHTML(this.contentArea))}getCleanHTML(e){const t=e.cloneNode(!0);return n.stripChromeIn(t),t.querySelectorAll("mark.liteeditor-search-highlight").forEach(t=>{const i=e.ownerDocument.createTextNode(t.textContent);t.parentNode.replaceChild(i,t)}),n.normalizePasted(t,this._pasteOpts),n.applyDefaultStyles(t,this._defaultStyles),t.innerHTML}setContent(e){this.contentArea.innerHTML=this.sanitizeHTML(e),this.syncContent(),this.saveState(),this.onContentChanged()}toggleSourceCode(){if(this.sourceCodeMode){this.sourceCodeMode=!1;const e=this.sourceTextarea?this.sourceTextarea.value:"";this.contentArea.innerHTML=this.sanitizeHTML(e),this.contentArea.contentEditable="true",this.sourceTextarea=null;const t=this.toolbar.querySelector('[data-command="sourcecode"]');t&&t.classList.remove("active"),this.syncContent(),this.saveState(),this.onContentChanged()}else{this.sourceCodeMode=!0;const e=this.getCleanHTML(this.contentArea);this.contentArea.contentEditable="false",this.contentArea.innerHTML="";const t=this.iframeDoc.createElement("textarea");t.className="liteeditor-source-code",t.value=this.formatHTML(e),t.style.cssText=`\n width: 100%;\n height: 100%;\n min-height: ${this.config.height||150}px;\n padding: 12px;\n font-family: 'Courier New', Consolas, Monaco, monospace;\n font-size: 13px;\n line-height: 1.6;\n border: none;\n outline: none;\n resize: none;\n background: #f8f9fa;\n color: #333;\n tab-size: 4;\n box-sizing: border-box;\n `,this.contentArea.appendChild(t),this.sourceTextarea=t,t.focus();const i=this.toolbar.querySelector('[data-command="sourcecode"]');i&&i.classList.add("active")}}formatHTML(e){let t=e,i=0;t=t.replace(/(<\/(div|p|h[1-6]|ul|ol|li|table|tr|td|th|blockquote|pre)>)/gi,"$1\n"),t=t.replace(/(<(div|p|h[1-6]|ul|ol|li|table|tr|td|th|blockquote|pre)[^>]*>)/gi,"\n$1"),t=t.replace(/<br\s*\/?>/gi,"<br>\n");const n=t.split("\n"),o=[];return n.forEach(e=>{(e=e.trim())&&(e.match(/^<\/(div|p|h[1-6]|ul|ol|li|table|tr|td|th|blockquote|pre)/i)&&(i=Math.max(0,i-1)),o.push(" ".repeat(i)+e),e.match(/<(div|p|h[1-6]|ul|ol|li|table|tr|td|th|blockquote|pre)[^>]*>$/i)&&!e.match(/<(div|p|h[1-6]|ul|ol|li|table|tr|td|th|blockquote|pre)[^>]*>.*<\/\1>/i)&&i++)}),o.join("\n")}destroy(){if(!this._destroyed){if(this._destroyed=!0,this._saveStateTimer&&(clearTimeout(this._saveStateTimer),this._saveStateTimer=null),this._closeDropdowns&&t.removeEventListener("click",this._closeDropdowns),this._onResizeMove&&t.removeEventListener("mousemove",this._onResizeMove),this._onResizeUp&&t.removeEventListener("mouseup",this._onResizeUp),this._imageObserver&&(this._imageObserver.disconnect(),this._imageObserver=null),this._onFormSubmit&&this.element&&this.element.form&&(this.element.form.removeEventListener("submit",this._onFormSubmit,!0),this._onFormSubmit=null),this._onToolbarMouseDown&&this.toolbar&&(this.toolbar.removeEventListener("mousedown",this._onToolbarMouseDown),this._onToolbarMouseDown=null),this._onSelectionChange&&this.iframeDoc&&(this.iframeDoc.removeEventListener("selectionchange",this._onSelectionChange),this._onSelectionChange=null),this._openPickers&&(Array.from(this._openPickers).forEach(e=>{try{e()}catch(e){}}),this._openPickers.clear()),this._activeResize){try{this._activeResize()}catch(e){}this._activeResize=null}if(this._activeReaders&&(this._activeReaders.forEach(e=>{try{e.abort()}catch(e){}}),this._activeReaders.clear()),this._closeSearchPanel){try{this._closeSearchPanel()}catch(e){}this._closeSearchPanel=null}this.searchPanel&&(this.searchPanel.remove(),this.searchPanel=null),this.editorContainer.remove(),this.element.style.display="",delete this.element.dataset.liteeditorId}}}const r=["#000000","#434343","#666666","#999999","#b7b7b7","#cccccc","#d9d9d9","#efefef","#f3f3f3","#ffffff","#980000","#ff0000","#ff9900","#ffff00","#00ff00","#00ffff","#4a86e8","#0000ff","#9900ff","#ff00ff","#e6b8af","#f4cccc","#fce5cd","#fff2cc","#d9ead3","#d0e0e3","#c9daf8","#cfe2f3","#d9d2e9","#ead1dc","#cc4125","#e06666","#f6b26b","#ffd966","#93c47d","#76a5af","#6d9eeb","#6fa8dc","#8e7cc3","#c27ba0"],l={undo:{title:"Undo",icon:"↶",type:"button"},redo:{title:"Redo",icon:"↷",type:"button"},blocks:{title:"Blocks",icon:"¶",type:"dropdown",showValue:!0,defaultLabel:"Paragraph",options:[{label:"Paragraph",value:"p",action:e=>{e.execCommand("formatBlock","p");const t=e.toolbar.querySelector('[data-command="blocks"] .liteeditor-btn-label');t&&(t.textContent="Paragraph")}},{label:"Heading 1",value:"h1",action:e=>{e.execCommand("formatBlock","h1");const t=e.toolbar.querySelector('[data-command="blocks"] .liteeditor-btn-label');t&&(t.textContent="Heading 1")}},{label:"Heading 2",value:"h2",action:e=>{e.execCommand("formatBlock","h2");const t=e.toolbar.querySelector('[data-command="blocks"] .liteeditor-btn-label');t&&(t.textContent="Heading 2")}},{label:"Heading 3",value:"h3",action:e=>{e.execCommand("formatBlock","h3");const t=e.toolbar.querySelector('[data-command="blocks"] .liteeditor-btn-label');t&&(t.textContent="Heading 3")}},{label:"Heading 4",value:"h4",action:e=>{e.execCommand("formatBlock","h4");const t=e.toolbar.querySelector('[data-command="blocks"] .liteeditor-btn-label');t&&(t.textContent="Heading 4")}},{label:"Heading 5",value:"h5",action:e=>{e.execCommand("formatBlock","h5");const t=e.toolbar.querySelector('[data-command="blocks"] .liteeditor-btn-label');t&&(t.textContent="Heading 5")}},{label:"Heading 6",value:"h6",action:e=>{e.execCommand("formatBlock","h6");const t=e.toolbar.querySelector('[data-command="blocks"] .liteeditor-btn-label');t&&(t.textContent="Heading 6")}},{label:"Preformatted",value:"pre",action:e=>{e.execCommand("formatBlock","pre");const t=e.toolbar.querySelector('[data-command="blocks"] .liteeditor-btn-label');t&&(t.textContent="Preformatted")}},{label:"Quote",value:"blockquote",action:e=>{e.execCommand("formatBlock","blockquote");const t=e.toolbar.querySelector('[data-command="blocks"] .liteeditor-btn-label');t&&(t.textContent="Quote")}}]},fontfamily:{title:"Font Family",icon:"Aa",type:"dropdown",showValue:!0,defaultLabel:"System Font",options:[{label:"System Font",value:""},{label:"Arial",value:"Arial, sans-serif"},{label:"Courier New",value:"Courier New, monospace"},{label:"Georgia",value:"Georgia, serif"},{label:"Times New Roman",value:"Times New Roman, serif"},{label:"Trebuchet MS",value:"Trebuchet MS, sans-serif"},{label:"Verdana",value:"Verdana, sans-serif"}].map(e=>({label:e.label,action:t=>{e.value?t.execCommand("fontName",e.value):t.removeFormatting();const i=t.toolbar.querySelector('[data-command="fontfamily"] .liteeditor-btn-label');i&&(i.textContent=e.label)}}))},fontsize:{title:"Font Size",icon:"A⁺",type:"dropdown",showValue:!0,defaultLabel:"12pt",options:["8pt","10pt","12pt","14pt","16pt","18pt","20pt","24pt","28pt","32pt","36pt","48pt"].map(e=>({label:e,action:t=>{t.setFontSize(e);const i=t.toolbar.querySelector('[data-command="fontsize"] .liteeditor-btn-label');i&&(i.textContent=e)}}))},bold:{title:"Bold",icon:"<strong>B</strong>",type:"button",value:null},italic:{title:"Italic",icon:"<em>I</em>",type:"button",value:null},underline:{title:"Underline",icon:"<u>U</u>",type:"button",value:null},strikethrough:{title:"Strikethrough",icon:"<s>S</s>",type:"button",value:null},link:{title:"Insert Link",icon:"🔗",type:"dialog",action:e=>{e.showLinkModal()}},image:{title:"Insert Image",icon:"🖼",type:"dialog",action:e=>{e.showImageModal()}},media:{title:"Insert Media",icon:"📹",type:"dialog",action:e=>{e.showMediaModal()}},table:{title:"Insert Table",icon:"⊞",type:"dialog",action:e=>{e.showTableModal()}},align:{title:"Align",icon:'<svg width="14" height="14" viewBox="0 0 14 14"><line x1="1" y1="3" x2="13" y2="3" stroke="currentColor" stroke-width="1.5"/><line x1="1" y1="6.5" x2="9" y2="6.5" stroke="currentColor" stroke-width="1.5"/><line x1="1" y1="10" x2="13" y2="10" stroke="currentColor" stroke-width="1.5"/></svg>',type:"dropdown",dropdownOpts:{detectActive:e=>e.detectCurrentAlignment()},options:[{key:"left",label:"Left",icon:'<svg width="14" height="14" viewBox="0 0 14 14"><line x1="1" y1="3" x2="13" y2="3" stroke="currentColor" stroke-width="1.5"/><line x1="1" y1="6.5" x2="9" y2="6.5" stroke="currentColor" stroke-width="1.5"/><line x1="1" y1="10" x2="13" y2="10" stroke="currentColor" stroke-width="1.5"/></svg>',action:e=>e.setAlignment("left")},{key:"center",label:"Center",icon:'<svg width="14" height="14" viewBox="0 0 14 14"><line x1="1" y1="3" x2="13" y2="3" stroke="currentColor" stroke-width="1.5"/><line x1="3" y1="6.5" x2="11" y2="6.5" stroke="currentColor" stroke-width="1.5"/><line x1="1" y1="10" x2="13" y2="10" stroke="currentColor" stroke-width="1.5"/></svg>',action:e=>e.setAlignment("center")},{key:"right",label:"Right",icon:'<svg width="14" height="14" viewBox="0 0 14 14"><line x1="1" y1="3" x2="13" y2="3" stroke="currentColor" stroke-width="1.5"/><line x1="5" y1="6.5" x2="13" y2="6.5" stroke="currentColor" stroke-width="1.5"/><line x1="1" y1="10" x2="13" y2="10" stroke="currentColor" stroke-width="1.5"/></svg>',action:e=>e.setAlignment("right")},{key:"justify",label:"Justify",icon:'<svg width="14" height="14" viewBox="0 0 14 14"><line x1="1" y1="3" x2="13" y2="3" stroke="currentColor" stroke-width="1.5"/><line x1="1" y1="6.5" x2="13" y2="6.5" stroke="currentColor" stroke-width="1.5"/><line x1="1" y1="10" x2="13" y2="10" stroke="currentColor" stroke-width="1.5"/></svg>',action:e=>e.setAlignment("justify")}]},alignleft:{title:"Align Left",icon:'<svg width="14" height="14" viewBox="0 0 14 14"><line x1="1" y1="3" x2="13" y2="3" stroke="currentColor" stroke-width="1.5"/><line x1="1" y1="6.5" x2="9" y2="6.5" stroke="currentColor" stroke-width="1.5"/><line x1="1" y1="10" x2="13" y2="10" stroke="currentColor" stroke-width="1.5"/></svg>',type:"dialog",action:e=>e.setAlignment("left")},aligncenter:{title:"Align Center",icon:'<svg width="14" height="14" viewBox="0 0 14 14"><line x1="1" y1="3" x2="13" y2="3" stroke="currentColor" stroke-width="1.5"/><line x1="3" y1="6.5" x2="11" y2="6.5" stroke="currentColor" stroke-width="1.5"/><line x1="1" y1="10" x2="13" y2="10" stroke="currentColor" stroke-width="1.5"/></svg>',type:"dialog",action:e=>e.setAlignment("center")},alignright:{title:"Align Right",icon:'<svg width="14" height="14" viewBox="0 0 14 14"><line x1="1" y1="3" x2="13" y2="3" stroke="currentColor" stroke-width="1.5"/><line x1="5" y1="6.5" x2="13" y2="6.5" stroke="currentColor" stroke-width="1.5"/><line x1="1" y1="10" x2="13" y2="10" stroke="currentColor" stroke-width="1.5"/></svg>',type:"dialog",action:e=>e.setAlignment("right")},alignjustify:{title:"Justify",icon:'<svg width="14" height="14" viewBox="0 0 14 14"><line x1="1" y1="3" x2="13" y2="3" stroke="currentColor" stroke-width="1.5"/><line x1="1" y1="6.5" x2="13" y2="6.5" stroke="currentColor" stroke-width="1.5"/><line x1="1" y1="10" x2="13" y2="10" stroke="currentColor" stroke-width="1.5"/></svg>',type:"dialog",action:e=>e.setAlignment("justify")},forecolor:{title:"Text Color",icon:'<span style="display:inline-block;border-bottom:3px solid #e53935;padding:0 2px;font-weight:bold;">A</span>',type:"dialog",action:e=>e.showColorPicker("forecolor")},backcolor:{title:"Background Color",icon:'<span style="display:inline-block;background:#fff59d;padding:0 4px;font-weight:bold;border-radius:2px;">A</span>',type:"dialog",action:e=>e.showColorPicker("backcolor")},lineheight:{title:"Line Height",icon:"≣",type:"dialog",action:e=>e.showLineHeightPicker()},numlist:function(){const e=e=>`<ol class="liteeditor-list-card" style="list-style-type:${e}"><li><span></span></li><li><span></span></li><li><span></span></li></ol>`;return{title:"Numbered List",icon:'<svg width="16" height="14" viewBox="0 0 16 14" fill="none"><text x="0" y="4" font-size="4" font-family="Arial,sans-serif" font-weight="600" fill="currentColor">1.</text><line x1="5" y1="3" x2="15" y2="3" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/><text x="0" y="8.5" font-size="4" font-family="Arial,sans-serif" font-weight="600" fill="currentColor">2.</text><line x1="5" y1="7.5" x2="15" y2="7.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/><text x="0" y="13" font-size="4" font-family="Arial,sans-serif" font-weight="600" fill="currentColor">3.</text><line x1="5" y1="12" x2="15" y2="12" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>',type:"dropdown",dropdownOpts:{variant:"grid",detectActive:e=>e.detectCurrentListStyle("ol")},options:[{key:"none",label:"None (remove list)",html:'<div class="liteeditor-list-card liteeditor-list-card-none"><span></span>None</div>',action:e=>e.removeList()},{key:"decimal",label:"Default (1. 2. 3.)",html:e("decimal"),action:e=>e.setListStyle("ol","decimal")},{key:"lower-alpha",label:"Lower alpha (a. b. c.)",html:e("lower-alpha"),action:e=>e.setListStyle("ol","lower-alpha")},{key:"lower-roman",label:"Lower roman (i. ii. iii.)",html:e("lower-roman"),action:e=>e.setListStyle("ol","lower-roman")},{key:"upper-alpha",label:"Upper alpha (A. B. C.)",html:e("upper-alpha"),action:e=>e.setListStyle("ol","upper-alpha")},{key:"upper-roman",label:"Upper roman (I. II. III.)",html:e("upper-roman"),action:e=>e.setListStyle("ol","upper-roman")}]}}(),bullist:function(){const e=e=>`<ul class="liteeditor-list-card" style="list-style-type:${e}"><li><span></span></li><li><span></span></li><li><span></span></li></ul>`;return{title:"Bullet List",icon:'<svg width="16" height="14" viewBox="0 0 16 14" fill="none"><circle cx="2" cy="3" r="1.2" fill="currentColor"/><line x1="6" y1="3" x2="15" y2="3" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/><circle cx="2" cy="7" r="1.2" fill="currentColor"/><line x1="6" y1="7" x2="15" y2="7" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/><circle cx="2" cy="11" r="1.2" fill="currentColor"/><line x1="6" y1="11" x2="15" y2="11" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>',type:"dropdown",dropdownOpts:{variant:"grid",detectActive:e=>e.detectCurrentListStyle("ul")},options:[{key:"none",label:"None (remove list)",html:'<div class="liteeditor-list-card liteeditor-list-card-none"><span></span>None</div>',action:e=>e.removeList()},{key:"default",label:"Default (Nested)",html:'<ul class="liteeditor-list-card liteeditor-list-card-nested" style="list-style-type:disc"><li><span></span><ul style="list-style-type:circle"><li><span></span><ul style="list-style-type:square"><li><span></span></li></ul></li></ul></li></ul>',action:e=>e.setListStyle("ul","default")},{key:"disc",label:"Disc",html:e("disc"),action:e=>e.setListStyle("ul","disc")},{key:"circle",label:"Circle",html:e("circle"),action:e=>e.setListStyle("ul","circle")},{key:"square",label:"Square",html:e("square"),action:e=>e.setListStyle("ul","square")}]}}(),indent:{title:"Indent",icon:"→",type:"button",value:null},outdent:{title:"Outdent",icon:"←",type:"button",value:null},emoticons:{title:"Emoticons",icon:"😀",type:"dropdown",options:["😀","😃","😄","😁","😅","😂","🤣","😊","😇","🙂","😉","😌","😍","🥰","😘","😗","😙","😚","😋","😛","😝","😜","🤪","🤨","🧐","🤓","😎","🤩","🥳","👍","👎","👌","✌️","🤞","🤝","👏","🙌","❤️","💔","💕","💖","💗","💙","💚","💛","🧡","💜","🖤","💯","✨","⭐","🌟","💫","🔥","💥"].map(e=>({label:e,action:t=>t.execCommand("insertHTML",e)}))},charmap:{title:"Special Characters",icon:"Ω",type:"dropdown",options:["©","®","™","€","£","¥","¢","§","¶","°","±","×","÷","≠","≈","≤","≥","µ","π","∞","∑","√","∫","∂","α","β","γ","δ","←","→","↑","↓","↔","⇐","⇒","⇑","⇓","⇔","•","◦","▪","▫","□","■","○","●","△","▲","▽","▼"].map(e=>({label:e,action:t=>t.execCommand("insertHTML",e)}))},removeformat:{title:"Clear Formatting",icon:'<svg width="14" height="14" viewBox="0 0 16 16" fill="none"><path d="M3.5 3h9" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/><path d="M6.5 3l-1.5 9" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/><path d="M9.5 3l-.6 3.6" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/><path d="M10 10.5l3 3M13 10.5l-3 3" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>',type:"button",value:null},sourcecode:{title:"Source Code",icon:"&lt;/&gt;",type:"dialog",action:e=>{e.toggleSourceCode()}},searchreplace:{title:"Search & Replace",icon:"🔍",type:"dialog",action:e=>{e.showSearchReplace()}},codesample:{title:"Code Sample",icon:"{ }",type:"dialog",action:e=>{e.showCodeSampleModal()}},visualblocks:{title:"Visual Blocks",icon:"☐",type:"dialog",action:e=>{e.contentArea.classList.toggle("liteeditor-visualblocks");const t=e.toolbar.querySelector('[data-command="visualblocks"]');t&&t.classList.toggle("active",e.contentArea.classList.contains("liteeditor-visualblocks"))}},anchor:{title:"Insert Anchor",icon:"⚓",type:"dialog",action:e=>{e.showAnchorModal()}}},a={anchor:class{constructor(e){this.editor=e}},autolink:class{constructor(e){this.editor=e,this.init()}init(){this.editor.contentArea.addEventListener("keyup",e=>{" "!==e.key&&"Enter"!==e.key||this.detectLinks(e.key)})}detectLinks(e){const t=this.editor.iframeDoc,i=/https?:\/\/[^\s<>]+?(?=[.,;:!?\)\]'"]*(?:\s|$))/g,n=this.editor.iframe.contentWindow.getSelection();if(!n||0===n.rangeCount)return;const o=n.getRangeAt(0);if(!o.collapsed)return;let r=o.startContainer,l=o.startOffset;if(r.nodeType!==Node.TEXT_NODE){const e=i=>{let n=i.previousSibling;for(;n;){if(n.nodeType===Node.TEXT_NODE&&n.nodeValue.length)return n;if(n.nodeType===Node.ELEMENT_NODE){const e=t.createTreeWalker(n,NodeFilter.SHOW_TEXT,null);let i=null;for(;e.nextNode();)i=e.currentNode;if(i)return i}n=n.previousSibling}return i.parentNode?e(i.parentNode):null},i=e(r);if(!i)return;r=i,l=i.nodeValue.length}if(r.parentNode&&r.parentNode.closest&&r.parentNode.closest("a"))return;const a=r.nodeValue.slice(0,l);i.lastIndex=0;let s,c=null;for(;null!==(s=i.exec(a));)c=s;if(!c)return;const d=c.index,h=c[0],p=d+h.length,u=r.splitText(p),m=r.splitText(d),f=t.createElement("a");if(f.href=h,f.textContent=h,f.target="_blank",f.rel="noopener noreferrer",m.parentNode.replaceChild(f,m)," "===e){const e=t.createRange(),i=Math.min(1,u.nodeValue.length);e.setStart(u,i),e.collapse(!0),n.removeAllRanges(),n.addRange(e)}}},charmap:class{constructor(e){this.editor=e}},codesample:class{constructor(e){this.editor=e}},emoticons:class{constructor(e){this.editor=e}},image:class{constructor(e){this.editor=e}},link:class{constructor(e){this.editor=e}},lists:class{constructor(e){this.editor=e}},media:class{constructor(e){this.editor=e}},searchreplace:class{constructor(e){this.editor=e}},table:class{constructor(e){this.editor=e}},visualblocks:class{constructor(e){this.editor=e,this.init()}init(){const e=this.editor.iframeDoc.createElement("style");e.id="liteeditor-visualblocks-style";const t=["p","h1","h2","h3","h4","h5","h6","div","blockquote","ul","ol","table","pre","section","article","aside","header","footer"],i=t.map(e=>`body.liteeditor-visualblocks ${e}`).join(",\n"),n=t.map(e=>`body.liteeditor-visualblocks ${e}::before`).join(",\n"),o=t.map(e=>`body.liteeditor-visualblocks ${e}::before { content: '${e}'; }`).join("\n");e.textContent=`\n ${i} {\n outline: 1px dashed #bbb;\n outline-offset: 2px;\n position: relative;\n padding-top: 20px !important;\n margin-top: 8px;\n }\n ${n} {\n position: absolute;\n top: 0; left: 0;\n font-size: 10px; font-weight: bold;\n color: #999; background: #f0f0f0;\n padding: 1px 6px; border-radius: 0 0 3px 0;\n text-transform: uppercase;\n font-family: -apple-system, BlinkMacSystemFont, sans-serif;\n line-height: 1.4;\n }\n ${o}\n `,this.editor.iframeDoc.head.appendChild(e)}},wordcount:class{constructor(e){this.editor=e,this.init()}init(){const e=t.createElement("div");e.className="liteeditor-wordcount",this.editor.editorContainer.appendChild(e);const i=()=>this.updateCount(e);this.editor.addContentListener(i),i()}updateCount(e){const t=this.editor.contentArea.textContent||"",i=t.trim().split(/\s+/).filter(e=>e.length>0).length,n=t.length;e.textContent=`Words: ${i} | Characters: ${n}`}}};e.liteeditor=new n}(window,document);
11
+ !function(e,t){"use strict";const i=t.currentScript;class n{constructor(){this.instances=new Map,this.instanceCounter=0,this.version="1.2.4",this.apiKey=null,this.apiBase=null,this._licensePromises={},this._license=null}configure(e={}){return e.apiKey&&(this.apiKey=String(e.apiKey)),e.apiBase&&(this.apiBase=String(e.apiBase)),this}getLicense(){const e=this._license||{valid:!1};return{valid:!!e.valid,features:e.features||[],token:e.token||null}}static DEFAULT_STYLES={table:"border-collapse: collapse; width: 100%; max-width: 100%; margin: 10px 0;",th:"border: 1px solid #ddd; padding: 8px; background: #f2f2f2; color: #000; text-align: left; font-weight: bold;",td:"border: 1px solid #ddd; padding: 8px;",blockquote:"border-left: 4px solid #ccc; padding: 10px 20px; margin: 10px 0; background: #f9f9f9;",pre:"background: #f4f4f4; padding: 10px; border-radius: 5px; overflow-x: auto; margin: 10px 0; font-family: 'Courier New', Consolas, Monaco, monospace;",code:"background: #f4f4f4; padding: 2px 6px; border-radius: 3px; font-family: 'Courier New', Consolas, Monaco, monospace;",hr:"border: none; border-top: 1px solid #ddd; margin: 15px 0;",img:"max-width: 100%; height: auto;",ul:"margin: 10px 0; padding-left: 40px; list-style-type: disc;",ol:"margin: 10px 0; padding-left: 40px; list-style-type: decimal;",li:"margin: 5px 0;"};static resolveStyles(e){return!1===e?null:e?Object.assign({},n.DEFAULT_STYLES,e):Object.assign({},n.DEFAULT_STYLES)}static sanitizeUrl(e,t={}){if(null==e)return"";const i=String(e).trim();if(!i)return"";const n=i.replace(/[\u0000-\u0020\u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000]/g,"").toLowerCase(),o=(n.match(/^([a-z][a-z0-9+.\-]*):/)||[])[1];if(!o)return i;if("data"===o)return t.allowDataImage&&/^data:image\/(png|jpe?g|gif|webp|bmp|x-icon|svg\+xml)[;,]/.test(n)?i:"";return["http","https","mailto","tel"].includes(o)?i:""}static isAllowedEmbedHost(e){const t=["youtube.com","youtube-nocookie.com","youtu.be","vimeo.com","player.vimeo.com","dailymotion.com","spotify.com","open.spotify.com","soundcloud.com","w.soundcloud.com","codepen.io","codesandbox.io","google.com","maps.google.com"];try{const i=new URL(e,"https://x.invalid").hostname.toLowerCase().replace(/^www\./,"");return t.some(e=>i===e||i.endsWith("."+e))}catch(e){return!1}}static applyDefaultStyles(e,t){const i=void 0===t?n.DEFAULT_STYLES:t;i&&(n._migrateImagesResponsive(e),Object.keys(i).forEach(t=>{const o=i[t];o&&e.querySelectorAll(t).forEach(e=>{const t=n._mergeStyles(o,e.getAttribute("style")||"");t&&e.setAttribute("style",t)})}),e.querySelectorAll("pre > code").forEach(e=>{i.code&&e.getAttribute("style")===i.code&&e.removeAttribute("style")}))}static _migrateImagesResponsive(e){function t(e){return Number.isInteger(e)?String(e):String(parseFloat(e.toFixed(3)))}e.querySelectorAll("img").forEach(e=>{const i=e.getAttribute("style")||"";if(!i)return;const n=i.split(";").map(e=>e.trim()).filter(Boolean);let o=0,r=0,l=!1;if(n.forEach(e=>{const t=e.indexOf(":");if(t<0)return;const i=e.slice(0,t).trim().toLowerCase(),n=e.slice(t+1).trim();if("width"===i||"height"===i){const e=n.match(/^(\d+(?:\.\d+)?)px$/);e&&("width"===i?o=parseFloat(e[1]):r=parseFloat(e[1]))}else"aspect-ratio"===i&&(l=!0)}),!(o>0&&r>0)||l)return;const a=n.filter(e=>"height"!==e.split(":")[0].trim().toLowerCase());a.push(`aspect-ratio: ${t(o)} / ${t(r)}`),a.push("height: auto"),e.setAttribute("style",a.join("; ")),e.removeAttribute("width"),e.removeAttribute("height")})}static _mergeStyles(e,t){const i=e=>{const t={},i=[];return e.split(";").forEach(e=>{if(!(e=e.trim()))return;const n=e.indexOf(":");if(n<0)return;const o=e.slice(0,n).trim().toLowerCase(),r=e.slice(n+1).trim();o&&(o in t||i.push(o),t[o]=r)}),{map:t,order:i}},n=i(e),o=i(t),r=n.order.slice();o.order.forEach(e=>{r.includes(e)||r.push(e)});const l=Object.assign({},n.map,o.map);return r.map(e=>`${e}: ${l[e]}`).join("; ")}applyDefaultStyles(e,i){const o=t.createElement("div");return o.innerHTML=String(null==e?"":e),n.applyDefaultStyles(o,void 0===i?n.DEFAULT_STYLES:i),o.innerHTML}init(e){const i=e.selector||"textarea",n="string"==typeof i?t.querySelectorAll(i):[i],o=[];return n.forEach(t=>{t&&!t.dataset.liteeditorId&&o.push(this.createInstance(t,e))}),this._enforceLicense(e,o),this}_resolveApiKey(e){return e&&e.apiKey?String(e.apiKey):this.apiKey?this.apiKey:this._apiKeyFromScript()}_apiKeyFromScript(){const t=i;if(!t||!t.getAttribute)return null;const n=t.getAttribute("data-key");if(n)return n.trim();const o=t.src||"";if(!o)return null;try{const t=new URL(o,e.location&&e.location.href||void 0),i=t.searchParams.get("key")||t.searchParams.get("apiKey");if(i)return i.trim();const n=t.pathname.match(/\/(le_[a-z0-9_]+)\//i);if(n)return n[1]}catch(e){}return null}_resolveApiBase(e){if(e&&e.apiBase)return String(e.apiBase);if(this.apiBase)return this.apiBase;return(i&&i.getAttribute?i.getAttribute("data-api-base"):null)||"https://app.liteeditor.com"}_validateLicense(e,t){const i=e||"none";if(this._licensePromises[i])return this._licensePromises[i];const n=this._readLicenseCache(e);if(n)return this._licensePromises[i]=Promise.resolve(n),this._licensePromises[i];if("undefined"==typeof fetch)return this._licensePromises[i]=Promise.resolve({valid:!0,_skipped:!0}),this._licensePromises[i];const o=String(t).replace(/\/+$/,"")+"/api/v1/validate";return this._licensePromises[i]=fetch(o,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({key:e||null})}).then(e=>e.json().then(t=>Object.assign({_http:e.status},t))).then(t=>(t&&t.valid&&this._writeLicenseCache(e,t),t)).catch(()=>({valid:!0,_networkError:!0})),this._licensePromises[i]}_enforceLicense(e,t){const i=this._resolveApiKey(e),n=this._resolveApiBase(e);this._validateLicense(i,n).then(e=>{e&&e.valid?this._license={valid:!0,features:e.features||[],token:e.token||null}:(this._license={valid:!1,reason:e&&e.reason||"invalid_key"},t.forEach(e=>{try{e&&e.applyLicenseState(this._license)}catch(e){}}),"undefined"!=typeof console&&console.warn&&console.warn("[LiteEditor] Invalid or missing API key"+(this._license.reason?" ("+this._license.reason+")":"")+". Get a free key at https://liteeditor.com"))})}_readLicenseCache(t){try{const i=e.localStorage.getItem("liteeditor_license_"+(t||"none"));if(!i)return null;const n=JSON.parse(i);if(n&&n.exp&&n.exp>Date.now())return n.res}catch(e){}return null}_writeLicenseCache(t,i){try{e.localStorage.setItem("liteeditor_license_"+(t||"none"),JSON.stringify({exp:Date.now()+6e5,res:i}))}catch(e){}}createInstance(e,t){const i="liteeditor-"+this.instanceCounter++;e.dataset.liteeditorId=i;const n=new o(e,t,i);return this.instances.set(i,n),n}get(e){if(e){if("string"==typeof e&&this.instances.has(e))return this.instances.get(e);if(e&&1===e.nodeType)return this.instances.get(e.dataset.liteeditorId);if("string"==typeof e){const i=t.querySelector(e);return i?this.instances.get(i.dataset.liteeditorId):void 0}}}getAll(e){if(!e)return Array.from(this.instances.values());const i=t.querySelectorAll(e),n=[];return i.forEach(e=>{const t=this.instances.get(e.dataset.liteeditorId);t&&n.push(t)}),n}remove(e){if(!e)return;const i=e=>{const t=this.instances.get(e);t&&(t.destroy(),this.instances.delete(e))};"string"==typeof e&&this.instances.has(e)?i(e):e&&1===e.nodeType?i(e.dataset.liteeditorId):"string"==typeof e&&t.querySelectorAll(e).forEach(e=>i(e.dataset.liteeditorId))}getAllInstances(){return Array.from(this.instances.values())}cleanHTML(e,i){const o=t.createElement("div");return o.innerHTML=String(null==e?"":e),n.stripChromeIn(o),n.normalizePasted(o,i),o.innerHTML}static _convertWordFakeLists(e){const i=e.ownerDocument||t,n=e=>{const t=/margin-left\s*:\s*(-?[\d.]+)\s*(in|pt|px|cm|mm|em)\b/i.exec(e||"");if(!t)return 1;const i=parseFloat(t[1]),n={in:i,pt:i/72,px:i/96,cm:i/2.54,mm:i/25.4,em:16*i/96}[t[2].toLowerCase()];return Math.max(1,Math.round(n/.5))},o=e=>{const t=i.createTreeWalker(e,NodeFilter.SHOW_TEXT,null);let n;for(;n=t.nextNode();)if(n.nodeValue&&n.nodeValue.replace(/[\s ]+/g,""))return n;return null},r=(e,t)=>{const i=o(e);if(!i)return null;const n=new RegExp("^[\\s ]*([•·▪■§○◦o]|\\(?\\d{1,4}[.)]|\\(?[ivxlcdmIVXLCDM]{2,6}[.)]|\\(?[A-Za-z][.)])"+(t?"(?:[\\s ]*[ \\t])[\\s ]*":"[\\s ]+")).exec(i.nodeValue);return n?(i.nodeValue=i.nodeValue.slice(n[0].length),n[1]):null},l=e=>{const t=e.getAttribute("style")||"",i=e.getAttribute("class")||"",o=/mso-list\s*:\s*l(\d+)\s+level(\d+)/i.exec(t),l=!!o||/\bMsoListParagraph/i.test(i);let a;if(l)a=(e=>{const t=Array.from(e.querySelectorAll("span[style]")).find(e=>/mso-list\s*:\s*ignore/i.test(e.getAttribute("style")||""));if(t){const e=t.textContent;return t.remove(),e}const i=Array.from(e.childNodes),n=i.findIndex(e=>8===e.nodeType&&/\[if\s+!supportLists\]/i.test(e.nodeValue));if(n>=0){let e="";for(let t=n;t<i.length;t++){const n=i[t],o=8===n.nodeType&&/\[endif\]/i.test(n.nodeValue);if(8!==n.nodeType&&(e+=n.textContent),n.remove(),o)break}return e}return r(e,!1)||""})(e);else if(a=r(e,!0),null==a)return null;const s=(e=>{const t=(e||"").replace(/[ \s]+/g," ").trim();return t?/^\(?\d{1,4}[.)]$/.test(t)?{ordered:!0,styleType:null}:/^\(?[ivxlcdm]{2,6}[.)]$/.test(t)?{ordered:!0,styleType:"lower-roman"}:/^\(?[IVXLCDM]{2,6}[.)]$/.test(t)?{ordered:!0,styleType:"upper-roman"}:/^\(?[a-z][.)]$/.test(t)?{ordered:!0,styleType:"lower-alpha"}:/^\(?[A-Z][.)]$/.test(t)?{ordered:!0,styleType:"upper-alpha"}:/^[o○◦]$/.test(t)?{ordered:!1,styleType:"circle"}:/^[§▪■]$/.test(t)?{ordered:!1,styleType:"square"}:{ordered:!1,styleType:null}:{ordered:!1,styleType:null}})(a);return{el:e,listId:o?o[1]:null,level:o?Math.max(1,parseInt(o[2],10)):n(t),ordered:s.ordered,styleType:s.styleType,continuation:l&&!o&&!a}},a=new Map;if(e.querySelectorAll("p").forEach(e=>{const t=l(e);t&&a.set(e,t)}),!a.size)return;const s=new Set;a.forEach((e,t)=>{if(s.has(t))return;const n=[];let r=t;for(;r&&a.has(r);){const e=a.get(r);if(n.length&&null!=e.listId){const t=n[n.length-1];if(null!=t.listId&&t.listId!==e.listId)break}s.add(r),n.push(e),r=r.nextElementSibling}(e=>{const t=e[0].el.parentNode;if(!t)return;const n=[],r=[];let l=null;e.forEach(e=>{if(e.continuation&&l){for(l.appendChild(i.createElement("br"));e.el.firstChild;)l.appendChild(e.el.firstChild);return}const t=Math.max(1,e.level||1);for(;r.length>t;)r.pop();for(r.length===t&&t&&r[t-1].tagName!==(e.ordered?"OL":"UL")&&r.pop();r.length<t;){const t=i.createElement(e.ordered?"ol":"ul");if(e.styleType&&t.setAttribute("style","list-style-type: "+e.styleType),r.length){const e=r[r.length-1];let n=e.lastElementChild;n&&"LI"===n.tagName||(n=i.createElement("li"),e.appendChild(n)),n.appendChild(t)}else n.push(t);r.push(t)}const a=i.createElement("li");for(;e.el.firstChild;)a.appendChild(e.el.firstChild);const s=o(a);s&&(s.nodeValue=s.nodeValue.replace(/^[\s ]+/,"")),r[r.length-1].appendChild(a),l=a}),n.forEach(i=>t.insertBefore(i,e[0].el)),e.forEach(e=>e.el.remove())})(n)})}static normalizePasted(e,i){const o=new Set((i||{}).keepClasses||[]),r=e.ownerDocument||t;n._convertWordFakeLists(e);const l=r.createTreeWalker(e,NodeFilter.SHOW_COMMENT,null),a=[];for(;l.nextNode();)a.push(l.currentNode);for(a.forEach(e=>e.parentNode&&e.parentNode.removeChild(e));;){e.querySelector("*");let t=null;if(e.querySelectorAll("*").forEach(e=>{if(t)return;const i=e.tagName?e.tagName.toLowerCase():"";i.includes(":")&&(i.startsWith("o:")||i.startsWith("v:")||i.startsWith("w:")||i.startsWith("x:")||i.startsWith("st1:"))&&(t=e)}),!t)break;for(;t.firstChild;)t.parentNode.insertBefore(t.firstChild,t);t.remove()}const s=["aria-level","aria-hidden","aria-labelledby","aria-describedby","dir","lang","role","data-block-id","data-tag","data-pm-slice","data-id","data-uuid","contenteditable"];e.querySelectorAll("*").forEach(e=>{s.forEach(t=>e.removeAttribute(t)),e.id&&/^docs-internal-guid-/.test(e.id)&&e.removeAttribute("id")}),e.querySelectorAll("[class]").forEach(e=>{if(0===o.size)return void e.removeAttribute("class");const t=(e.getAttribute("class")||"").split(/\s+/).filter(e=>e&&o.has(e));t.length?e.setAttribute("class",t.join(" ")):e.removeAttribute("class")});const c=(e,t)=>{const i=r.createElement(t);for(Array.from(e.attributes).forEach(e=>i.setAttribute(e.name,e.value));e.firstChild;)i.appendChild(e.firstChild);return e.parentNode.replaceChild(i,e),i},d=e=>{for(;e.firstChild;)e.parentNode.insertBefore(e.firstChild,e);e.remove()};e.querySelectorAll("b, strong").forEach(e=>{/font-weight\s*:\s*(normal|400)\b/i.test(e.getAttribute("style")||"")&&d(e)}),e.querySelectorAll("i, em").forEach(e=>{/font-style\s*:\s*normal\b/i.test(e.getAttribute("style")||"")&&d(e)}),e.querySelectorAll("b").forEach(e=>c(e,"strong")),e.querySelectorAll("i").forEach(e=>c(e,"em")),e.querySelectorAll("strike").forEach(e=>c(e,"s")),e.querySelectorAll("font").forEach(e=>{const t=e.getAttribute("color"),i=e.getAttribute("face"),n=[];if(t&&n.push(`color: ${t}`),i&&n.push(`font-family: ${i}`),n.length){const t=r.createElement("span");for(t.setAttribute("style",n.join("; "));e.firstChild;)t.appendChild(e.firstChild);e.parentNode.replaceChild(t,e)}else{for(;e.firstChild;)e.parentNode.insertBefore(e.firstChild,e);e.remove()}}),e.querySelectorAll("center").forEach(e=>{const t=r.createElement("div");for(t.setAttribute("style","text-align: center;");e.firstChild;)t.appendChild(e.firstChild);e.parentNode.replaceChild(t,e)});const h=new Set(["color","background-color","font-weight","font-style","text-decoration","font-size","line-height","text-align","list-style-type","list-style-position","list-style","list-style-image","width","height","max-width","min-width","max-height","min-height","aspect-ratio","object-fit","object-position","border","border-top","border-right","border-bottom","border-left","border-collapse","border-radius","border-color","border-style","border-width","padding","padding-top","padding-right","padding-bottom","padding-left","margin","margin-top","margin-right","margin-bottom","margin-left","display","float","clear","overflow","overflow-x","overflow-y","font-family"]),p={"font-weight":'strong, b, h1, h2, h3, h4, h5, h6, th, [style*="font-weight"]',"font-style":'em, i, [style*="font-style"]',"text-decoration":'u, a, s, strike, [style*="text-decoration"]',color:'[style*="color"]'};e.querySelectorAll("[style]").forEach(e=>{const t=e.getAttribute("style").split(";").map(e=>e.trim()).filter(Boolean).map(t=>{const i=t.indexOf(":");if(i<0)return null;const n=t.slice(0,i).trim().toLowerCase(),o=t.slice(i+1).trim();if(!h.has(n))return null;const r=o.toLowerCase().replace(/\s+/g,"");return("font-weight"===n&&("400"===o||"normal"===o)||"font-style"===n&&"normal"===o||"text-decoration"===n&&"none"===o||"color"===n&&("#000000"===r||"#000"===r||"black"===r||"rgb(0,0,0)"===r))&&!((e,t)=>!(!e.parentElement||!e.parentElement.closest(p[t])))(e,n)?null:"background-color"!==n||"transparent"!==r&&"rgba(0,0,0,0)"!==r?`${n}: ${o}`:null}).filter(Boolean).join("; ");t?e.setAttribute("style",t):e.removeAttribute("style")});const u=/font-weight\s*:\s*(700|800|900|bold|bolder)/i,m=/font-style\s*:\s*italic/i,f=/text-decoration[^:]*:\s*[^;]*underline/i,g=/text-decoration[^:]*:\s*[^;]*line-through/i;e.querySelectorAll("span[style]").forEach(e=>{const t=e.getAttribute("style")||"",i=u.test(t),n=m.test(t),o=f.test(t),l=g.test(t);if(!(i||n||o||l))return;let a=t.split(";").map(e=>e.trim()).filter(Boolean).filter(e=>{const t=e.split(":")[0].trim().toLowerCase();return("font-weight"!==t||!i)&&(("font-style"!==t||!n)&&("text-decoration"!==t||!o&&!l))}).join("; ");a?e.setAttribute("style",a):e.removeAttribute("style");let s=e;const c=e=>{const t=r.createElement(e);s.parentNode.insertBefore(t,s),t.appendChild(s),s=t};l&&c("s"),o&&c("u"),n&&c("em"),i&&c("strong")}),e.querySelectorAll("span").forEach(e=>{if(0===e.attributes.length&&e.parentNode){for(;e.firstChild;)e.parentNode.insertBefore(e.firstChild,e);e.remove()}}),["strong","em","u","s"].forEach(t=>{e.querySelectorAll(`${t} ${t}`).forEach(e=>{if(e.parentNode&&e.parentNode.tagName.toLowerCase()===t){for(;e.firstChild;)e.parentNode.insertBefore(e.firstChild,e);e.remove()}})});const b=/^(P|DIV|UL|OL|LI|TABLE|TBODY|THEAD|TFOOT|TR|TD|TH|H[1-6]|BLOCKQUOTE|PRE|HR|SECTION|ARTICLE|ASIDE|HEADER|FOOTER|NAV|FIGURE|FIGCAPTION|FORM)$/;e.querySelectorAll("div").forEach(e=>{if(Array.from(e.children).some(e=>b.test(e.tagName)))return;const t=r.createElement("p");for(Array.from(e.attributes).forEach(e=>t.setAttribute(e.name,e.value));e.firstChild;)t.appendChild(e.firstChild);e.parentNode.replaceChild(t,e)}),e.querySelectorAll("li").forEach(e=>{for(;e.firstChild&&3===e.firstChild.nodeType&&!e.firstChild.nodeValue.trim();)e.removeChild(e.firstChild);for(;e.lastChild&&3===e.lastChild.nodeType&&!e.lastChild.nodeValue.trim();)e.removeChild(e.lastChild);if(1===e.children.length&&1===e.childNodes.length){const t=e.children[0];if("P"===t.tagName||"DIV"===t.tagName){for(;t.firstChild;)e.insertBefore(t.firstChild,t);t.remove()}}});const y=["utm_source","utm_medium","utm_campaign","utm_term","utm_content","fbclid","gclid","msclkid","mc_cid","mc_eid","_ga","mkt_tok","yclid","dclid"];e.querySelectorAll("a[href]").forEach(e=>{const t=e.getAttribute("href")||"";if(t&&"#"!==t[0]&&!/^(mailto:|tel:|javascript:)/i.test(t))try{const i=new URL(t,"http://x.invalid");let n=!1;if(y.forEach(e=>{i.searchParams.has(e)&&(i.searchParams.delete(e),n=!0)}),n){const n=/^[a-z][a-z0-9+.-]*:\/\//i.test(t)?i.toString():i.pathname+(i.search?i.search:"")+(i.hash?i.hash:"");e.setAttribute("href",n.replace(/\?$/,""))}}catch(e){}})}static stripChromeIn(e){e.querySelectorAll('.liteeditor-image-resizer, [data-liteeditor-chrome="1"].liteeditor-image-resizer').forEach(e=>{const t=e.querySelector("img");t?(t.classList.remove("wrapped"),""===t.getAttribute("class")&&t.removeAttribute("class"),e.parentNode.replaceChild(t,e)):e.remove()});e.querySelectorAll('.liteeditor-table-wrapper, [data-liteeditor-chrome="1"].liteeditor-table-wrapper').forEach(e=>{const t=e.querySelector(":scope > table");t?e.parentNode.replaceChild(t,e):e.remove()}),e.querySelectorAll('.liteeditor-resize-handle, .liteeditor-image-info, [data-liteeditor-chrome="1"]').forEach(e=>e.remove()),e.querySelectorAll("img.wrapped").forEach(e=>{e.classList.remove("wrapped"),""===e.getAttribute("class")&&e.removeAttribute("class")})}}class o{constructor(e,t,i){this.id=i,this.element=e,this.config=t,this.content=e.value||e.textContent||"",this.plugins={},this.toolbar=null,this.editorContainer=null,this.contentArea=null,this.iframe=null,this.iframeDoc=null,this.history={stack:[],currentIndex:-1,maxSize:100},this.selection=null,this.savedRange=null,this.sourceCodeMode=!1,this.sourceTextarea=null,this._defaultStyles=n.resolveStyles(t&&t.default_styles),this._pasteOpts={keepClasses:t&&Array.isArray(t.paste_keep_classes)?t.paste_keep_classes:[]},this._openPickers=new Set,this._activeReaders=new Set,this._activeResize=null,this.init()}init(){this.createEditorStructure(),this.initializePlugins(),this.createToolbar(),this.attachEventListeners(),this.restoreContent(),this.saveState()}saveSelection(){const e=this.iframe.contentWindow.getSelection();e.rangeCount>0&&(this.savedRange=e.getRangeAt(0).cloneRange())}_trackReader(e,t){this._activeReaders.add(e);const i=()=>this._activeReaders.delete(e);return e.addEventListener("load",e=>{i(),t(e)}),e.addEventListener("error",i),e.addEventListener("abort",i),e}restoreSelection(){if(this.savedRange){const e=this.iframe.contentWindow.getSelection();e.removeAllRanges(),e.addRange(this.savedRange)}}showModal(e,i,n){this.saveSelection();const o=t.createElement("div");o.className="liteeditor-modal-overlay active";const r=t.createElement("div");r.className="liteeditor-modal",r.innerHTML='\n <div class="liteeditor-modal-header">\n <h3 class="liteeditor-modal-title"></h3>\n <button class="liteeditor-modal-close" type="button">&times;</button>\n </div>\n <div class="liteeditor-modal-body"></div>\n <div class="liteeditor-modal-footer">\n <button class="liteeditor-modal-btn liteeditor-modal-btn-secondary" data-action="cancel">Cancel</button>\n <button class="liteeditor-modal-btn liteeditor-modal-btn-primary" data-action="confirm">Insert</button>\n </div>\n ',r.querySelector(".liteeditor-modal-title").textContent=String(null==e?"":e),r.querySelector(".liteeditor-modal-body").innerHTML=i,o.appendChild(r),t.body.appendChild(o);const l=()=>{o.remove();try{this.restoreSelection()}catch(e){}this.iframe.contentWindow.focus()};return r.querySelector(".liteeditor-modal-close").addEventListener("click",l),r.querySelector('[data-action="cancel"]').addEventListener("click",l),r.querySelector('[data-action="confirm"]').addEventListener("click",()=>{n(r)&&l()}),o.addEventListener("click",e=>{e.target===o&&l()}),r}showImageModal(e){const i=!!e,n=i?this._readImageFields(e):{url:"",alt:"",width:"",height:"",link:"",linkNewTab:!1},o=e=>String(null==e?"":e).replace(/&/g,"&amp;").replace(/"/g,"&quot;").replace(/</g,"&lt;").replace(/>/g,"&gt;"),r=`\n <div class="liteeditor-tabs">\n <button class="liteeditor-tab active" data-tab="url">URL</button>\n <button class="liteeditor-tab" data-tab="upload">${i?"Replace":"Upload"}</button>\n </div>\n\n <div class="liteeditor-tab-content active" data-content="url">\n <div class="liteeditor-form-group">\n <label class="liteeditor-form-label">Image URL</label>\n <input type="url" class="liteeditor-form-input" id="image-url" placeholder="https://example.com/image.jpg" value="${o(n.url)}">\n </div>\n <div class="liteeditor-form-group">\n <label class="liteeditor-form-label">Alt Text (optional)</label>\n <input type="text" class="liteeditor-form-input" id="image-alt" placeholder="Image description" value="${o(n.alt)}">\n </div>\n <div style="display: flex; gap: 12px;">\n <div class="liteeditor-form-group" style="flex: 1;">\n <label class="liteeditor-form-label">Width (px)</label>\n <input type="number" class="liteeditor-form-input" id="image-width-url" placeholder="Auto" min="1" value="${o(n.width)}">\n </div>\n <div class="liteeditor-form-group" style="flex: 1;">\n <label class="liteeditor-form-label">Height (px)</label>\n <input type="number" class="liteeditor-form-input" id="image-height-url" placeholder="Auto" min="1" value="${o(n.height)}">\n </div>\n </div>\n </div>\n\n <div class="liteeditor-tab-content" data-content="upload">\n <div class="liteeditor-file-upload" id="file-drop-area">\n <div class="liteeditor-file-upload-icon">📁</div>\n <div class="liteeditor-file-upload-text">Click to browse or drag &amp; drop image</div>\n <div class="liteeditor-file-upload-hint">Supports: JPG, PNG, GIF, WebP</div>\n <input type="file" class="liteeditor-file-input" id="image-file" accept="image/*">\n </div>\n <div class="liteeditor-image-preview" id="image-preview" style="display: none;"></div>\n <div class="liteeditor-form-group" style="margin-top: 16px;">\n <label class="liteeditor-form-label">Alt Text (optional)</label>\n <input type="text" class="liteeditor-form-input" id="image-alt-upload" placeholder="Image description" value="${o(n.alt)}">\n </div>\n <div style="display: flex; gap: 12px;">\n <div class="liteeditor-form-group" style="flex: 1;">\n <label class="liteeditor-form-label">Width (px)</label>\n <input type="number" class="liteeditor-form-input" id="image-width-upload" placeholder="Auto" min="1">\n </div>\n <div class="liteeditor-form-group" style="flex: 1;">\n <label class="liteeditor-form-label">Height (px)</label>\n <input type="number" class="liteeditor-form-input" id="image-height-upload" placeholder="Auto" min="1">\n </div>\n </div>\n </div>\n\n <div class="liteeditor-form-group" style="margin-top: 12px; border-top: 1px solid #eee; padding-top: 12px;">\n <label class="liteeditor-form-label">Link URL (optional)</label>\n <input type="url" class="liteeditor-form-input" id="image-link" placeholder="https://example.com — wrap the image in a link" value="${o(n.link)}">\n <label style="display: inline-flex; align-items: center; gap: 6px; margin-top: 6px; font-size: 13px; color: #555;">\n <input type="checkbox" id="image-link-newtab" ${n.linkNewTab?"checked":""}>\n Open in new tab\n </label>\n </div>\n `,l=this.showModal(i?"Edit Image":"Insert Image",r,t=>{const n=t.querySelector(".liteeditor-tab.active").dataset.tab,o=t.querySelector("#image-link").value.trim(),r=t.querySelector("#image-link-newtab").checked;if("url"===n){const n=t.querySelector("#image-url").value.trim(),l=t.querySelector("#image-alt").value,a=t.querySelector("#image-width-url").value,s=t.querySelector("#image-height-url").value;return n?(i?this._updateImage(e,{url:n,alt:l,width:a,height:s,link:o,linkNewTab:r}):this._insertImage({url:n,alt:l,width:a,height:s,link:o,linkNewTab:r}),!0):(alert("Please enter an image URL"),!1)}{const n=t.querySelector("#image-file"),l=t.querySelector("#image-alt-upload").value,a=t.querySelector("#image-width-upload").value,s=t.querySelector("#image-height-upload").value;if(!n.files||!n.files[0])return alert("Please select an image file"),!1;const c=n.files[0];return this._trackReader(new FileReader,t=>{const n={url:t.target.result,alt:l||c.name,width:a,height:s,link:o,linkNewTab:r};i?this._updateImage(e,n):this._insertImage(n)}).readAsDataURL(c),!0}}),a=l.querySelectorAll(".liteeditor-tab"),s=l.querySelectorAll(".liteeditor-tab-content");a.forEach(e=>{e.addEventListener("click",()=>{a.forEach(e=>e.classList.remove("active")),s.forEach(e=>e.classList.remove("active")),e.classList.add("active"),l.querySelector(`[data-content="${e.dataset.tab}"]`).classList.add("active")})});const c=l.querySelector("#file-drop-area"),d=l.querySelector("#image-file"),h=l.querySelector("#image-preview"),p=l.querySelector("#image-width-upload"),u=l.querySelector("#image-height-upload");c.addEventListener("click",()=>d.click()),d.addEventListener("change",e=>{e.target.files&&e.target.files[0]&&b(e.target.files[0])});const m=l.querySelector("#image-url"),f=l.querySelector("#image-width-url"),g=l.querySelector("#image-height-url");m.addEventListener("blur",()=>{const e=m.value;if(!e)return;const t=new Image;t.onload=function(){f.value=this.width,g.value=this.height,f.placeholder=this.width,g.placeholder=this.height},t.onerror=()=>{f.placeholder="Auto",g.placeholder="Auto"},t.src=e}),c.addEventListener("dragover",e=>{e.preventDefault(),c.classList.add("dragover")}),c.addEventListener("dragleave",()=>{c.classList.remove("dragover")}),c.addEventListener("drop",e=>{e.preventDefault(),c.classList.remove("dragover"),e.dataTransfer.files&&e.dataTransfer.files[0]&&(d.files=e.dataTransfer.files,b(e.dataTransfer.files[0]))});const b=e=>{this._trackReader(new FileReader,i=>{const n=new Image;n.onload=function(){p.value=this.width,u.value=this.height,p.placeholder=this.width,u.placeholder=this.height},n.onerror=()=>{},n.src=i.target.result,h.innerHTML="";const o=t.createElement("img");o.src=i.target.result,o.alt="Preview";const r=t.createElement("div");r.className="liteeditor-image-preview-name",r.textContent=e.name,h.appendChild(o),h.appendChild(r),h.style.display="block"}).readAsDataURL(e)}}showTableModal(){const e=this.showModal("Insert Table",'\n <div class="liteeditor-form-group">\n <label class="liteeditor-form-label">Select Table Size</label>\n <div style="text-align: center; margin-top: 16px;">\n <div class="liteeditor-table-grid" id="table-grid"></div>\n <div class="liteeditor-table-size-label" id="table-size-label">0 × 0</div>\n </div>\n </div>\n \n <div style="display: flex; gap: 16px; margin-top: 24px;">\n <div class="liteeditor-form-group" style="flex: 1;">\n <label class="liteeditor-form-label">Rows</label>\n <input type="number" class="liteeditor-form-input" id="table-rows" value="3" min="1" max="20">\n </div>\n <div class="liteeditor-form-group" style="flex: 1;">\n <label class="liteeditor-form-label">Columns</label>\n <input type="number" class="liteeditor-form-input" id="table-cols" value="3" min="1" max="20">\n </div>\n </div>\n \n <div class="liteeditor-form-group">\n <label style="display: flex; align-items: center; gap: 8px; cursor: pointer;">\n <input type="checkbox" id="table-header" checked>\n <span>Include header row</span>\n </label>\n </div>\n ',e=>{const t=parseInt(e.querySelector("#table-rows").value)||3,i=parseInt(e.querySelector("#table-cols").value)||3,n=e.querySelector("#table-header").checked,o=this._defaultStyles,r=o&&o.table?` style="${o.table}" border="1"`:"",l=o&&o.th?` style="${o.th}"`:"",a=o&&o.td?` style="${o.td}"`:"";let s=`<table${r}><tbody>`;for(let e=0;e<t;e++){s+="<tr>";for(let t=0;t<i;t++)s+=n&&0===e?`<th${l}>Header</th>`:`<td${a}>Cell</td>`;s+="</tr>"}return s+="</tbody></table>",this.execCommand("insertHTML",s),!0}),i=e.querySelector("#table-grid"),n=e.querySelector("#table-size-label"),o=e.querySelector("#table-rows"),r=e.querySelector("#table-cols");let l=3,a=3;for(let c=0;c<10;c++){const d=t.createElement("div");d.className="liteeditor-table-grid-row";for(let i=0;i<10;i++){const h=t.createElement("div");h.className="liteeditor-table-grid-cell",h.dataset.row=c+1,h.dataset.col=i+1,h.addEventListener("mouseenter",()=>{l=parseInt(h.dataset.row),a=parseInt(h.dataset.col),s(),n.textContent=`${l} × ${a}`,o.value=l,r.value=a}),h.addEventListener("click",()=>{e.querySelector('[data-action="confirm"]').click()}),d.appendChild(h)}i.appendChild(d)}function s(){i.querySelectorAll(".liteeditor-table-grid-cell").forEach(e=>{const t=parseInt(e.dataset.row),i=parseInt(e.dataset.col);t<=l&&i<=a?e.classList.add("selected"):e.classList.remove("selected")})}o.addEventListener("input",()=>{l=Math.min(Math.max(1,parseInt(o.value)||1),10),o.value=l,s(),n.textContent=`${l} × ${a}`}),r.addEventListener("input",()=>{a=Math.min(Math.max(1,parseInt(r.value)||1),10),r.value=a,s(),n.textContent=`${l} × ${a}`}),s(),n.textContent=`${l} × ${a}`}showLinkModal(){const e=this.iframe.contentWindow.getSelection().toString(),t=`\n <div class="liteeditor-form-group">\n <label class="liteeditor-form-label">URL</label>\n <input type="url" class="liteeditor-form-input" id="link-url" placeholder="https://example.com" required>\n </div>\n <div class="liteeditor-form-group">\n <label class="liteeditor-form-label">Display Text</label>\n <input type="text" class="liteeditor-form-input" id="link-text" placeholder="Link text" value="${e.replace(/&/g,"&amp;").replace(/"/g,"&quot;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}">\n </div>\n <div class="liteeditor-form-group">\n <label style="display: flex; align-items: center; gap: 8px; cursor: pointer;">\n <input type="checkbox" id="link-new-tab" checked>\n <span>Open in new tab</span>\n </label>\n </div>\n `;this.showModal("Insert Link",t,t=>{const i=t.querySelector("#link-url").value.trim(),o=t.querySelector("#link-text").value.trim()||i,r=t.querySelector("#link-new-tab").checked;if(!i)return alert("Please enter a URL"),!1;const l=n.sanitizeUrl(i);if(!l)return alert("This URL scheme is not allowed"),!1;const a=r?' target="_blank" rel="noopener noreferrer"':"";if(e&&o===e){if(this.execCommand("createLink",l),r){this.contentArea.querySelectorAll("a").forEach(e=>{e.getAttribute("href")!==l||e.getAttribute("target")||(e.setAttribute("target","_blank"),e.setAttribute("rel","noopener noreferrer"))})}}else{const e=o.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;"),t=`<a href="${s=l,s.replace(/&/g,"&amp;").replace(/"/g,"&quot;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}"${a}>${e}</a>`;this.execCommand("insertHTML",t)}var s;return!0})}showMediaModal(){const e=this.showModal("Insert Media",'\n <div class="liteeditor-tabs">\n <button class="liteeditor-tab active" data-tab="video-url">Video URL</button>\n <button class="liteeditor-tab" data-tab="embed-code">Embed Code</button>\n </div>\n\n <div class="liteeditor-tab-content active" data-content="video-url">\n <div class="liteeditor-form-group">\n <label class="liteeditor-form-label">Video URL</label>\n <input type="url" class="liteeditor-form-input" id="media-url" placeholder="https://www.youtube.com/watch?v=...">\n </div>\n <div style="display: flex; gap: 12px;">\n <div class="liteeditor-form-group" style="flex: 1;">\n <label class="liteeditor-form-label">Width (px)</label>\n <input type="number" class="liteeditor-form-input" id="media-width" value="560" min="100">\n </div>\n <div class="liteeditor-form-group" style="flex: 1;">\n <label class="liteeditor-form-label">Height (px)</label>\n <input type="number" class="liteeditor-form-input" id="media-height" value="315" min="100">\n </div>\n </div>\n <div id="media-preview" style="display: none; margin-top: 16px; border-radius: 4px; overflow: hidden;"></div>\n </div>\n\n <div class="liteeditor-tab-content" data-content="embed-code">\n <div class="liteeditor-form-group">\n <label class="liteeditor-form-label">Embed Code</label>\n <textarea class="liteeditor-form-input" id="media-embed" rows="6" placeholder="Paste your embed code here..." style="font-family: monospace; resize: vertical;"></textarea>\n </div>\n </div>\n ',e=>{if("video-url"===e.querySelector(".liteeditor-tab.active").dataset.tab){const i=e.querySelector("#media-url").value.trim(),n=e.querySelector("#media-width").value||560,o=e.querySelector("#media-height").value||315;if(!i)return alert("Please enter a video URL"),!1;const r=this.getVideoEmbedUrl(i);if(!r)return alert("Unsupported video URL. Supported: YouTube, Vimeo, Dailymotion"),!1;const l=t.createElement("div");l.style.margin="10px 0";const a=t.createElement("iframe");return a.setAttribute("src",r),a.setAttribute("width",String(parseInt(n,10)||560)),a.setAttribute("height",String(parseInt(o,10)||315)),a.setAttribute("frameborder","0"),a.setAttribute("allowfullscreen",""),a.style.maxWidth="100%",a.style.border="none",l.appendChild(a),this.execCommand("insertHTML",l.outerHTML),!0}{const t=e.querySelector("#media-embed").value.trim();if(!t)return alert("Please enter embed code"),!1;const i=this.sanitizeMediaEmbed(t);return this.execCommand("insertHTML",i),!0}}),i=e.querySelectorAll(".liteeditor-tab"),n=e.querySelectorAll(".liteeditor-tab-content");i.forEach(t=>{t.addEventListener("click",()=>{i.forEach(e=>e.classList.remove("active")),n.forEach(e=>e.classList.remove("active")),t.classList.add("active"),e.querySelector(`[data-content="${t.dataset.tab}"]`).classList.add("active")})});const o=e.querySelector("#media-url"),r=e.querySelector("#media-preview");o.addEventListener("blur",()=>{const e=o.value.trim(),i=this.getVideoEmbedUrl(e);if(i){r.innerHTML="";const e=t.createElement("iframe");e.setAttribute("src",i),e.setAttribute("width","100%"),e.setAttribute("height","200"),e.setAttribute("frameborder","0"),e.setAttribute("allowfullscreen",""),e.style.border="none",r.appendChild(e),r.style.display="block"}else r.style.display="none"})}getVideoEmbedUrl(e){let t=e.match(/(?:youtube\.com\/watch\?v=|youtu\.be\/|youtube\.com\/embed\/)([a-zA-Z0-9_-]{11})/);return t?`https://www.youtube.com/embed/${t[1]}`:(t=e.match(/vimeo\.com\/(\d+)/),t?`https://player.vimeo.com/video/${t[1]}`:(t=e.match(/dailymotion\.com\/video\/([a-zA-Z0-9]+)/),t?`https://www.dailymotion.com/embed/video/${t[1]}`:null))}sanitizeMediaEmbed(e){const i=t.createElement("div");i.innerHTML=e;const o=["IFRAME","VIDEO","AUDIO","SOURCE","EMBED","OBJECT","PARAM"],r=new Set(["IFRAME","EMBED","OBJECT"]);return i.querySelectorAll("*").forEach(e=>{if(!o.includes(e.tagName))return void e.remove();let t=!1;Array.from(e.attributes).forEach(i=>{const o=i.name.toLowerCase();if(o.startsWith("on")||"srcdoc"===o)e.removeAttribute(i.name);else if(["src","href","data"].includes(o)){const o=n.sanitizeUrl(i.value);if(!o)return void e.removeAttribute(i.name);if(r.has(e.tagName)&&!n.isAllowedEmbedHost(o))return void(t=!0);o!==i.value&&e.setAttribute(i.name,o)}}),t&&e.remove()}),i.innerHTML}showCodeSampleModal(){const e=`\n <div class="liteeditor-form-group">\n <label class="liteeditor-form-label">Language</label>\n <select class="liteeditor-form-input" id="codesample-lang">${[{value:"javascript",label:"JavaScript"},{value:"python",label:"Python"},{value:"html",label:"HTML"},{value:"css",label:"CSS"},{value:"php",label:"PHP"},{value:"java",label:"Java"},{value:"cpp",label:"C++"},{value:"ruby",label:"Ruby"},{value:"go",label:"Go"},{value:"bash",label:"Bash"},{value:"plaintext",label:"Plain Text"}].map(e=>`<option value="${e.value}">${e.label}</option>`).join("")}</select>\n </div>\n <div class="liteeditor-form-group">\n <label class="liteeditor-form-label">Code</label>\n <textarea class="liteeditor-form-input" id="codesample-code" rows="10" placeholder="Paste your code here..." style="font-family: 'Courier New', Consolas, Monaco, monospace; font-size: 13px; line-height: 1.5; tab-size: 4; resize: vertical;"></textarea>\n </div>\n `;this.showModal("Insert Code Sample",e,e=>{const t=e.querySelector("#codesample-lang").value,i=e.querySelector("#codesample-code").value;if(!i.trim())return alert("Please enter some code"),!1;const n=i.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;"),o=this._defaultStyles,r=`<pre${o&&o.pre?` style="${o.pre}"`:""}><code class="language-${t}">${n}</code></pre><p><br></p>`;return this.execCommand("insertHTML",r),!0})}showAnchorModal(){this.showModal("Insert Anchor",'\n <div class="liteeditor-form-group">\n <label class="liteeditor-form-label">Anchor Name / ID</label>\n <input type="text" class="liteeditor-form-input" id="anchor-name" placeholder="e.g., section-intro">\n <div style="margin-top: 6px; font-size: 12px; color: #666;">\n Must start with a letter. Only letters, numbers, hyphens, and underscores allowed.\n </div>\n </div>\n ',e=>{let t=e.querySelector("#anchor-name").value.trim();if(!t)return alert("Please enter an anchor name"),!1;if(t=t.replace(/[^a-zA-Z0-9_-]/g,"-").replace(/^[^a-zA-Z]+/,""),!t)return alert("Invalid anchor name"),!1;const i=`<a id="${t}" class="liteeditor-anchor"></a>`;return this.execCommand("insertHTML",i),!0})}showSearchReplace(){if(this.searchPanel)return void this.searchPanel.querySelector("#search-find-input").focus();const e=t.createElement("div");e.className="liteeditor-search-panel",e.innerHTML='\n <div class="liteeditor-search-row">\n <input type="text" class="liteeditor-form-input" id="search-find-input" placeholder="Find...">\n <span class="liteeditor-search-count" id="search-count">0 of 0</span>\n <button type="button" class="liteeditor-search-btn" id="search-prev" title="Previous">&#9650;</button>\n <button type="button" class="liteeditor-search-btn" id="search-next" title="Next">&#9660;</button>\n <button type="button" class="liteeditor-search-btn liteeditor-search-close" id="search-close" title="Close">&times;</button>\n </div>\n <div class="liteeditor-search-row">\n <input type="text" class="liteeditor-form-input" id="search-replace-input" placeholder="Replace with...">\n <button type="button" class="liteeditor-search-btn" id="search-replace" title="Replace">Replace</button>\n <button type="button" class="liteeditor-search-btn" id="search-replace-all" title="Replace All">All</button>\n </div>\n ',this.toolbar.parentNode.insertBefore(e,this.toolbar.nextSibling),this.searchPanel=e;let i=[],n=-1;const o=e.querySelector("#search-find-input"),r=e.querySelector("#search-replace-input"),l=e.querySelector("#search-count"),a=()=>{this.contentArea.querySelectorAll("mark.liteeditor-search-highlight").forEach(e=>{const t=e.parentNode;t.replaceChild(this.iframeDoc.createTextNode(e.textContent),e),t.normalize()}),i=[],n=-1},s=()=>{const e=this._markGroups||[];i.forEach(e=>e.classList.remove("current")),e.forEach((e,t)=>{t===n&&e.forEach(e=>e.classList.add("current"))}),l.textContent=e.length>0?`${n+1} of ${e.length}`:"0 of 0",n>=0&&e[n]&&e[n][0]&&e[n][0].scrollIntoView({block:"center",behavior:"smooth"})},c=()=>{const e=this._markGroups||[];0!==e.length&&(n=(n+1)%e.length,s())},d=()=>{const e=this._markGroups||[];0!==e.length&&(n=(n-1+e.length)%e.length,s())},h=(e,t)=>{if(!e.length)return;const i=e[0],n=this.iframeDoc.createTextNode(t);i.parentNode.replaceChild(n,i);for(let t=1;t<e.length;t++)e[t].parentNode&&e[t].remove();n.parentNode&&n.parentNode.normalize()},p=()=>{a(),e.remove(),this.searchPanel=null,this._closeSearchPanel=null};this._closeSearchPanel=p,o.addEventListener("input",()=>{a();const e=o.value;if(!e)return void(l.textContent="0 of 0");const t=this.iframeDoc.createTreeWalker(this.contentArea,NodeFilter.SHOW_TEXT,{acceptNode:e=>{if(!e.nodeValue)return NodeFilter.FILTER_REJECT;const t=e.parentNode;return t&&t.closest&&t.closest(".liteeditor-image-resizer")?NodeFilter.FILTER_REJECT:NodeFilter.FILTER_ACCEPT}});let r="";const c=[];for(;t.nextNode();){const e=t.currentNode;c.push({node:e,start:r.length,end:r.length+e.nodeValue.length}),r+=e.nodeValue}const d=e.toLowerCase(),h=r.toLowerCase(),p=[];let u=0;for(;u<=h.length-d.length;){const t=h.indexOf(d,u);if(-1===t)break;p.push({start:t,end:t+e.length}),u=t+e.length}const m=e=>{for(let t=0;t<c.length;t++)if(e>=c[t].start&&e<=c[t].end)return{node:c[t].node,offset:e-c[t].start};return null};for(let e=p.length-1;e>=0;e--){const t=p[e],i=m(t.start),n=m(t.end);if(!i||!n)continue;const o=this.iframeDoc.createRange();try{o.setStart(i.node,i.offset),o.setEnd(n.node,n.offset)}catch(e){continue}this.wrapRangeInMark(o)}i=Array.from(this.contentArea.querySelectorAll("mark.liteeditor-search-highlight")),this._markGroups=this.groupMarks(i),n=this._markGroups.length>0?0:-1,s()}),e.querySelector("#search-prev").addEventListener("click",d),e.querySelector("#search-next").addEventListener("click",c),e.querySelector("#search-replace").addEventListener("click",()=>{const e=this._markGroups||[];n<0||!e[n]||(h(e[n],r.value),e.splice(n,1),n>=e.length&&(n=0),0===e.length&&(n=-1),i=Array.from(this.contentArea.querySelectorAll("mark.liteeditor-search-highlight")),s(),this.saveState(),this.syncContent())}),e.querySelector("#search-replace-all").addEventListener("click",()=>{const e=this._markGroups||[];if(0===e.length)return;const t=r.value;e.forEach(e=>h(e,t)),this._markGroups=[],i=[],n=-1,l.textContent="0 of 0",this.saveState(),this.syncContent()}),e.querySelector("#search-close").addEventListener("click",p),o.addEventListener("keydown",e=>{"Enter"===e.key&&(e.preventDefault(),e.shiftKey?d():c()),"Escape"===e.key&&p()}),r.addEventListener("keydown",e=>{"Escape"===e.key&&p()}),o.focus()}createEditorStructure(){this.element.style.display="none",this.editorContainer=t.createElement("div"),this.editorContainer.className="liteeditor-container",this.editorContainer.id=this.id+"-container",this.element.parentNode.insertBefore(this.editorContainer,this.element),this.config.menubar&&this.createMenuBar(),this.toolbar=t.createElement("div"),this.toolbar.className="liteeditor-toolbar",this.editorContainer.appendChild(this.toolbar);const e=t.createElement("div");e.className="liteeditor-editor-wrapper",this.iframe=t.createElement("iframe"),this.iframe.className="liteeditor-content",this.iframe.setAttribute("frameborder","0");const i=this.config.height||150;this.iframe.style.height=i+"px",e.appendChild(this.iframe),this.editorContainer.appendChild(e),this.iframeDoc=this.iframe.contentDocument||this.iframe.contentWindow.document,this.iframeDoc.open(),this.iframeDoc.write('\n <!DOCTYPE html>\n <html>\n <head>\n <style>\n * { margin: 0; padding: 0; box-sizing: border-box; }\n html, body {\n height: 100%;\n }\n body {\n font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;\n font-size: 14px;\n line-height: 1.6;\n color: #333;\n padding: 12px;\n min-height: 100%;\n word-wrap: break-word;\n }\n p { margin: 0 0 10px 0; }\n h1, h2, h3, h4, h5, h6 { margin: 15px 0 10px 0; font-weight: 600; }\n h1 { font-size: 2em; }\n h2 { font-size: 1.5em; }\n h3 { font-size: 1.17em; }\n h4 { font-size: 1em; }\n h5 { font-size: 0.83em; }\n h6 { font-size: 0.67em; }\n ul, ol { margin: 10px 0; padding-left: 40px; }\n li { margin: 5px 0; }\n a { color: #0066cc; text-decoration: underline; }\n img { max-width: 100%; height: auto; }\n table { border-collapse: collapse; width: 100%; margin: 10px 0; }\n table td, table th { border: 1px solid #ddd; padding: 8px; }\n table th { background-color: #f2f2f2; color: #000; font-weight: bold; }\n blockquote { margin: 10px 0; padding: 10px 20px; border-left: 4px solid #ccc; background: #f9f9f9; }\n code { background: #f4f4f4; padding: 2px 6px; border-radius: 3px; font-family: monospace; }\n pre { background: #f4f4f4; padding: 10px; border-radius: 5px; overflow-x: auto; margin: 10px 0; }\n pre code { padding: 0; background: none; }\n hr { border: none; border-top: 1px solid #ddd; margin: 15px 0; }\n .text-left { text-align: left; }\n .text-center { text-align: center; }\n .text-right { text-align: right; }\n .text-justify { text-align: justify; }\n \n /* Image Resize Styles */\n .liteeditor-image-resizer {\n position: relative;\n display: inline-block;\n max-width: 100%;\n margin: 5px;\n }\n .liteeditor-image-resizer img {\n display: block;\n max-width: 100%;\n }\n .liteeditor-image-resizer img[style*="width"] {\n max-width: none;\n }\n .liteeditor-image-resizer.selected {\n outline: 2px solid #667eea;\n outline-offset: 2px;\n }\n .liteeditor-resize-handle {\n position: absolute;\n width: 10px;\n height: 10px;\n background: #667eea;\n border: 2px solid #fff;\n border-radius: 50%;\n display: none;\n z-index: 100;\n }\n .liteeditor-image-resizer.selected .liteeditor-resize-handle {\n display: block;\n }\n .liteeditor-resize-handle.nw { top: -5px; left: -5px; cursor: nw-resize; }\n .liteeditor-resize-handle.ne { top: -5px; right: -5px; cursor: ne-resize; }\n .liteeditor-resize-handle.sw { bottom: -5px; left: -5px; cursor: sw-resize; }\n .liteeditor-resize-handle.se { bottom: -5px; right: -5px; cursor: se-resize; }\n .liteeditor-resize-handle.n { top: -5px; left: 50%; transform: translateX(-50%); cursor: n-resize; }\n .liteeditor-resize-handle.s { bottom: -5px; left: 50%; transform: translateX(-50%); cursor: s-resize; }\n .liteeditor-resize-handle.e { top: 50%; right: -5px; transform: translateY(-50%); cursor: e-resize; }\n .liteeditor-resize-handle.w { top: 50%; left: -5px; transform: translateY(-50%); cursor: w-resize; }\n .liteeditor-image-info {\n position: absolute;\n top: -30px;\n left: 50%;\n transform: translateX(-50%);\n background: rgba(0, 0, 0, 0.8);\n color: #fff;\n padding: 4px 8px;\n border-radius: 4px;\n font-size: 11px;\n white-space: nowrap;\n pointer-events: none;\n display: none;\n }\n .liteeditor-image-resizer.selected .liteeditor-image-info {\n display: block;\n }\n\n /* Floating image toolbar (Edit · Replace · Align · Link · Delete) */\n .liteeditor-image-toolbar {\n position: absolute;\n bottom: calc(100% + 8px);\n left: 50%;\n transform: translateX(-50%);\n display: none;\n background: #2d3748;\n color: #fff;\n padding: 4px;\n border-radius: 6px;\n white-space: nowrap;\n z-index: 200;\n box-shadow: 0 2px 8px rgba(0,0,0,0.2);\n user-select: none;\n font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;\n }\n .liteeditor-image-resizer.selected .liteeditor-image-toolbar {\n display: inline-flex;\n gap: 1px;\n align-items: center;\n }\n .liteeditor-img-toolbar-btn {\n background: transparent;\n color: inherit;\n border: 0;\n width: 30px;\n height: 28px;\n padding: 0;\n cursor: pointer;\n border-radius: 3px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n font-size: 14px;\n line-height: 1;\n }\n .liteeditor-img-toolbar-btn:hover {\n background: rgba(255,255,255,0.18);\n }\n .liteeditor-img-toolbar-sep {\n display: inline-block;\n width: 1px;\n height: 18px;\n background: rgba(255,255,255,0.25);\n margin: 0 3px;\n }\n\n /* Inline link-edit popover under the image */\n .liteeditor-image-link-popover {\n position: absolute;\n top: calc(100% + 8px);\n left: 0;\n background: #fff;\n border: 1px solid #ddd;\n border-radius: 6px;\n padding: 6px;\n box-shadow: 0 4px 12px rgba(0,0,0,0.12);\n z-index: 201;\n display: flex;\n gap: 6px;\n align-items: center;\n user-select: text;\n white-space: nowrap;\n font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;\n font-size: 13px;\n }\n .liteeditor-img-link-input {\n border: 1px solid #ddd;\n outline: 0;\n padding: 6px 8px;\n min-width: 260px;\n font-size: 13px;\n border-radius: 3px;\n }\n .liteeditor-img-link-input:focus {\n border-color: #667eea;\n }\n .liteeditor-img-link-newtab {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n font-size: 12px;\n color: #555;\n cursor: pointer;\n }\n .liteeditor-img-link-save {\n padding: 5px 12px;\n background: #667eea;\n color: #fff;\n border: 0;\n border-radius: 3px;\n cursor: pointer;\n font-size: 13px;\n }\n .liteeditor-img-link-save:hover {\n background: #5563d6;\n }\n .liteeditor-img-link-remove {\n padding: 5px 10px;\n background: transparent;\n color: #c00;\n border: 0;\n cursor: pointer;\n font-size: 13px;\n }\n .liteeditor-img-link-remove:hover {\n background: #fef2f2;\n border-radius: 3px;\n }\n\n /* Table editor chrome (wrapper + floating toolbar) */\n .liteeditor-table-wrapper {\n position: relative;\n display: block;\n /* Reserve 40px above so the floating toolbar always\n sits above the table without clipping into prior\n content or the body padding. Wrapper is editor\n chrome — stripped on save — so this added margin\n never reaches the rendered page. */\n margin: 40px 0 10px 0;\n /* Shrink the wrapper to the table\'s actual rendered\n width so the resize handles + floating toolbar\n (which are positioned at wrapper edges) always\n align with the table edge, no matter how the\n user has sized or aligned the table. */\n width: fit-content;\n /* But never overflow the editor\'s content area. */\n max-width: 100%;\n }\n .liteeditor-table-toolbar {\n position: absolute;\n top: -34px;\n left: 0;\n display: none;\n background: #2d3748;\n color: #fff;\n padding: 3px;\n border-radius: 6px;\n white-space: nowrap;\n z-index: 200;\n box-shadow: 0 2px 8px rgba(0,0,0,0.2);\n user-select: none;\n font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;\n }\n .liteeditor-table-wrapper.active .liteeditor-table-toolbar {\n display: inline-flex;\n gap: 1px;\n align-items: center;\n }\n .liteeditor-tbl-toolbar-btn {\n background: transparent;\n color: inherit;\n border: 0;\n width: 30px;\n height: 28px;\n padding: 0;\n cursor: pointer;\n border-radius: 3px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n font-size: 14px;\n line-height: 1;\n }\n .liteeditor-tbl-toolbar-btn:hover {\n background: rgba(255,255,255,0.18);\n }\n .liteeditor-tbl-toolbar-btn.active {\n background: rgba(102, 126, 234, 0.5);\n }\n .liteeditor-tbl-toolbar-sep {\n display: inline-block;\n width: 1px;\n height: 18px;\n background: rgba(255,255,255,0.25);\n margin: 0 3px;\n }\n /* Inside the wrapper only — collapse the table\'s normal\n vertical margin so the wrapper edge sits flush with\n the table edge. Resize handles are positioned\n relative to the wrapper, so they appear at the\n table\'s border instead of floating in margin space.\n The wrapper is stripped on save, so the table\'s\n original inline margin is preserved in the output. */\n .liteeditor-table-wrapper > table {\n margin-top: 0 !important;\n margin-bottom: 0 !important;\n }\n /* Eight resize handles on the wrapper, visible only when\n the table is active (cursor inside a cell).\n Corners → resize both width and height.\n E / W → width only (most common table edit).\n N / S → height only. */\n .liteeditor-table-resize-handle {\n position: absolute;\n background: #667eea;\n border: 2px solid #fff;\n z-index: 199;\n display: none;\n box-sizing: border-box;\n }\n .liteeditor-table-wrapper.active .liteeditor-table-resize-handle { display: block; }\n /* Corner handles — 10×10 circles. */\n .liteeditor-table-resize-handle.nw,\n .liteeditor-table-resize-handle.ne,\n .liteeditor-table-resize-handle.sw,\n .liteeditor-table-resize-handle.se {\n width: 10px;\n height: 10px;\n border-radius: 50%;\n }\n .liteeditor-table-resize-handle.nw { top: -5px; left: -5px; cursor: nwse-resize; }\n .liteeditor-table-resize-handle.ne { top: -5px; right: -5px; cursor: nesw-resize; }\n .liteeditor-table-resize-handle.sw { bottom: -5px; left: -5px; cursor: nesw-resize; }\n .liteeditor-table-resize-handle.se { bottom: -5px; right: -5px; cursor: nwse-resize; }\n /* Edge handles — bar-shaped so the affordance is clear:\n horizontal bar for vertical drag (N / S), vertical\n bar for horizontal drag (E / W). */\n .liteeditor-table-resize-handle.n,\n .liteeditor-table-resize-handle.s {\n width: 22px;\n height: 6px;\n left: 50%;\n margin-left: -11px;\n border-radius: 3px;\n cursor: ns-resize;\n }\n .liteeditor-table-resize-handle.n { top: -3px; }\n .liteeditor-table-resize-handle.s { bottom: -3px; }\n .liteeditor-table-resize-handle.e,\n .liteeditor-table-resize-handle.w {\n width: 6px;\n height: 22px;\n top: 50%;\n margin-top: -11px;\n border-radius: 3px;\n cursor: ew-resize;\n }\n .liteeditor-table-resize-handle.e { right: -3px; }\n .liteeditor-table-resize-handle.w { left: -3px; }\n\n /* Anchor marker */\n .liteeditor-anchor {\n display: inline-block;\n width: 16px; height: 16px;\n background: #667eea;\n border-radius: 2px;\n position: relative;\n vertical-align: middle;\n cursor: default;\n }\n .liteeditor-anchor::before {\n content: \'\\2693\';\n position: absolute;\n top: 50%; left: 50%;\n transform: translate(-50%, -50%);\n font-size: 11px; color: #fff; line-height: 1;\n }\n .liteeditor-anchor::after {\n content: attr(id);\n position: absolute;\n bottom: 100%; left: 50%;\n transform: translateX(-50%);\n background: rgba(0,0,0,0.8);\n color: #fff; padding: 2px 6px;\n border-radius: 3px; font-size: 10px;\n white-space: nowrap;\n display: none; pointer-events: none;\n }\n .liteeditor-anchor:hover::after { display: block; }\n\n /* Search highlights */\n mark.liteeditor-search-highlight {\n background: #ffeb3b;\n color: inherit;\n padding: 0;\n border-radius: 2px;\n }\n mark.liteeditor-search-highlight.current {\n background: #ff9800;\n color: #fff;\n }\n </style>\n </head>\n <body contenteditable="true"></body>\n </html>\n '),this.iframeDoc.close(),this.contentArea=this.iframeDoc.body,this._injectInstanceStyles(),this.resizeHandle=t.createElement("div"),this.resizeHandle.className="liteeditor-resize-handle-bar",this.resizeHandle.innerHTML='<span class="liteeditor-resize-icon">⋮⋮⋮</span>',this.editorContainer.appendChild(this.resizeHandle),this.setupEditorResize()}initializePlugins(){const e=(this.config.plugins||"").trim();("all"===e||"full"===e?Object.keys(a):e?e.split(/\s+/):[]).forEach(e=>{const t=a[e];t&&(this.plugins[e]=new t(this))})}static FULL_TOOLBAR="undo redo | blocks fontfamily fontsize | bold italic underline strikethrough | forecolor backcolor | link image media table | align lineheight | numlist bullist indent outdent | emoticons charmap | removeformat | sourcecode | searchreplace codesample visualblocks anchor";createToolbar(){let e=this.config.toolbar||"bold italic underline";"full"!==e&&"all"!==e||(e=o.FULL_TOOLBAR);this.parseToolbarConfig(e).forEach(e=>{if("|"===e){const e=t.createElement("div");e.className="liteeditor-separator",this.toolbar.appendChild(e)}else this.createToolbarButton(e)})}parseToolbarConfig(e){return e.split(/\s+/).filter(e=>e)}createToolbarButton(e){const i=l[e];if(!i)return;const n=t.createElement("button");if(n.type="button",n.className="liteeditor-btn",n.title=i.title,n.dataset.command=e,"dropdown"===i.type){if(n.classList.add("liteeditor-dropdown-btn"),i.showValue){n.classList.add("liteeditor-value-btn");const e=t.createElement("span");e.className="liteeditor-btn-label",e.textContent=i.defaultLabel||i.title,n.appendChild(e)}else n.innerHTML=i.icon;const o=this.createDropdown(e,i.options,i.dropdownOpts||{}),r=t.createElement("div");r.className="liteeditor-dropdown-wrapper",r.appendChild(n),r.appendChild(o),this.toolbar.appendChild(r),n.addEventListener("click",e=>{e.stopPropagation();this.toolbar.querySelectorAll(".liteeditor-dropdown").forEach(e=>{e!==o&&e.classList.remove("active")});const t=!o.classList.contains("active");o.classList.toggle("active"),t&&o._refreshActive&&o._refreshActive()})}else if("dialog"===i.type)n.innerHTML=i.icon,n.addEventListener("click",()=>{i.action(this)}),this.toolbar.appendChild(n);else if("split"===i.type){n.classList.add("liteeditor-split-main"),n.innerHTML=i.icon,n.addEventListener("click",()=>{this.execCommand(e,i.value)});const o=t.createElement("button");o.type="button",o.className="liteeditor-btn liteeditor-split-arrow",o.title=i.title+" options",o.dataset.command=e+"-arrow",o.innerHTML='<span class="liteeditor-split-chevron">▾</span>';const r=this.createDropdown(e,i.options,i.dropdownOpts||{});r.classList.add("liteeditor-split-dropdown");const l=t.createElement("div");l.className="liteeditor-split-wrapper liteeditor-dropdown-wrapper",l.appendChild(n),l.appendChild(o),l.appendChild(r),this.toolbar.appendChild(l),o.addEventListener("click",e=>{e.stopPropagation();this.toolbar.querySelectorAll(".liteeditor-dropdown").forEach(e=>{e!==r&&e.classList.remove("active")});const t=!r.classList.contains("active");r.classList.toggle("active"),t&&r._refreshActive&&r._refreshActive()})}else n.innerHTML=i.icon,n.addEventListener("click",()=>{this.execCommand(e,i.value)}),this.toolbar.appendChild(n)}createDropdown(e,i,n={}){const o=t.createElement("div");o.className="liteeditor-dropdown","grid"===n.variant&&o.classList.add("liteeditor-dropdown-grid");const r=n.detectActive;if(i.forEach(i=>{const n=t.createElement("div");n.className="liteeditor-dropdown-item",i.key&&(n.dataset.key=i.key),i.label&&(n.dataset.label=i.label),i.html?n.innerHTML=i.html:i.icon?n.innerHTML=`<span class="liteeditor-dropdown-item-icon">${i.icon}</span><span class="liteeditor-dropdown-item-label">${i.label}</span>`:n.textContent=i.label,n.addEventListener("click",()=>{i.action?i.action(this):this.execCommand(e,i.value),o.classList.remove("active")}),o.appendChild(n)}),n.showActiveLabel){const e=t.createElement("div");e.className="liteeditor-dropdown-active-label",o.appendChild(e)}return o._refreshActive=()=>{if(!r)return;const e=r(this);let t=null;o.querySelectorAll(".liteeditor-dropdown-item").forEach(i=>{const n=i.dataset.key===e;i.classList.toggle("active",n),n&&(t=i.dataset.label||i.textContent.trim())});const i=o.querySelector(".liteeditor-dropdown-active-label");i&&(i.textContent=t||"")},o}_menubarModel(){const t=l,i=e=>e.map(e=>({label:e.label,action:e.action})),n=e=>r.map(t=>({color:t,action:i=>i.execCommand(e,t)})),o=e=>t=>{const i=t._menuTableCell();i&&e(t,i)},a=e=>!e._menuTableCell();return{file:{label:"File",items:[{label:"New document",action:e=>e.menuNewDocument()},"|",{label:"Preview",action:e=>e.showPreview()},{label:"Print…",action:e=>e.printContent()}]},edit:{label:"Edit",items:[{label:"Undo",shortcut:"Ctrl+Z",action:e=>e.undo(),disabled:e=>e.history.currentIndex<=0},{label:"Redo",shortcut:"Ctrl+Y",action:e=>e.redo(),disabled:e=>e.history.currentIndex>=e.history.stack.length-1},"|",{label:"Cut",shortcut:"Ctrl+X",action:e=>e.execCommand("cut")},{label:"Copy",shortcut:"Ctrl+C",action:e=>e.execCommand("copy")},{label:"Paste",shortcut:"Ctrl+V",action:e=>e.menuPaste()},{label:"Select all",shortcut:"Ctrl+A",action:e=>e.execCommand("selectAll")},"|",{label:"Search & Replace…",shortcut:"Ctrl+F",action:e=>e.showSearchReplace()}]},view:{label:"View",items:[{label:"Source code",action:e=>e.toggleSourceCode(),checked:e=>!!e.sourceCodeMode},{label:"Visual blocks",action:t.visualblocks.action,checked:e=>e.contentArea.classList.contains("liteeditor-visualblocks")}]},insert:{label:"Insert",items:[{label:"Link…",action:e=>e.showLinkModal()},{label:"Image…",action:e=>e.showImageModal()},{label:"Media…",action:e=>e.showMediaModal()},{label:"Table…",action:e=>e.showTableModal()},{label:"Code sample…",action:e=>e.showCodeSampleModal()},{label:"Special character",grid:!0,items:i(t.charmap.options)},{label:"Emojis",grid:!0,items:i(t.emoticons.options)},{label:"Anchor…",action:e=>e.showAnchorModal()},"|",{label:"Horizontal line",action:e=>e.execCommand("insertHorizontalRule")}]},format:{label:"Format",items:[{label:"Bold",shortcut:"Ctrl+B",action:e=>e.execCommand("bold")},{label:"Italic",shortcut:"Ctrl+I",action:e=>e.execCommand("italic")},{label:"Underline",shortcut:"Ctrl+U",action:e=>e.execCommand("underline")},{label:"Strikethrough",action:e=>e.execCommand("strikethrough")},"|",{label:"Blocks",items:i(t.blocks.options)},{label:"Fonts",items:i(t.fontfamily.options)},{label:"Font sizes",items:i(t.fontsize.options)},{label:"Align",items:["left","center","right","justify"].map(e=>({label:e[0].toUpperCase()+e.slice(1),action:t=>t.setAlignment(e)}))},{label:"Line height",items:["1","1.15","1.5","1.75","2","2.5","3"].map(e=>({label:e,action:t=>t.setLineHeight(e)}))},"|",{label:"Text color",grid:!0,items:n("foreColor")},{label:"Background color",grid:!0,items:n("hiliteColor")},"|",{label:"Bullet list",action:e=>e.execCommand("bullist")},{label:"Numbered list",action:e=>e.execCommand("numlist")},{label:"Indent",action:e=>e.execCommand("indent")},{label:"Outdent",action:e=>e.execCommand("outdent")},"|",{label:"Clear formatting",action:e=>e.removeFormatting()}]},tools:{label:"Tools",items:[{label:"Source code",action:e=>e.toggleSourceCode(),checked:e=>!!e.sourceCodeMode},{label:"Word count",action:e=>e.showWordCount()}]},table:{label:"Table",items:[{label:"Insert table…",action:e=>e.showTableModal()},"|",{label:"Insert row above",disabled:a,action:o((e,t)=>e._tableInsertRowAbove(t))},{label:"Insert row below",disabled:a,action:o((e,t)=>e._tableInsertRowBelow(t))},{label:"Delete row",disabled:a,action:o((e,t)=>e._tableDeleteRow(t))},"|",{label:"Insert column left",disabled:a,action:o((e,t)=>e._tableInsertColumnLeft(t))},{label:"Insert column right",disabled:a,action:o((e,t)=>e._tableInsertColumnRight(t))},{label:"Delete column",disabled:a,action:o((e,t)=>e._tableDeleteColumn(t))},"|",{label:"Table properties…",disabled:a,action:o((e,t)=>e._showTablePropertiesModal(t.closest("table")))},{label:"Delete table",disabled:a,action:o((e,t)=>e._tableDeleteTable(t))}]},help:{label:"Help",items:[{label:"Keyboard shortcuts…",action:e=>e.showHelpDialog()},{label:"Version",action:t=>t._infoModal("LiteEditor",'<p style="margin:0">LiteEditor v'+(e.liteeditor&&e.liteeditor.version||"")+"</p>")}]}}}createMenuBar(){const e=!0===this.config.menubar?"file edit view insert format tools table help":String(this.config.menubar),i=this._menubarModel(),n=e.split(/\s+/).filter(e=>i[e]);if(!n.length)return;this._menus=i,this._menuPanels={},this._openMenuKey=null;const o=t.createElement("div");o.className="liteeditor-menubar",o.setAttribute("role","menubar"),n.forEach(e=>{const n=t.createElement("button");n.type="button",n.className="liteeditor-menu-btn",n.dataset.menu=e,n.setAttribute("role","menuitem"),n.textContent=i[e].label,o.appendChild(n)}),this.menubar=o,this.editorContainer.appendChild(o),o.addEventListener("click",e=>this._onMenubarClick(e)),o.addEventListener("mouseover",e=>this._onMenubarHover(e)),o.addEventListener("keydown",e=>this._onMenubarKeydown(e))}_menuItemForPath(e){const t=e.split(":");let i=this._menus[t[0]]&&this._menus[t[0]].items,n=null;for(let e=1;i&&e<t.length;e++)n=i[+t[e]],i=n&&n.items;return n}_buildMenuItemEl(e,i){if("|"===e){const e=t.createElement("div");return e.className="liteeditor-menu-sep",e}const n=t.createElement("div");if(n.className="liteeditor-menu-item",n.dataset.path=i,n.setAttribute("role","menuitem"),n.tabIndex=-1,e.color)return n.classList.add("liteeditor-menu-swatch"),n.style.background=e.color,n.title=e.color,n;const o=t.createElement("span");if(o.className="liteeditor-menu-label",o.textContent=e.label,n.appendChild(o),e.shortcut){const i=t.createElement("span");i.className="liteeditor-menu-shortcut",i.textContent=e.shortcut,n.appendChild(i)}return e.items&&n.classList.add("liteeditor-menu-has-sub"),n}_menuPanel(e){let i=this._menuPanels[e];if(i)return i;i=t.createElement("div"),i.className="liteeditor-menu-panel",i.setAttribute("role","menu"),this._menus[e].items.forEach((t,n)=>{i.appendChild(this._buildMenuItemEl(t,e+":"+n))});const n=this.menubar.querySelector(`[data-menu="${e}"]`);return i.style.left=n.offsetLeft+"px",this.menubar.appendChild(i),this._menuPanels[e]=i,i}_openSubmenu(i){let n=i._subPanel;if(!n){const e=this._menuItemForPath(i.dataset.path);if(!e||!e.items)return;n=t.createElement("div"),n.className="liteeditor-menu-panel liteeditor-menu-subpanel",e.grid&&n.classList.add("liteeditor-menu-grid"),n.setAttribute("role","menu"),e.items.forEach((e,t)=>{n.appendChild(this._buildMenuItemEl(e,i.dataset.path+":"+t))}),i.appendChild(n),i._subPanel=n}this._refreshMenuState(n),n.classList.remove("liteeditor-menu-subpanel--left"),n.classList.add("active"),n.getBoundingClientRect().right>(e.innerWidth||0)&&n.classList.add("liteeditor-menu-subpanel--left")}_closeSubmenus(e,t){e.querySelectorAll(".liteeditor-menu-subpanel.active").forEach(e=>{t&&(e.contains(t)||t.contains(e))||e.classList.remove("active")})}_openMenu(e){if(this._openMenuKey===e)return;this._closeMenus();const t=this._menuPanel(e);this._refreshMenuState(t),t.classList.add("active");const i=this.menubar.querySelector(`[data-menu="${e}"]`);i&&i.classList.add("active"),this._openMenuKey=e}_closeMenus(){if(!this._openMenuKey)return;const e=this._menuPanels[this._openMenuKey];e&&(this._closeSubmenus(e),e.classList.remove("active")),this.menubar.querySelectorAll(".liteeditor-menu-btn.active").forEach(e=>e.classList.remove("active")),this._openMenuKey=null}_refreshMenuState(e){e.querySelectorAll(":scope > .liteeditor-menu-item").forEach(e=>{const t=this._menuItemForPath(e.dataset.path);t&&(t.disabled&&e.classList.toggle("disabled",!!t.disabled(this)),t.checked&&e.classList.toggle("checked",!!t.checked(this)))})}_onMenubarClick(e){const t=e.target.closest(".liteeditor-menu-btn");if(t)return e.stopPropagation(),void(this._openMenuKey===t.dataset.menu?this._closeMenus():this._openMenu(t.dataset.menu));const i=e.target.closest(".liteeditor-menu-item");if(!i||i.classList.contains("disabled"))return;const n=this._menuItemForPath(i.dataset.path);n&&(n.items?this._openSubmenu(i):(this._closeMenus(),n.action&&n.action(this)))}_onMenubarHover(e){const t=e.target.closest(".liteeditor-menu-btn");if(t)return void(this._openMenuKey&&t.dataset.menu!==this._openMenuKey&&this._openMenu(t.dataset.menu));if(!this._openMenuKey)return;const i=e.target.closest(".liteeditor-menu-item"),n=this._menuPanels[this._openMenuKey];i&&n&&n.contains(i)&&(this._closeSubmenus(n,i),i.classList.contains("liteeditor-menu-has-sub")&&this._openSubmenu(i))}_onMenubarKeydown(e){if("Escape"===e.key)return void this._closeMenus();if(!this._openMenuKey)return void("ArrowDown"!==e.key&&"Enter"!==e.key||!e.target.classList.contains("liteeditor-menu-btn")||(e.preventDefault(),this._openMenu(e.target.dataset.menu)));const i=this._menuPanels[this._openMenuKey],n=Array.from(i.querySelectorAll(".liteeditor-menu-item:not(.disabled)")).filter(e=>null!==e.offsetParent);if(!n.length)return;const o=n.indexOf(t.activeElement);if("ArrowDown"===e.key||"ArrowUp"===e.key){e.preventDefault();("ArrowDown"===e.key?n[(o+1)%n.length]:n[(o-1+n.length)%n.length]).focus()}else if("Enter"===e.key&&o>=0)e.preventDefault(),n[o].click();else if("ArrowRight"===e.key&&o>=0&&n[o].classList.contains("liteeditor-menu-has-sub"))e.preventDefault(),this._openSubmenu(n[o]);else if("ArrowLeft"===e.key){const t=e.target.closest&&e.target.closest(".liteeditor-menu-subpanel");t&&(e.preventDefault(),t.classList.remove("active"))}}_infoModal(e,t){const i=this.showModal(e,t,()=>!0),n=i.querySelector('[data-action="cancel"]');return n&&(n.style.display="none"),i.querySelector('[data-action="confirm"]').textContent="Close",i}menuNewDocument(){((this.contentArea.textContent||"").trim()||this.contentArea.querySelector("img, table, hr"))&&!e.confirm("Start a new document? Current content will be replaced.")||(this.setContent("<p><br></p>"),this.saveState())}menuPaste(){const e=()=>this._infoModal("Paste",'<p style="margin:0">Your browser blocks pasting from a menu. Use <strong>Ctrl+V</strong> (⌘V on Mac) instead.</p>');navigator.clipboard&&navigator.clipboard.readText?navigator.clipboard.readText().then(e=>{e&&this.execCommand("insertText",e)}).catch(e):e()}_previewDocHTML(){return'<!doctype html><html><head><meta charset="utf-8"><title>Preview</title><style>body{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;font-size:14px;line-height:1.6;color:#333;padding:16px;}img{max-width:100%;height:auto;}a{color:#0066cc;}</style></head><body>'+this.getContent()+"</body></html>"}showPreview(){const e=this._infoModal("Preview",'<div class="liteeditor-preview-holder"></div>');e.classList.add("liteeditor-modal-wide");const i=t.createElement("iframe");i.className="liteeditor-preview-frame",i.setAttribute("sandbox",""),i.setAttribute("srcdoc",this._previewDocHTML()),e.querySelector(".liteeditor-preview-holder").appendChild(i)}printContent(){const e=t.createElement("iframe");e.setAttribute("aria-hidden","true"),e.style.cssText="position:fixed;right:0;bottom:0;width:0;height:0;border:0;",t.body.appendChild(e);const i=e.contentDocument;i.open(),i.write(this._previewDocHTML()),i.close(),setTimeout(()=>{try{e.contentWindow.focus(),e.contentWindow.print()}catch(e){}setTimeout(()=>e.remove(),1e3)},50)}showWordCount(){const e=(this.contentArea.textContent||"").trim(),t=e?e.split(/\s+/).filter(Boolean).length:0,i=(e,t)=>`<tr><td>${e}</td><td style="text-align:right"><strong>${t}</strong></td></tr>`;this._infoModal("Word count",'<table class="liteeditor-help-table">'+i("Words",t)+i("Characters",e.length)+i("Characters (no spaces)",e.replace(/\s/g,"").length)+"</table>")}showHelpDialog(){const t=e.liteeditor&&e.liteeditor.version||"";this._infoModal("Keyboard shortcuts",'<table class="liteeditor-help-table">'+[["Bold","Ctrl + B"],["Italic","Ctrl + I"],["Underline","Ctrl + U"],["Undo","Ctrl + Z"],["Redo","Ctrl + Y / Ctrl + Shift + Z"],["Search & Replace","Ctrl + F"]].map(e=>`<tr><td>${e[0]}</td><td style="text-align:right">${e[1]}</td></tr>`).join("")+"</table>"+`<p style="margin:10px 0 0;color:#888;font-size:12px">LiteEditor v${t}</p>`)}_menuTableCell(){const e=this.iframe&&this.iframe.contentWindow.getSelection();if(!e||!e.rangeCount)return null;let t=e.getRangeAt(0).startContainer;return 3===t.nodeType&&(t=t.parentNode),t&&t.closest?t.closest("td, th"):null}execCommand(e,t=null){this.iframe.contentWindow.focus(),this.restoreSelection();const i={undo:()=>this.undo(),redo:()=>this.redo(),strikethrough:()=>this.iframeDoc.execCommand("strikeThrough",!1,null),removeformat:()=>this.removeFormatting(),align:e=>this.setAlignment(e),lineheight:e=>this.setLineHeight(e),numlist:()=>this._toggleList("ol"),bullist:()=>this._toggleList("ul"),formatBlock:e=>this._formatBlock(e),indent:()=>this.iframeDoc.execCommand("indent",!1,null),outdent:()=>this.iframeDoc.execCommand("outdent",!1,null)};i[e]?i[e](t):this.iframeDoc.execCommand(e,!1,t),this.saveState(),this.syncContent(),this.updateToolbarState()}removeFormatting(){this.iframeDoc.execCommand("removeFormat",!1,null),this.iframeDoc.execCommand("unlink",!1,null);const e=this.iframe.contentWindow.getSelection();if(0===e.rangeCount)return;const t=e.getRangeAt(0),i=t.commonAncestorContainer,n=i.nodeType===Node.TEXT_NODE?i.parentNode:i;if(!n||n===this.contentArea.ownerDocument)return;const o=[],r=this.iframeDoc.createTreeWalker(n,NodeFilter.SHOW_ELEMENT,null);for(n.nodeType===Node.ELEMENT_NODE&&t.intersectsNode(n)&&o.push(n);r.nextNode();)t.intersectsNode(r.currentNode)&&o.push(r.currentNode);const l=new Set(["FONT","SPAN","B","I","U","STRIKE","S","EM","STRONG","SUB","SUP","MARK","SMALL"]);o.forEach(e=>{if(e!==this.contentArea&&(e.removeAttribute("style"),e.removeAttribute("color"),e.removeAttribute("face"),e.removeAttribute("size"),e.removeAttribute("bgcolor"),l.has(e.tagName))){const t=e.parentNode;if(!t)return;for(;e.firstChild;)t.insertBefore(e.firstChild,e);t.removeChild(e)}})}setAlignment(e){this.iframeDoc.execCommand({left:"justifyLeft",center:"justifyCenter",right:"justifyRight",justify:"justifyFull"}[e],!1,null)}setFontSize(e){this.iframe.contentWindow.focus();const t=this.iframe.contentWindow.getSelection();if(!t.rangeCount)return;const i=t.getRangeAt(0);if(i.collapsed){this.iframeDoc.execCommand("fontSize",!1,"7");this.iframeDoc.querySelectorAll('font[size="7"]').forEach(t=>{const i=this.iframeDoc.createElement("span");i.style.fontSize=e,i.innerHTML=t.innerHTML||"&nbsp;",t.parentNode.replaceChild(i,t)})}else{const n=i.toString(),o=this.iframeDoc.createElement("span");o.style.fontSize=e;try{const e=i.extractContents();o.appendChild(e),i.insertNode(o),i.selectNodeContents(o),t.removeAllRanges(),t.addRange(i)}catch(t){const i=`<span style="font-size: ${e}">${n}</span>`;this.iframeDoc.execCommand("insertHTML",!1,i)}}this.saveState(),this.syncContent()}showColorPicker(e){this._colorPicker&&(this._colorPicker.remove(),this._colorPicker=null),this.saveSelection();const i="backcolor"===e?"hiliteColor":"foreColor",n=this.toolbar.querySelector(`[data-command="${e}"]`);if(!n)return;const o=r,l=t.createElement("div");l.className="liteeditor-color-picker",l.innerHTML=`\n <div class="liteeditor-color-grid">\n ${o.map(e=>`<button type="button" class="liteeditor-color-swatch" data-color="${e}" style="background:${e}" title="${e}"></button>`).join("")}\n </div>\n <div class="liteeditor-color-actions">\n <button type="button" class="liteeditor-color-clear" data-action="clear">Remove</button>\n <label class="liteeditor-color-custom">\n Custom\n <input type="color" class="liteeditor-color-input" value="#000000">\n </label>\n </div>\n `,this.anchorPopover(l,n),this._colorPicker=l;const a=t=>{if(this.iframe.contentWindow.focus(),this.restoreSelection(),null===t){this.iframeDoc.execCommand(i,!1,"transparent");const t=this.iframe.contentWindow.getSelection();if(t.rangeCount>0){const i=t.getRangeAt(0);(i.commonAncestorContainer.nodeType===Node.TEXT_NODE?i.commonAncestorContainer.parentNode:i.commonAncestorContainer).querySelectorAll("font, span").forEach(t=>{"forecolor"===e?(t.removeAttribute("color"),t.style.color=""):t.style.backgroundColor="",t.getAttribute("style")||t.removeAttribute("style")})}}else this.iframeDoc.execCommand(i,!1,t);this.saveState(),this.syncContent(),c()};let s=0;const c=()=>{s&&(clearTimeout(s),s=0),this._colorPicker&&(this._colorPicker.remove(),this._colorPicker=null),t.removeEventListener("mousedown",d,!0),this.iframeDoc.removeEventListener("mousedown",h,!0),this._openPickers.delete(c)};this._openPickers.add(c);const d=e=>{l.contains(e.target)||e.target===n||c()},h=()=>c();s=setTimeout(()=>{s=0,t.addEventListener("mousedown",d,!0),this.iframeDoc.addEventListener("mousedown",h,!0)},0),l.querySelectorAll(".liteeditor-color-swatch").forEach(e=>{e.addEventListener("click",()=>a(e.dataset.color))}),l.querySelector('[data-action="clear"]').addEventListener("click",()=>a(null)),l.querySelector(".liteeditor-color-input").addEventListener("input",e=>a(e.target.value))}detectCurrentListStyle(e){const t=this.iframe.contentWindow.getSelection();if(0===t.rangeCount)return null;let i=t.getRangeAt(0).startContainer;i.nodeType===Node.TEXT_NODE&&(i=i.parentNode);const n=i&&i.closest?i.closest(e):null;if(!n)return"none";let o=n,r=n.parentNode;for(;r&&r!==this.contentArea;)r.nodeType===Node.ELEMENT_NODE&&r.tagName&&r.tagName.toLowerCase()===e&&(o=r),r=r.parentNode;const l=o.style.listStyleType;return l||("ul"===e?"default":"decimal")}detectCurrentAlignment(){const e=this.iframe.contentWindow.getSelection();if(0===e.rangeCount)return null;let t=e.getRangeAt(0).startContainer;t.nodeType===Node.TEXT_NODE&&(t=t.parentNode);const i=new Set(["P","H1","H2","H3","H4","H5","H6","DIV","BLOCKQUOTE","LI","TD","TH","PRE"]);for(;t&&t!==this.contentArea;){if(t.nodeType===Node.ELEMENT_NODE&&i.has(t.tagName)){const e=t.style.textAlign;if(e)return e;const i=this.iframe.contentWindow.getComputedStyle(t);if(i.textAlign&&"start"!==i.textAlign)return i.textAlign;break}t=t.parentNode}return"left"}removeList(){const e=this.iframe.contentWindow.getSelection();if(!e||0===e.rangeCount)return;let t=e.getRangeAt(0).startContainer;t.nodeType===Node.TEXT_NODE&&(t=t.parentNode);const i=t&&t.closest?t.closest("li"):null,n=i&&i.parentElement?i.parentElement.tagName:null;"OL"===n?this.execCommand("numlist"):"UL"===n&&this.execCommand("bullist")}_toggleList(e){const t=this.iframe.contentWindow.getSelection();if(!t||0===t.rangeCount)return;const i=t.getRangeAt(0);let n=i.startContainer;n.nodeType===Node.TEXT_NODE&&(n=n.parentNode);const o=n&&n.closest?n.closest("li"):null;let r=o?o.parentElement:null;if(!r){r=(n&&n.childNodes?Array.from(n.childNodes):[]).find(e=>e.nodeType===Node.ELEMENT_NODE&&/^(UL|OL)$/.test(e.tagName)&&(i.intersectsNode?i.intersectsNode(e):e.contains(i.startContainer)))||null}if(r&&r.tagName.toLowerCase()===e)this._unwrapListItems(r);else if(r){const t=this.iframeDoc.createElement(e);for(;r.firstChild;)t.appendChild(r.firstChild);r.parentNode.replaceChild(t,r),this._selectNodeContents(t)}else this._wrapBlocksInList(e)}_wrapBlocksInList(e){const t=this.iframe.contentWindow.getSelection().getRangeAt(0);let i=t.commonAncestorContainer;i.nodeType===Node.TEXT_NODE&&(i=i.parentNode),i=i.closest&&i.closest("td, th, blockquote")||this.contentArea;const n=this.iframeDoc.createElement(e);let o=null,r=!1;const l=[];Array.from(i.childNodes).forEach(e=>{if(!(t.intersectsNode?t.intersectsNode(e):e.contains(t.startContainer)||e.contains(t.endContainer)))return void(o=null);r||(i.insertBefore(n,e),r=!0);const a=e.nodeType===Node.ELEMENT_NODE?e.tagName.toLowerCase():"",s=e.nodeType!==Node.ELEMENT_NODE||0===this.iframe.contentWindow.getComputedStyle(e).display.indexOf("inline");if("ul"===a||"ol"===a){for(;e.firstChild;)n.appendChild(e.firstChild);l.push(e),o=null}else if("p"===a||"div"===a){const t=this.iframeDoc.createElement("li");for(;e.firstChild;)t.appendChild(e.firstChild);n.appendChild(t),l.push(e),o=null}else if(s)o||(o=this.iframeDoc.createElement("li"),n.appendChild(o)),o.appendChild(e),l.push(null);else{const t=this.iframeDoc.createElement("li");t.appendChild(e),n.appendChild(t),l.push(null),o=null}}),n.childNodes.length?(l.forEach(e=>{e&&e.parentNode&&e.parentNode.removeChild(e)}),this._selectNodeContents(n)):r&&n.remove()}_unwrapListItems(e){const t=this.iframe.contentWindow.getSelection(),i=t.getRangeAt(0),n=Array.from(e.children).filter(e=>"LI"===e.tagName),o=n.filter(e=>i.intersectsNode?i.intersectsNode(e):e.contains(i.startContainer)||e.contains(i.endContainer));if(!o.length)return;const r=e.parentNode,l=n.slice(n.indexOf(o[o.length-1])+1),a=[],s=/^(H[1-6]|PRE|BLOCKQUOTE|TABLE|HR|FIGURE|P|DIV)$/;o.forEach(e=>{if(1===e.children.length&&1===e.childNodes.length&&s.test(e.children[0].tagName))return a.push(e.children[0]),void e.remove();const t=this.iframeDoc.createElement("p");for(;e.firstChild;)t.appendChild(e.firstChild);a.push(t),e.remove()});let c=null;l.length&&(c=this.iframeDoc.createElement(e.tagName.toLowerCase()),l.forEach(e=>c.appendChild(e)));const d=e.nextSibling;a.forEach(e=>r.insertBefore(e,d)),c&&r.insertBefore(c,d),e.children.length||e.remove();const h=this.iframeDoc.createRange();h.setStartBefore(a[0]),h.setEndAfter(a[a.length-1]),t.removeAllRanges(),t.addRange(h)}_formatBlock(e){const t=this.iframe.contentWindow.getSelection();if(!t||0===t.rangeCount)return;let i=t.getRangeAt(0).startContainer;i.nodeType===Node.TEXT_NODE&&(i=i.parentNode);const n=i&&i.closest?i.closest("li"):null;if(!n)return void this.iframeDoc.execCommand("formatBlock",!1,e);const o=/^(H[1-6]|P|PRE|BLOCKQUOTE|DIV)$/;if(Array.from(n.children).forEach(e=>{if(o.test(e.tagName)){for(;e.firstChild;)n.insertBefore(e.firstChild,e);e.remove()}}),"p"===e.toLowerCase())return void this._selectNodeContents(n);const r=this.iframeDoc.createElement(e);Array.from(n.childNodes).forEach(e=>{e.nodeType===Node.ELEMENT_NODE&&/^(UL|OL)$/.test(e.tagName)||r.appendChild(e)}),n.insertBefore(r,n.firstChild),this._selectNodeContents(r)}_selectNodeContents(e){const t=this.iframe.contentWindow.getSelection(),i=this.iframeDoc.createRange();i.selectNodeContents(e),t.removeAllRanges(),t.addRange(i)}setListStyle(e,t){this.iframe.contentWindow.focus(),this.restoreSelection();const i=this.iframe.contentWindow.getSelection();if(0===i.rangeCount)return;const n=()=>{let t=i.getRangeAt(0).startContainer;return t.nodeType===Node.TEXT_NODE&&(t=t.parentNode),t&&t.closest?t.closest(e):null};let o=n();if(o||(this._toggleList(e),o=n()),!o)return;let r=o,l=o.parentNode;for(;l&&l!==this.contentArea;)l.nodeType===Node.ELEMENT_NODE&&l.tagName&&l.tagName.toLowerCase()===e&&(r=l),l=l.parentNode;"default"===t?(r.style.listStyleType="",r.getAttribute("style")||r.removeAttribute("style"),r.querySelectorAll(e).forEach(e=>{e.style.listStyleType="",e.getAttribute("style")||e.removeAttribute("style")})):r.style.listStyleType=t,this.saveState(),this.syncContent()}anchorPopover(e,t){e.style.position="absolute",e.style.visibility="hidden",this.editorContainer.appendChild(e);const i=this.editorContainer.getBoundingClientRect(),n=t.getBoundingClientRect(),o=n.bottom-i.top+4;let r=n.left-i.left;const l=e.offsetWidth,a=this.editorContainer.clientWidth;r+l>a-4&&(r=Math.max(4,a-l-4)),r<4&&(r=4),e.style.top=o+"px",e.style.left=r+"px",e.style.zIndex="10000",e.style.visibility=""}showLineHeightPicker(){if(this._lineHeightPicker)return this._lineHeightPicker.remove(),void(this._lineHeightPicker=null);this.saveSelection();const e=this.toolbar.querySelector('[data-command="lineheight"]');if(!e)return;const i=this.detectCurrentLineHeight()||"1.5",n=t.createElement("div");n.className="liteeditor-lineheight-picker",n.innerHTML=`\n <div class="liteeditor-lh-section">\n <div class="liteeditor-lh-label">Presets</div>\n <div class="liteeditor-lh-presets">\n ${["1","1.15","1.5","1.75","2","2.5","3"].map(e=>`<button type="button" class="liteeditor-lh-preset" data-value="${e}">${e}</button>`).join("")}\n </div>\n </div>\n <div class="liteeditor-lh-section">\n <div class="liteeditor-lh-label">\n <span>Slider</span>\n <span class="liteeditor-lh-value">${i}</span>\n </div>\n <input type="range" class="liteeditor-lh-slider" min="0.5" max="4" step="0.05" value="${i}">\n <div class="liteeditor-lh-slider-range"><span>0.5</span><span>4.0</span></div>\n </div>\n <div class="liteeditor-lh-section liteeditor-lh-custom">\n <input type="number" class="liteeditor-lh-input" min="0" step="0.05" value="${i}" placeholder="1.5">\n <button type="button" class="liteeditor-lh-apply">Apply</button>\n <button type="button" class="liteeditor-lh-reset">Reset</button>\n </div>\n `,this.anchorPopover(n,e),this._lineHeightPicker=n;const o=n.querySelector(".liteeditor-lh-slider"),r=n.querySelector(".liteeditor-lh-value"),l=n.querySelector(".liteeditor-lh-input"),a=e=>{this.iframe.contentWindow.focus(),this.restoreSelection(),this.setLineHeight(e),this.saveSelection()},s=e=>{a(e),this.saveState()};n.querySelectorAll(".liteeditor-lh-preset").forEach(e=>{e.addEventListener("click",()=>{const t=e.dataset.value;o.value=t,l.value=t,r.textContent=t,s(t)})}),o.addEventListener("input",()=>{const e=o.value;r.textContent=e,l.value=e,a(e)}),o.addEventListener("change",()=>{this.saveState()});const c=()=>{const e=l.value.trim();if(""===e)return;const t=parseFloat(e);if(isNaN(t)||t<0)return;const i=t.toString();o.value=Math.min(Math.max(t,.5),4),r.textContent=i,s(i)};l.addEventListener("keydown",e=>{"Enter"===e.key&&(e.preventDefault(),c())}),n.querySelector(".liteeditor-lh-apply").addEventListener("click",c),n.querySelector(".liteeditor-lh-reset").addEventListener("click",()=>{o.value="1.5",l.value="",r.textContent="default",s(null)});let d=0;const h=()=>{d&&(clearTimeout(d),d=0),this._lineHeightPicker&&(this._lineHeightPicker.remove(),this._lineHeightPicker=null),t.removeEventListener("mousedown",p,!0),t.removeEventListener("keydown",m,!0),this.iframeDoc.removeEventListener("mousedown",u,!0),this.iframeDoc.removeEventListener("keydown",m,!0),this._openPickers.delete(h)};this._openPickers.add(h);const p=t=>{n.contains(t.target)||t.target===e||e.contains(t.target)||h()},u=()=>h(),m=e=>{"Escape"===e.key&&h()};d=setTimeout(()=>{d=0,t.addEventListener("mousedown",p,!0),t.addEventListener("keydown",m,!0),this.iframeDoc.addEventListener("mousedown",u,!0),this.iframeDoc.addEventListener("keydown",m,!0)},0)}detectCurrentLineHeight(){const e=this.iframe.contentWindow.getSelection();if(0===e.rangeCount)return null;const t=e.getRangeAt(0).commonAncestorContainer,i=t.nodeType===Node.TEXT_NODE?t.parentNode:t;if(!i)return null;const n=i.style&&i.style.lineHeight;if(n&&!n.endsWith("px"))return n;const o=this.iframe.contentWindow.getComputedStyle(i),r=o.lineHeight;if(r&&r.endsWith("px")){const e=parseFloat(o.fontSize);if(e>0)return(parseFloat(r)/e).toFixed(2)}return null}setLineHeight(e){const t=this.iframe.contentWindow.getSelection();if(0===t.rangeCount)return;const i=t.getRangeAt(0),n=new Set(["P","H1","H2","H3","H4","H5","H6","DIV","BLOCKQUOTE","LI","TD","TH","PRE"]),o=new Set,r=e=>{for(;e&&e!==this.contentArea;){if(e.nodeType===Node.ELEMENT_NODE&&n.has(e.tagName))return e;e=e.parentNode}return null},l=r(i.startContainer),a=r(i.endContainer);l&&o.add(l),a&&o.add(a);const s=this.iframeDoc.createTreeWalker(this.contentArea,NodeFilter.SHOW_ELEMENT,{acceptNode:e=>n.has(e.tagName)?i.intersectsNode(e)?NodeFilter.FILTER_ACCEPT:NodeFilter.FILTER_REJECT:NodeFilter.FILTER_SKIP});for(;s.nextNode();)o.add(s.currentNode);const c=t=>{null===e||""===e||void 0===e?(t.style.lineHeight="",t.getAttribute("style")||t.removeAttribute("style")):t.style.lineHeight=e};0===o.size?c(this.contentArea):o.forEach(c),this.syncContent()}attachEventListeners(){this.contentArea.addEventListener("input",()=>{this.syncContent(),this._scheduleSaveState(),this.onContentChanged()}),this.contentArea.addEventListener("keydown",e=>{(e.ctrlKey||e.metaKey)&&("z"===e.key?(e.preventDefault(),this.undo()):"y"===e.key||e.shiftKey&&"z"===e.key?(e.preventDefault(),this.redo()):"b"===e.key?(e.preventDefault(),this.execCommand("bold")):"i"===e.key?(e.preventDefault(),this.execCommand("italic")):"u"===e.key?(e.preventDefault(),this.execCommand("underline")):"f"!==e.key&&"h"!==e.key||(e.preventDefault(),this.showSearchReplace()))}),this.contentArea.addEventListener("mouseup",()=>{this.updateToolbarState()}),this.contentArea.addEventListener("keyup",()=>{this.updateToolbarState()}),this._onToolbarMouseDown=e=>{const t=e.target;"INPUT"===t.tagName||"TEXTAREA"===t.tagName||"SELECT"===t.tagName||t.isContentEditable||t.closest(".liteeditor-btn, .liteeditor-dropdown-item")&&(this.saveSelection(),e.preventDefault())},this.toolbar.addEventListener("mousedown",this._onToolbarMouseDown);let e=0;this._onSelectionChange=()=>{if(e)return;if(!this.toolbar||!this.iframe||!this.iframe.contentWindow)return;const t=this.iframe.contentWindow.requestAnimationFrame||(e=>this.iframe.contentWindow.setTimeout(e,16));e=t.call(this.iframe.contentWindow,()=>{e=0,this.toolbar&&this.iframe&&this.iframe.contentWindow&&(this.updateToolbarState(),this._syncTableActiveState())})},this.iframeDoc.addEventListener("selectionchange",this._onSelectionChange),this._closeDropdowns=e=>{this.toolbar.querySelectorAll(".liteeditor-dropdown").forEach(e=>e.classList.remove("active")),!this.menubar||e&&e.target&&this.menubar.contains(e.target)||this._closeMenus()},t.addEventListener("click",this._closeDropdowns),this.contentArea.addEventListener("click",this._closeDropdowns),this.iframeDoc.addEventListener("click",this._closeDropdowns),this.contentArea.addEventListener("paste",e=>{e.preventDefault();const t=e.clipboardData;if(!t)return;const i=t.getData("text/html"),n=t.getData("text/plain");if(i)try{return void this.iframeDoc.execCommand("insertHTML",!1,this.sanitizeHTML(i))}catch(e){}if(n)try{this.iframeDoc.execCommand("insertHTML",!1,n.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/\n/g,"<br>"))}catch(e){}}),this.setupImageResize(),this.setupFormSubmitHook()}setupFormSubmitHook(){const e=this.element&&this.element.form;e&&(this._onFormSubmit=()=>{try{this.syncContent()}catch(e){}},e.addEventListener("submit",this._onFormSubmit,!0))}setupEditorResize(){let e=!1,i=0,n=0;this.resizeHandle.addEventListener("mousedown",o=>{e=!0,i=o.clientY,n=this.iframe.offsetHeight,t.body.style.cursor="ns-resize",t.body.style.userSelect="none",o.preventDefault()}),this._onResizeMove=t=>{if(!e)return;const o=t.clientY-i,r=Math.max(100,Math.min(1e3,n+o));this.iframe.style.height=r+"px"},this._onResizeUp=()=>{e&&(e=!1,t.body.style.cursor="",t.body.style.userSelect="")},t.addEventListener("mousemove",this._onResizeMove),t.addEventListener("mouseup",this._onResizeUp)}setupImageResize(){this.contentArea.addEventListener("click",e=>{if("IMG"===e.target.tagName)this.selectImage(e.target);else if(e.target.closest(".liteeditor-image-resizer")){const t=e.target.closest(".liteeditor-image-resizer").querySelector("img");t&&this.selectImage(t)}else this.deselectImage()}),this.contentArea.addEventListener("dblclick",e=>{let t=null;if("IMG"===e.target.tagName)t=e.target;else{const i=e.target.closest&&e.target.closest(".liteeditor-image-resizer");i&&(t=i.querySelector("img"))}t&&(e.preventDefault(),e.stopPropagation(),this.showImageModal(t))}),this._imageObserver=new MutationObserver(()=>{this.contentArea.querySelectorAll("img:not(.wrapped)").forEach(e=>{e.parentElement.classList.contains("liteeditor-image-resizer")||this.wrapImage(e)});this.contentArea.querySelectorAll("table").forEach(e=>{e.parentElement&&e.parentElement.classList.contains("liteeditor-table-wrapper")||this.wrapTable(e)})}),this._imageObserver.observe(this.contentArea,{childList:!0,subtree:!0})}_injectInstanceStyles(){const e=this._defaultStyles;if(!e)return;const t={table:"table",th:"table th",td:"table td",blockquote:"blockquote",pre:"pre",code:"code",hr:"hr",img:"img",ul:"ul",ol:"ol",li:"li"},i=Object.keys(t).filter(t=>e[t]).map(i=>`${t[i]} { ${e[i]} }`).join("\n");if(!i)return;const n=this.iframeDoc.createElement("style");n.setAttribute("data-liteeditor-instance-styles","1"),n.textContent=i,this.iframeDoc.head.appendChild(n)}_buildImageStyle(e,t,i){const n=this._defaultStyles&&this._defaultStyles.img?this._defaultStyles.img:"",o=n?[n.replace(/;?\s*$/,";")]:[],r=e?parseInt(e,10):0,l=t?parseInt(t,10):0;return r&&l?(o.push(` width: ${r}px;`),o.push(` aspect-ratio: ${r} / ${l};`)):r?o.push(` width: ${r}px;`):l&&(o.push(` height: ${l}px;`),o.push(" width: auto;")),i&&o.push(" "+i.replace(/^\s*;?\s*/,"").replace(/;?\s*$/,";")),o.join("").trim()}_readImageFields(e){const t=(e.style&&e.style.width||"").match(/(\d+)/),i=(e.style&&e.style.height||"").match(/(\d+)/),n=e.closest&&e.closest("a");return{url:e.getAttribute("src")||"",alt:e.getAttribute("alt")||"",width:t?t[1]:e.getAttribute("width")||"",height:i?i[1]:e.getAttribute("height")||"",link:n&&n.getAttribute("href")||"",linkNewTab:!(!n||"_blank"!==n.getAttribute("target"))}}_insertImage(e){const t=e=>String(null==e?"":e).replace(/&/g,"&amp;").replace(/"/g,"&quot;").replace(/</g,"&lt;").replace(/>/g,"&gt;"),i=n.sanitizeUrl(e.url,{allowDataImage:!0}),o=this._buildImageStyle(e.width,e.height);let r=`<img src="${t(i)}" alt="${t(e.alt||"")}"`;if(o&&(r+=` style="${o}"`),r+=" />",e.link){const i=n.sanitizeUrl(e.link);if(i){const n=e.linkNewTab?' target="_blank" rel="noopener noreferrer"':"";r=`<a href="${t(i)}"${n}>${r}</a>`}}this.execCommand("insertHTML",r)}_updateImage(e,t){void 0!==t.url&&e.setAttribute("src",n.sanitizeUrl(t.url,{allowDataImage:!0})),void 0!==t.alt&&e.setAttribute("alt",t.alt||"");const i=e.getAttribute("style")||"",o=["float","display","margin","margin-left","margin-right","margin-top","margin-bottom"],r=i.split(";").map(e=>e.trim()).filter(Boolean).filter(e=>{const t=e.split(":")[0].trim().toLowerCase();return o.includes(t)}).join("; ");e.setAttribute("style",this._buildImageStyle(t.width,t.height,r)),this._setImageLink(e,t.link,t.linkNewTab),this.syncContent(),this.saveState(),this.onContentChanged(),this.updateImageInfo(e.closest(".liteeditor-image-resizer"),e)}_setImageAlign(e,t){const i=new Set(["float","display","margin","margin-left","margin-right","margin-top","margin-bottom"]),n=(e.getAttribute("style")||"").split(";").map(e=>e.trim()).filter(Boolean).filter(e=>!i.has(e.split(":")[0].trim().toLowerCase())),o=new Set(n.map(e=>e.split(":")[0].trim().toLowerCase()));o.has("max-width")||n.unshift("max-width: 100%"),o.has("height")||n.push("height: auto"),"left"===t?(n.push("float: left"),n.push("margin: 0 16px 8px 0")):"right"===t?(n.push("float: right"),n.push("margin: 0 0 8px 16px")):"center"===t&&(n.push("display: block"),n.push("margin-left: auto"),n.push("margin-right: auto")),e.setAttribute("style",n.join("; ")),this.syncContent(),this.saveState(),this.onContentChanged()}_setImageLink(e,t,i){const o=e.closest(".liteeditor-image-resizer")||e,r=o.parentNode,l=r&&"A"===r.tagName,a=t?n.sanitizeUrl(t):"";if(a){let e;l?e=r:(e=this.iframeDoc.createElement("a"),r.insertBefore(e,o),e.appendChild(o)),e.setAttribute("href",a),i?(e.setAttribute("target","_blank"),e.setAttribute("rel","noopener noreferrer")):(e.removeAttribute("target"),e.removeAttribute("rel"))}else if(l){for(;r.firstChild;)r.parentNode.insertBefore(r.firstChild,r);r.remove()}}_replaceImageFile(e){const t=this.iframeDoc.createElement("input");t.type="file",t.accept="image/*",t.style.display="none",t.addEventListener("change",()=>{const i=t.files&&t.files[0];if(!i)return void t.remove();this._trackReader(new FileReader,n=>{e.isConnected?(e.setAttribute("src",n.target.result),e.getAttribute("alt")||e.setAttribute("alt",i.name),this.syncContent(),this.saveState(),this.onContentChanged(),t.remove()):t.remove()}).readAsDataURL(i)}),this.iframeDoc.body.appendChild(t),t.click()}_deleteImage(e){const t=e.closest(".liteeditor-image-resizer")||e,i=t.closest&&t.closest("a");(i&&1===i.childNodes.length&&i.childNodes[0]===t?i:t).remove(),this.syncContent(),this.saveState(),this.onContentChanged()}_showImageLinkPopover(e,t){const i=e.querySelector(".liteeditor-image-link-popover");if(i)return void i.remove();const n=t.closest("a"),o=n&&n.getAttribute("href")||"",r=!(!n||"_blank"!==n.getAttribute("target")),l=this.iframeDoc.createElement("div");var a;l.className="liteeditor-image-link-popover",l.setAttribute("data-liteeditor-chrome","1"),l.contentEditable="false",l.innerHTML=`\n <input type="url" class="liteeditor-img-link-input" placeholder="https://example.com" value="${a=o,String(null==a?"":a).replace(/&/g,"&amp;").replace(/"/g,"&quot;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}">\n <label class="liteeditor-img-link-newtab"><input type="checkbox" ${r?"checked":""}>New tab</label>\n <button type="button" class="liteeditor-img-link-save" data-action="save">Save</button>\n ${o?'<button type="button" class="liteeditor-img-link-remove" data-action="remove">Remove</button>':""}\n `;const s=l.querySelector('input[type="url"]'),c=l.querySelector('input[type="checkbox"]'),d=()=>{this._setImageLink(t,s.value.trim(),c.checked),this.syncContent(),this.saveState(),this.onContentChanged(),l.remove()};l.querySelector('[data-action="save"]').addEventListener("click",d);const h=l.querySelector('[data-action="remove"]');h&&h.addEventListener("click",()=>{this._setImageLink(t,"",!1),this.syncContent(),this.saveState(),this.onContentChanged(),l.remove()}),s.addEventListener("keydown",e=>{"Enter"===e.key&&(e.preventDefault(),d()),"Escape"===e.key&&(e.preventDefault(),l.remove())}),l.addEventListener("mousedown",e=>e.stopPropagation()),l.addEventListener("click",e=>e.stopPropagation()),e.appendChild(l),s.focus(),s.select()}_buildImageToolbar(e,t){const i=this.iframeDoc.createElement("div");i.className="liteeditor-image-toolbar",i.setAttribute("data-liteeditor-chrome","1"),i.contentEditable="false";const n=(e,t,i)=>{const n=this.iframeDoc.createElement("button");return n.type="button",n.className="liteeditor-img-toolbar-btn",n.title=t,n.innerHTML=e,n.setAttribute("data-liteeditor-chrome","1"),n.addEventListener("mousedown",e=>{e.preventDefault()}),n.addEventListener("click",e=>{e.preventDefault(),e.stopPropagation(),i()}),n},o=()=>{const e=this.iframeDoc.createElement("span");return e.className="liteeditor-img-toolbar-sep",e.setAttribute("data-liteeditor-chrome","1"),e},r='<svg viewBox="0 0 16 16" width="14" height="14"><path fill="currentColor" d="M11.7 1.3a1 1 0 0 1 1.4 0l1.6 1.6a1 1 0 0 1 0 1.4l-9 9-3.7.7.7-3.7 9-9zM10.6 3.4l2 2"/></svg>',l='<svg viewBox="0 0 16 16" width="14" height="14"><path fill="currentColor" d="M8 2a6 6 0 0 1 5.7 4.1l1.3-.4-1.5 3-3-1.5 1.3-.4A4 4 0 0 0 4.5 9H2.5A6 6 0 0 1 8 2zM2.5 7.4l3 1.5-1.3.4A4 4 0 0 0 11.5 7h2A6 6 0 0 1 2.3 10.4l-1.3.4 1.5-3.4z"/></svg>',a='<svg viewBox="0 0 16 16" width="14" height="14"><rect fill="currentColor" x="1" y="2" width="6" height="6"/><rect fill="currentColor" x="1" y="10" width="14" height="1.4"/><rect fill="currentColor" x="1" y="13" width="14" height="1.4"/></svg>',s='<svg viewBox="0 0 16 16" width="14" height="14"><rect fill="currentColor" x="5" y="2" width="6" height="6"/><rect fill="currentColor" x="1" y="10" width="14" height="1.4"/><rect fill="currentColor" x="1" y="13" width="14" height="1.4"/></svg>',c='<svg viewBox="0 0 16 16" width="14" height="14"><rect fill="currentColor" x="9" y="2" width="6" height="6"/><rect fill="currentColor" x="1" y="10" width="14" height="1.4"/><rect fill="currentColor" x="1" y="13" width="14" height="1.4"/></svg>',d='<svg viewBox="0 0 16 16" width="14" height="14"><path fill="none" stroke="currentColor" stroke-width="1.6" d="M6 9a3 3 0 0 0 4 0l2-2a3 3 0 0 0-4-4l-1 1M10 7a3 3 0 0 0-4 0L4 9a3 3 0 0 0 4 4l1-1"/></svg>',h='<svg viewBox="0 0 16 16" width="14" height="14"><path fill="currentColor" d="M6 1h4l1 1h3v2H2V2h3l1-1zm-3 4h10l-1 9.5a1 1 0 0 1-1 .9H5a1 1 0 0 1-1-.9L3 5z"/></svg>';i.appendChild(n(r,"Edit image",()=>this.showImageModal(t))),i.appendChild(n(l,"Replace image",()=>this._replaceImageFile(t))),i.appendChild(o()),i.appendChild(n(a,"Align left",()=>this._setImageAlign(t,"left"))),i.appendChild(n(s,"Align center",()=>this._setImageAlign(t,"center"))),i.appendChild(n(c,"Align right",()=>this._setImageAlign(t,"right"))),i.appendChild(o()),i.appendChild(n(d,"Add or edit link",()=>this._showImageLinkPopover(e,t))),i.appendChild(o()),i.appendChild(n(h,"Remove image",()=>this._deleteImage(t))),e.appendChild(i)}wrapTable(e){const t=this.iframeDoc.createElement("div");t.className="liteeditor-table-wrapper",t.setAttribute("data-liteeditor-chrome","1"),e.parentNode.insertBefore(t,e),t.appendChild(e),this._buildTableToolbar(t),this._attachTableResizeHandles(t,e),this._syncWrapperAlignment(t,e),this._syncWrapperWidth(t,e),this.syncContent()}_attachTableResizeHandles(e,t){const i=this.iframeDoc;["nw","n","ne","e","se","s","sw","w"].forEach(n=>{const o=i.createElement("span");o.className=`liteeditor-table-resize-handle ${n}`,o.setAttribute("data-liteeditor-chrome","1"),o.setAttribute("contenteditable","false"),o.addEventListener("mousedown",i=>{i.preventDefault(),i.stopPropagation(),this._startTableResize(i,e,t,n)}),e.appendChild(o)})}_startTableResize(e,i,n,o){const r=e.clientX,l=e.clientY,a=n.offsetWidth,s=n.offsetHeight,c="nw"===o||"w"===o||"sw"===o,d="nw"===o||"n"===o||"ne"===o,h=c||("ne"===o||"e"===o||"se"===o),p=d||("sw"===o||"s"===o||"se"===o),u=e=>{e.preventDefault();const t=e.clientX-r,o=e.clientY-l;if(h){const e=Math.max(80,c?a-t:a+t);n.style.width=e+"px","100%"===n.style.maxWidth&&(n.style.maxWidth=""),this._syncWrapperWidth(i,n)}if(p){const e=Math.max(30,d?s-o:s+o);n.style.height=e+"px"}},m=()=>{this.iframeDoc.removeEventListener("mousemove",u),this.iframeDoc.removeEventListener("mouseup",f),t.removeEventListener("mousemove",u),t.removeEventListener("mouseup",f),this._activeResize===m&&(this._activeResize=null)},f=()=>{m(),this.syncContent(),this.saveState(),this.onContentChanged()};this._activeResize=m,this.iframeDoc.addEventListener("mousemove",u),this.iframeDoc.addEventListener("mouseup",f),t.addEventListener("mousemove",u),t.addEventListener("mouseup",f)}_buildTableToolbar(e){const t=this.iframeDoc,i=t.createElement("div");i.className="liteeditor-table-toolbar",i.setAttribute("data-liteeditor-chrome","1"),i.contentEditable="false";const n=(i,n,o)=>{const r=t.createElement("button");return r.type="button",r.className="liteeditor-tbl-toolbar-btn",r.title=n,r.innerHTML=i,r.setAttribute("data-liteeditor-chrome","1"),r.addEventListener("mousedown",e=>e.preventDefault()),r.addEventListener("click",t=>{t.preventDefault(),t.stopPropagation();const i=e._activeCell;i&&i.isConnected&&o(i)}),r},o=()=>{const e=t.createElement("span");return e.className="liteeditor-tbl-toolbar-sep",e.setAttribute("data-liteeditor-chrome","1"),e},r='<svg viewBox="0 0 16 16" width="14" height="14"><rect x="1" y="6" width="14" height="3" fill="currentColor"/><rect x="1" y="11" width="14" height="3" fill="currentColor" opacity="0.45"/><path d="M8 1v3M6.5 2.5L8 1l1.5 1.5" stroke="currentColor" stroke-width="1.4" fill="none" stroke-linecap="round" stroke-linejoin="round"/></svg>',l='<svg viewBox="0 0 16 16" width="14" height="14"><rect x="1" y="2" width="14" height="3" fill="currentColor" opacity="0.45"/><rect x="1" y="7" width="14" height="3" fill="currentColor"/><path d="M8 15v-3M6.5 13.5L8 15l1.5-1.5" stroke="currentColor" stroke-width="1.4" fill="none" stroke-linecap="round" stroke-linejoin="round"/></svg>',a='<svg viewBox="0 0 16 16" width="14" height="14"><rect x="1" y="7" width="14" height="3" fill="currentColor"/><path d="M3 4l3 3M6 4L3 7M10 4l3 3M13 4l-3 3" stroke="currentColor" stroke-width="1.4" fill="none" stroke-linecap="round"/></svg>',s='<svg viewBox="0 0 16 16" width="14" height="14"><rect x="6" y="1" width="3" height="14" fill="currentColor"/><rect x="11" y="1" width="3" height="14" fill="currentColor" opacity="0.45"/><path d="M1 8h3M2.5 6.5L1 8l1.5 1.5" stroke="currentColor" stroke-width="1.4" fill="none" stroke-linecap="round" stroke-linejoin="round"/></svg>',c='<svg viewBox="0 0 16 16" width="14" height="14"><rect x="2" y="1" width="3" height="14" fill="currentColor" opacity="0.45"/><rect x="7" y="1" width="3" height="14" fill="currentColor"/><path d="M15 8h-3M13.5 6.5L15 8l-1.5 1.5" stroke="currentColor" stroke-width="1.4" fill="none" stroke-linecap="round" stroke-linejoin="round"/></svg>',d='<svg viewBox="0 0 16 16" width="14" height="14"><rect x="7" y="1" width="3" height="14" fill="currentColor"/><path d="M4 3l3 3M7 3L4 6M4 10l3 3M7 10l-3 3M12 3l-3 3M9 3l3 3M12 10l-3 3M9 10l3 3" stroke="currentColor" stroke-width="1.2" fill="none" stroke-linecap="round"/></svg>',h='<svg viewBox="0 0 16 16" width="14" height="14"><rect x="1" y="2" width="14" height="12" fill="none" stroke="currentColor" stroke-width="1.4"/><path d="M1 6h14M1 10h14M6 2v12M10 2v12" stroke="currentColor" stroke-width="1.4" fill="none"/><path d="M3 3l10 10M13 3L3 13" stroke="#e53935" stroke-width="1.6" fill="none" stroke-linecap="round"/></svg>',p='<svg viewBox="0 0 16 16" width="14" height="14"><circle cx="8" cy="8" r="2" fill="currentColor"/><path d="M8 1v2M8 13v2M1 8h2M13 8h2M3.1 3.1l1.4 1.4M11.5 11.5l1.4 1.4M12.9 3.1l-1.4 1.4M4.5 11.5l-1.4 1.4" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" fill="none"/></svg>',u='<svg viewBox="0 0 16 16" width="14" height="14"><rect x="1" y="5" width="14" height="6" fill="none" stroke="currentColor" stroke-width="1.4"/><path d="M3 8h2M11 8h2M4.5 6.5L3 8l1.5 1.5M11.5 6.5L13 8l-1.5 1.5" stroke="currentColor" stroke-width="1.4" fill="none" stroke-linecap="round" stroke-linejoin="round"/></svg>';i.appendChild(n(r,"Insert row above",e=>this._tableInsertRowAbove(e))),i.appendChild(n(l,"Insert row below",e=>this._tableInsertRowBelow(e))),i.appendChild(n(a,"Delete row",e=>this._tableDeleteRow(e))),i.appendChild(o()),i.appendChild(n(s,"Insert column left",e=>this._tableInsertColumnLeft(e))),i.appendChild(n(c,"Insert column right",e=>this._tableInsertColumnRight(e))),i.appendChild(n(d,"Delete column",e=>this._tableDeleteColumn(e))),i.appendChild(o()),i.appendChild(n(h,"Delete table",e=>this._tableDeleteTable(e))),i.appendChild(o()),i.appendChild(n(p,"Table properties",e=>this._showTablePropertiesModal(e.closest("table"))));const m=n(u,"Toggle full width (100%)",e=>this._tableToggleFullWidth(e));m.classList.add("liteeditor-tbl-fullwidth-btn"),i.appendChild(m),e.appendChild(i)}_syncTableActiveState(){const e=this.iframe.contentWindow.getSelection();if(!e||0===e.rangeCount)return void this.contentArea.querySelectorAll(".liteeditor-table-wrapper.active").forEach(e=>{e.classList.remove("active"),e._activeCell=null});let t=e.anchorNode;t&&3===t.nodeType&&(t=t.parentNode);const i=t&&t.closest&&t.closest(".liteeditor-table-wrapper"),n=t&&t.closest&&t.closest("td, th");if(this.contentArea.querySelectorAll(".liteeditor-table-wrapper.active").forEach(e=>{e!==i&&(e.classList.remove("active"),e._activeCell=null)}),i){i.classList.add("active"),n&&i.contains(n)&&(i._activeCell=n);const e=i.querySelector(":scope > table"),t=i.querySelector(".liteeditor-tbl-fullwidth-btn");if(e&&t){const i=(e.style.width||"").trim().toLowerCase();t.classList.toggle("active","100%"===i)}}}_placeTableCursor(e){if(!e||!e.isConnected)return;const t=this.iframeDoc.createRange();t.selectNodeContents(e),t.collapse(!0);const i=this.iframe.contentWindow.getSelection();i.removeAllRanges(),i.addRange(t),this.savedRange=t.cloneRange()}_makeCellLike(e,t){const i=this.iframeDoc,n=e?e.tagName.toLowerCase():t||"td",o=i.createElement(n),r=e&&e.getAttribute("style");return r?o.setAttribute("style",r):this._defaultStyles&&this._defaultStyles[n]&&o.setAttribute("style",this._defaultStyles[n]),o.innerHTML="<br>",o}_afterTableMutation(e){this._placeTableCursor(e),this.syncContent(),this.saveState(),this.onContentChanged(),this.updateToolbarState()}_tableRemoveIfEmpty(e){if(e.querySelector("td, th"))return!1;const t=e.closest(".liteeditor-table-wrapper")||e,i=t.nextSibling||t.previousSibling;if(t.remove(),i&&1===i.nodeType){const e=this.iframeDoc.createRange();e.selectNodeContents(i),e.collapse(!0);const t=this.iframe.contentWindow.getSelection();t.removeAllRanges(),t.addRange(e)}return this.syncContent(),this.saveState(),this.onContentChanged(),!0}_tableInsertRow(e,t){const i=e.closest("tr");if(!i)return;const n=this.iframeDoc.createElement("tr");Array.from(i.cells).forEach(e=>{const t=this._makeCellLike(e);e.hasAttribute("colspan")&&t.setAttribute("colspan",e.getAttribute("colspan")),n.appendChild(t)}),"above"===t?i.parentNode.insertBefore(n,i):i.parentNode.insertBefore(n,i.nextSibling),this._afterTableMutation(n.cells[Array.from(i.cells).indexOf(e)]||n.cells[0])}_tableInsertRowAbove(e){this._tableInsertRow(e,"above")}_tableInsertRowBelow(e){this._tableInsertRow(e,"below")}_tableDeleteRow(e){const t=e.closest("tr");if(!t)return;const i=t.closest("table"),n=t.parentNode,o=t.nextElementSibling||t.previousElementSibling;if(t.remove(),n&&!n.querySelector("tr")&&"TABLE"!==n.tagName&&i.querySelectorAll("tr").length>0&&n.remove(),this._tableRemoveIfEmpty(i))return;const r=o&&o.cells[Array.from(t.cells||[]).indexOf(e)]||o&&o.cells[0];this._afterTableMutation(r)}_tableInsertColumn(e,t){const i=e.closest("tr");if(!i)return;const n=Array.from(i.cells).indexOf(e),o=i.closest("table"),r=[];o.querySelectorAll("tr").forEach(e=>{const o=e.cells[n],l=this._makeCellLike(o,e.parentNode&&"THEAD"===e.parentNode.tagName?"th":"td");o?"left"===t?e.insertBefore(l,o):e.insertBefore(l,o.nextSibling):e.appendChild(l),e===i&&r.push(l)}),this._afterTableMutation(r[0]||e)}_tableInsertColumnLeft(e){this._tableInsertColumn(e,"left")}_tableInsertColumnRight(e){this._tableInsertColumn(e,"right")}_tableDeleteColumn(e){const t=e.closest("tr");if(!t)return;const i=Array.from(t.cells).indexOf(e),n=t.closest("table");if(n.querySelectorAll("tr").forEach(e=>{e.cells[i]&&e.cells[i].remove()}),this._tableRemoveIfEmpty(n))return;const o=t.cells[i]||t.cells[t.cells.length-1];this._afterTableMutation(o)}_tableToggleFullWidth(e){const t=e.closest("table");if(!t)return;const i=t.closest(".liteeditor-table-wrapper");"100%"===(t.style.width||"").trim().toLowerCase()?t.style.removeProperty("width"):(t.style.width="100%",t.style.maxWidth="100%"),this._syncWrapperWidth(i,t),this._afterTableMutation(e)}_tableDeleteTable(e){const t=e.closest("table");if(!t)return;const i=t.closest(".liteeditor-table-wrapper")||t,n=i.nextSibling||i.previousSibling;i.remove();const o=this.iframe.contentWindow.getSelection();if(o.removeAllRanges(),n&&1===n.nodeType){const e=this.iframeDoc.createRange();e.selectNodeContents(n),e.collapse(!0),o.addRange(e)}this.syncContent(),this.saveState(),this.onContentChanged(),this.updateToolbarState()}_readTableProperties(e){const t=t=>{const i=(e.getAttribute("style")||"").match(new RegExp(`(?:^|;)\\s*${t}\\s*:\\s*([^;]+)`,"i"));return i?i[1].trim():""},i=t("width"),n=t("height"),o=e.querySelector("th, td"),r=o&&o.style.padding||"",l=o&&(o.style.borderWidth||(o.style.border&&o.style.border.match(/^(\d+(?:\.\d+)?)px/)||[,""])[1])||"",a=t("border-spacing"),s=e.querySelector(":scope > caption"),c=t("float").toLowerCase(),d=t("margin-left").toLowerCase(),h=t("margin-right").toLowerCase();let p="none";return"left"===c?p="left":"right"===c?p="right":"auto"===d&&"auto"===h&&(p="center"),{width:i||(e.offsetWidth?e.offsetWidth+"px":""),height:n||"",cellPadding:this._extractPxNumber(r),borderWidth:this._extractPxNumber(l),cellSpacing:this._extractPxNumber(a),hasCaption:!!s,captionText:s?s.textContent:"",alignment:p}}_extractPxNumber(e){if(null==e||""===e)return"";const t=String(e).match(/(-?\d+(?:\.\d+)?)/);return t?t[1]:""}_parseDimension(e,t){if(null==e)return"";const i=String(e).trim();if(!i)return"";const n=i.match(/^(-?\d+(?:\.\d+)?)\s*(px|%)?$/i);if(!n)return"";const o=parseFloat(n[1]);if(!isFinite(o)||o<0)return"";return o+(n[2]||t||"px").toLowerCase()}_applyTableProperties(e,t){const i=(e,t,i)=>{""===i||null==i?e.style.removeProperty(t):e.style.setProperty(t,i)},n=this._parseDimension(t.width,"px");i(e,"width",n),"100%"===n?i(e,"max-width","100%"):n&&i(e,"max-width","");const o=e.closest(".liteeditor-table-wrapper");this._syncWrapperWidth(o,e);i(e,"height",this._parseDimension(t.height,"px"));const r=null==t.cellSpacing||""===t.cellSpacing?"":parseInt(t.cellSpacing,10);if(""===r||isNaN(r)?(i(e,"border-spacing",""),i(e,"border-collapse","collapse")):r>0?(i(e,"border-spacing",r+"px"),i(e,"border-collapse","separate")):(i(e,"border-spacing","0"),i(e,"border-collapse","collapse")),""!==t.cellPadding&&null!=t.cellPadding){const i=parseInt(t.cellPadding,10);!isNaN(i)&&i>=0&&e.querySelectorAll("th, td").forEach(e=>{e.style.padding=i+"px"})}if(""!==t.borderWidth&&null!=t.borderWidth){const i=parseInt(t.borderWidth,10);if(!isNaN(i)&&i>=0){const t=e=>{const t=e.style.borderStyle||"solid",n=e.style.borderColor||"#ddd";0===i?e.style.border="0":(e.style.borderWidth=i+"px",e.style.borderStyle=t,e.style.borderColor=n)};t(e),e.querySelectorAll("th, td").forEach(t)}}const l=e.querySelector(":scope > caption");if(t.hasCaption){const i=(t.captionText||"").trim()||"Caption";if(l)l.textContent=i;else{const t=this.iframeDoc.createElement("caption");t.textContent=i,e.insertBefore(t,e.firstChild)}}else l&&l.remove();this._setTableAlign(e,t.alignment||"none")}_setTableAlign(e,t){const i=e.closest&&e.closest(".liteeditor-table-wrapper");if(["float","margin-left","margin-right"].forEach(t=>{e.style.removeProperty(t),i&&i.style.removeProperty(t)}),"center"===t){const t=(e.style.width||"").trim();t&&"100%"!==t||(e.style.width=e.offsetWidth+"px",e.style.maxWidth=""),e.style.marginLeft="auto",e.style.marginRight="auto",i&&(i.style.marginLeft="auto",i.style.marginRight="auto")}else"left"===t?(e.style.float="left",e.style.marginRight="12px",i&&(i.style.float="left",i.style.marginRight="12px")):"right"===t&&(e.style.float="right",e.style.marginLeft="12px",i&&(i.style.float="right",i.style.marginLeft="12px"))}_syncWrapperWidth(e,t){if(!e||!t)return;const i=(t.style.width||"").trim();i?e.style.width=i:e.style.removeProperty("width")}_syncWrapperAlignment(e,t){["float","margin-left","margin-right"].forEach(t=>e.style.removeProperty(t));const i=t.getAttribute("style")||"",n=e=>{const t=i.match(new RegExp(`(?:^|;)\\s*${e}\\s*:\\s*([^;]+)`,"i"));return t?t[1].trim().toLowerCase():""},o=n("float"),r=n("margin-left"),l=n("margin-right");"left"===o?(e.style.float="left",e.style.marginRight="12px"):"right"===o?(e.style.float="right",e.style.marginLeft="12px"):"auto"===r&&"auto"===l&&(e.style.marginLeft="auto",e.style.marginRight="auto")}_showTablePropertiesModal(e){if(!e)return;const t=this._readTableProperties(e),i=e=>String(null==e?"":e).replace(/&/g,"&amp;").replace(/"/g,"&quot;").replace(/</g,"&lt;").replace(/>/g,"&gt;"),n=`\n <div class="liteeditor-tabs">\n <button class="liteeditor-tab active" data-tab="general">General</button>\n </div>\n <div class="liteeditor-tab-content active" data-content="general">\n <div style="display: flex; gap: 12px;">\n <div class="liteeditor-form-group" style="flex: 1;">\n <label class="liteeditor-form-label">Width</label>\n <input type="text" class="liteeditor-form-input" id="tprop-width"\n placeholder="auto, 300px, 50%" value="${i(t.width)}">\n </div>\n <div class="liteeditor-form-group" style="flex: 1;">\n <label class="liteeditor-form-label">Height</label>\n <input type="text" class="liteeditor-form-input" id="tprop-height"\n placeholder="auto or 400px" value="${i(t.height)}">\n </div>\n </div>\n <div style="display: flex; gap: 12px;">\n <div class="liteeditor-form-group" style="flex: 1;">\n <label class="liteeditor-form-label">Cell spacing</label>\n <input type="number" class="liteeditor-form-input" id="tprop-spacing"\n min="0" placeholder="0" value="${i(t.cellSpacing)}">\n </div>\n <div class="liteeditor-form-group" style="flex: 1;">\n <label class="liteeditor-form-label">Cell padding</label>\n <input type="number" class="liteeditor-form-input" id="tprop-padding"\n min="0" placeholder="8" value="${i(t.cellPadding)}">\n </div>\n </div>\n <div style="display: flex; gap: 12px;">\n <div class="liteeditor-form-group" style="flex: 1;">\n <label class="liteeditor-form-label">Border width</label>\n <input type="number" class="liteeditor-form-input" id="tprop-border"\n min="0" placeholder="1" value="${i(t.borderWidth)}">\n </div>\n <div class="liteeditor-form-group" style="flex: 1;">\n <label class="liteeditor-form-label">Caption</label>\n <label style="display: inline-flex; align-items: center; gap: 8px; margin-top: 8px; font-size: 13px; color: #555;">\n <input type="checkbox" id="tprop-caption-on" ${t.hasCaption?"checked":""}>\n Show caption\n </label>\n </div>\n </div>\n <div class="liteeditor-form-group" id="tprop-caption-row" style="${t.hasCaption?"":"display: none;"}">\n <label class="liteeditor-form-label">Caption text</label>\n <input type="text" class="liteeditor-form-input" id="tprop-caption-text"\n placeholder="Caption" value="${i(t.captionText)}">\n </div>\n <div class="liteeditor-form-group">\n <label class="liteeditor-form-label">Alignment</label>\n <select class="liteeditor-form-input" id="tprop-align">\n ${o=t.alignment,r=[{v:"none",label:"None"},{v:"left",label:"Left"},{v:"center",label:"Center"},{v:"right",label:"Right"}],r.map(e=>`<option value="${e.v}"${e.v===o?" selected":""}>${e.label}</option>`).join("")}\n </select>\n </div>\n </div>\n `;var o,r;const l=this.showModal("Table properties",n,t=>{const i={width:t.querySelector("#tprop-width").value.trim(),height:t.querySelector("#tprop-height").value.trim(),cellSpacing:t.querySelector("#tprop-spacing").value.trim(),cellPadding:t.querySelector("#tprop-padding").value.trim(),borderWidth:t.querySelector("#tprop-border").value.trim(),hasCaption:t.querySelector("#tprop-caption-on").checked,captionText:t.querySelector("#tprop-caption-text").value.trim(),alignment:t.querySelector("#tprop-align").value};return this._applyTableProperties(e,i),this.syncContent(),this.saveState(),this.onContentChanged(),!0}),a=l.querySelector("#tprop-caption-on"),s=l.querySelector("#tprop-caption-row");a.addEventListener("change",()=>{s.style.display=a.checked?"":"none"});const c=l.querySelector('[data-action="confirm"]');c&&(c.textContent="Save")}wrapImage(e){e.classList.add("wrapped");const t=this.iframeDoc.createElement("span");t.className="liteeditor-image-resizer",t.contentEditable="false",t.setAttribute("data-liteeditor-chrome","1"),e.parentNode.insertBefore(t,e),t.appendChild(e);["nw","ne","sw","se","n","s","e","w"].forEach(i=>{const n=this.iframeDoc.createElement("span");n.className=`liteeditor-resize-handle ${i}`,n.dataset.position=i,n.setAttribute("data-liteeditor-chrome","1"),t.appendChild(n),n.addEventListener("mousedown",n=>{n.preventDefault(),n.stopPropagation(),this.startResize(n,t,e,i)})});const i=this.iframeDoc.createElement("span");i.className="liteeditor-image-info",i.setAttribute("data-liteeditor-chrome","1"),t.appendChild(i),this.updateImageInfo(t,e),this._buildImageToolbar(t,e),this.syncContent()}selectImage(e){this.deselectImage();const t=e.closest(".liteeditor-image-resizer");t&&t.classList.add("selected")}deselectImage(){this.contentArea.querySelectorAll(".liteeditor-image-resizer.selected").forEach(e=>e.classList.remove("selected"))}startResize(e,i,n,o){const r=e.clientX,l=e.clientY,a=n.offsetWidth,s=n.offsetHeight,c=a/s,d=e=>{e.preventDefault();let t=a,d=s;const h=e.clientX-r,p=e.clientY-l;switch(o){case"se":case"ne":case"e":t=Math.max(50,a+h),d=t/c;break;case"sw":case"nw":case"w":t=Math.max(50,a-h),d=t/c;break;case"s":d=Math.max(50,s+p),t=d*c;break;case"n":d=Math.max(50,s-p),t=d*c}n.style.width=t+"px",n.style.height="auto",n.style.maxWidth="100%",n.removeAttribute("width"),n.removeAttribute("height"),this.updateImageInfo(i,n)},h=()=>{this.iframeDoc.removeEventListener("mousemove",d),this.iframeDoc.removeEventListener("mouseup",p),t.removeEventListener("mousemove",d),t.removeEventListener("mouseup",p),this._activeResize===h&&(this._activeResize=null)},p=()=>{h(),this.syncContent(),this.saveState(),this.onContentChanged()};this._activeResize=h,this.iframeDoc.addEventListener("mousemove",d),this.iframeDoc.addEventListener("mouseup",p),t.addEventListener("mousemove",d),t.addEventListener("mouseup",p)}updateImageInfo(e,t){const i=e.querySelector(".liteeditor-image-info");if(i){const e=t.offsetWidth||t.naturalWidth,n=t.offsetHeight||t.naturalHeight;i.textContent=`${Math.round(e)} × ${Math.round(n)}`}}wrapRangeInMark(e){const t=this.iframeDoc,i="g"+(++this._searchGroupCounter||(this._searchGroupCounter=1));let n=e.startContainer,o=e.startOffset,r=e.endContainer,l=e.endOffset;if(n===r&&n.nodeType===Node.TEXT_NODE){n.splitText(l);const e=n.splitText(o),r=t.createElement("mark");return r.className="liteeditor-search-highlight",r.dataset.group=i,r.textContent=e.nodeValue,void e.parentNode.replaceChild(r,e)}const a=e.commonAncestorContainer,s=t.createTreeWalker(a.nodeType===Node.TEXT_NODE?a.parentNode:a,NodeFilter.SHOW_TEXT,null),c=[];for(;s.nextNode();){const t=s.currentNode;e.intersectsNode(t)&&c.push(t)}c.forEach(e=>{let a=0,s=e.nodeValue.length;if(e===n&&(a=o),e===r&&(s=l),a>=s)return;let c=e;s<e.nodeValue.length&&c.splitText(s),a>0&&(c=c.splitText(a));const d=t.createElement("mark");d.className="liteeditor-search-highlight",d.dataset.group=i,d.textContent=c.nodeValue,c.parentNode.replaceChild(d,c)})}groupMarks(e){const t=new Map;return e.forEach(e=>{const i=e.dataset.group||e;t.has(i)||t.set(i,[]),t.get(i).push(e)}),Array.from(t.values())}sanitizeHTML(e){const i=t.createElement("div");i.innerHTML=e,n.stripChromeIn(i),n.normalizePasted(i,this._pasteOpts),n.applyDefaultStyles(i,this._defaultStyles);["script","iframe","object","embed","applet","svg","math","form","base","meta","link","style","template","noscript","title"].forEach(e=>{i.querySelectorAll(e).forEach(e=>e.remove())});const o=["href","src","action","poster","xlink:href","background","data","ping","formaction"];return i.querySelectorAll("*").forEach(e=>{Array.from(e.attributes).forEach(t=>{const i=t.name.toLowerCase();if(i.startsWith("on")||"srcdoc"===i)e.removeAttribute(t.name);else if(o.includes(i)){const o="IMG"===e.tagName&&"src"===i,r=n.sanitizeUrl(t.value,{allowDataImage:o});r?r!==t.value&&e.setAttribute(t.name,r):e.removeAttribute(t.name)}})}),i.innerHTML}getActiveFormats(){const e={bold:!1,italic:!1,underline:!1,strikethrough:!1,block:null},t=this.iframe&&this.iframe.contentWindow;if(!t)return e;const i=t.getSelection();if(!i||0===i.rangeCount)return e;let n=i.anchorNode;n&&3===n.nodeType&&(n=n.parentNode);const o={p:"p",h1:"h1",h2:"h2",h3:"h3",h4:"h4",h5:"h5",h6:"h6",blockquote:"blockquote",pre:"pre"};for(;n&&n!==this.contentArea;){if(1===n.nodeType){const i=n.tagName.toLowerCase();"strong"!==i&&"b"!==i||(e.bold=!0),"em"!==i&&"i"!==i||(e.italic=!0),"u"===i&&(e.underline=!0),"s"!==i&&"strike"!==i&&"del"!==i||(e.strikethrough=!0),!e.block&&o[i]&&(e.block=o[i]);try{const i=t.getComputedStyle(n);if(i){if(!e.bold){const t=parseInt(i.fontWeight,10);!isNaN(t)&&t>=700?e.bold=!0:"bold"!==i.fontWeight&&"bolder"!==i.fontWeight||(e.bold=!0)}e.italic||"italic"!==i.fontStyle||(e.italic=!0);const t=i.textDecorationLine||i.textDecoration||"";!e.underline&&t.indexOf("underline")>=0&&(e.underline=!0),!e.strikethrough&&t.indexOf("line-through")>=0&&(e.strikethrough=!0)}}catch(e){}}n=n.parentNode}try{e.bold||(e.bold=this.iframeDoc.queryCommandState("bold")),e.italic||(e.italic=this.iframeDoc.queryCommandState("italic")),e.underline||(e.underline=this.iframeDoc.queryCommandState("underline")),e.strikethrough||(e.strikethrough=this.iframeDoc.queryCommandState("strikeThrough"))}catch(e){}return e}updateToolbarState(){const e=this.getActiveFormats();if(this.toolbar.querySelectorAll(".liteeditor-btn").forEach(t=>{const i=t.dataset.command;if("bold"===i)t.classList.toggle("active",e.bold);else if("italic"===i)t.classList.toggle("active",e.italic);else if("underline"===i)t.classList.toggle("active",e.underline);else if("strikethrough"===i)t.classList.toggle("active",e.strikethrough);else if("numlist"===i||"bullist"===i){const e="numlist"===i?"insertOrderedList":"insertUnorderedList";t.classList.toggle("active",this.iframeDoc.queryCommandState(e))}}),e.block){const t={p:"Paragraph",h1:"Heading 1",h2:"Heading 2",h3:"Heading 3",h4:"Heading 4",h5:"Heading 5",h6:"Heading 6",blockquote:"Quote",pre:"Preformatted"},i=this.toolbar.querySelector('[data-command="blocks"] .liteeditor-btn-label');i&&t[e.block]&&(i.textContent=t[e.block])}}saveState(){const e=this.contentArea.innerHTML;this.history.stack[this.history.currentIndex]!==e&&(this.history.stack=this.history.stack.slice(0,this.history.currentIndex+1),this.history.stack.push(e),this.history.currentIndex++,this.history.stack.length>this.history.maxSize&&(this.history.stack.shift(),this.history.currentIndex--))}_scheduleSaveState(){this._saveStateTimer&&clearTimeout(this._saveStateTimer),this._saveStateTimer=setTimeout(()=>{this._saveStateTimer=null,this.saveState()},400)}_flushSaveState(){this._saveStateTimer&&(clearTimeout(this._saveStateTimer),this._saveStateTimer=null,this.saveState())}undo(){this._flushSaveState(),this.history.currentIndex>0&&(this.history.currentIndex--,this.contentArea.innerHTML=this.history.stack[this.history.currentIndex],this.rebindImageHandles(),this.syncContent(),this.onContentChanged())}redo(){this._flushSaveState(),this.history.currentIndex<this.history.stack.length-1&&(this.history.currentIndex++,this.contentArea.innerHTML=this.history.stack[this.history.currentIndex],this.rebindImageHandles(),this.syncContent(),this.onContentChanged())}rebindImageHandles(){this.contentArea.querySelectorAll('.liteeditor-image-resizer, [data-liteeditor-chrome="1"].liteeditor-image-resizer').forEach(e=>{const t=e.querySelector("img");t?(t.classList.remove("wrapped"),e.parentNode.replaceChild(t,e)):e.remove()});this.contentArea.querySelectorAll(".liteeditor-table-wrapper").forEach(e=>{const t=e.querySelector(":scope > table");t?e.parentNode.replaceChild(t,e):e.remove()}),this.contentArea.querySelectorAll('.liteeditor-resize-handle, .liteeditor-image-info, [data-liteeditor-chrome="1"]').forEach(e=>e.remove())}onContentChanged(){this._contentListeners&&this._contentListeners.forEach(e=>{try{e()}catch(e){}})}addContentListener(e){this._contentListeners||(this._contentListeners=[]),this._contentListeners.push(e)}syncContent(){this.element.value=this.getCleanHTML(this.contentArea);const e=new Event("change",{bubbles:!0});this.element.dispatchEvent(e)}restoreContent(){this.contentArea.innerHTML=this.sanitizeHTML(this.content),n.stripChromeIn(this.contentArea),n.normalizePasted(this.contentArea,this._pasteOpts),n.applyDefaultStyles(this.contentArea,this._defaultStyles)}applyLicenseState(i){if(!i||i.valid||this._licenseInvalid)return;this._licenseInvalid=!0;try{this.contentArea&&this.contentArea.setAttribute("contenteditable","false")}catch(e){}if(this.toolbar&&(this.toolbar.style.pointerEvents="none",this.toolbar.style.opacity="0.5"),!this.editorContainer||this._licenseNotice)return;const n=this.config&&this.config.portalUrl||"https://app.liteeditor.com",o={domain_not_allowed:{level:"warning",text:'The domain "'+(e.location&&e.location.hostname||"this domain")+'" is not registered for this LiteEditor API key.',label:"Register this domain",href:n+"/dashboard"},invalid_key:{level:"error",text:"This LiteEditor API key could not be validated.",label:"Get a free API key",href:n+"/register"},missing_key:{level:"warning",text:"No LiteEditor API key was found. Add your key to the editor script.",label:"View setup docs",href:"https://liteeditor.com/docs#installation"},inactive_subscription:{level:"error",text:"This LiteEditor API key's plan is inactive.",label:"Manage billing",href:n+"/dashboard"}},r=o[i.reason||"invalid_key"]||o.invalid_key,l=t.createElement("div");l.className="liteeditor-license-notice liteeditor-license-notice--"+r.level,l.setAttribute("data-liteeditor-chrome","1"),l.setAttribute("role","alert"),l.style.cssText='display:flex;align-items:center;gap:8px;padding:10px 14px;font:13px/1.45 -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;'+("error"===r.level?"background:#fef2f2;color:#991b1b;border-bottom:1px solid #fecaca;":"background:#fffbeb;color:#92400e;border-bottom:1px solid #fde68a;");const a=t.createElement("span");a.textContent="⚠",a.style.cssText="font-size:15px;line-height:1;",l.appendChild(a);const s=t.createElement("span");s.textContent=r.text,s.style.flex="1",l.appendChild(s);const c=t.createElement("a");c.href=r.href,c.target="_blank",c.rel="noopener noreferrer",c.textContent=r.label+" →",c.style.cssText="font-weight:600;color:inherit;text-decoration:underline;white-space:nowrap;",l.appendChild(c),this.toolbar&&this.toolbar.parentNode===this.editorContainer?this.toolbar.insertAdjacentElement("afterend",l):this.editorContainer.insertBefore(l,this.editorContainer.firstChild),this._licenseNotice=l}getContent(){return this.sanitizeHTML(this.getCleanHTML(this.contentArea))}getCleanHTML(e){const t=e.cloneNode(!0);return n.stripChromeIn(t),t.querySelectorAll("mark.liteeditor-search-highlight").forEach(t=>{const i=e.ownerDocument.createTextNode(t.textContent);t.parentNode.replaceChild(i,t)}),n.normalizePasted(t,this._pasteOpts),n.applyDefaultStyles(t,this._defaultStyles),t.innerHTML}setContent(e){this.contentArea.innerHTML=this.sanitizeHTML(e),this.syncContent(),this.saveState(),this.onContentChanged()}toggleSourceCode(){if(this.sourceCodeMode){this.sourceCodeMode=!1;const e=this.sourceTextarea?this.sourceTextarea.value:"";this.contentArea.innerHTML=this.sanitizeHTML(e),this.contentArea.contentEditable="true",this.sourceTextarea=null;const t=this.toolbar.querySelector('[data-command="sourcecode"]');t&&t.classList.remove("active"),this.syncContent(),this.saveState(),this.onContentChanged()}else{this.sourceCodeMode=!0;const e=this.getCleanHTML(this.contentArea);this.contentArea.contentEditable="false",this.contentArea.innerHTML="";const t=this.iframeDoc.createElement("textarea");t.className="liteeditor-source-code",t.value=this.formatHTML(e),t.style.cssText=`\n width: 100%;\n height: 100%;\n min-height: ${this.config.height||150}px;\n padding: 12px;\n font-family: 'Courier New', Consolas, Monaco, monospace;\n font-size: 13px;\n line-height: 1.6;\n border: none;\n outline: none;\n resize: none;\n background: #f8f9fa;\n color: #333;\n tab-size: 4;\n box-sizing: border-box;\n `,this.contentArea.appendChild(t),this.sourceTextarea=t,t.focus();const i=this.toolbar.querySelector('[data-command="sourcecode"]');i&&i.classList.add("active")}}formatHTML(e){let t=e,i=0;t=t.replace(/(<\/(div|p|h[1-6]|ul|ol|li|table|tr|td|th|blockquote|pre)>)/gi,"$1\n"),t=t.replace(/(<(div|p|h[1-6]|ul|ol|li|table|tr|td|th|blockquote|pre)[^>]*>)/gi,"\n$1"),t=t.replace(/<br\s*\/?>/gi,"<br>\n");const n=t.split("\n"),o=[];return n.forEach(e=>{(e=e.trim())&&(e.match(/^<\/(div|p|h[1-6]|ul|ol|li|table|tr|td|th|blockquote|pre)/i)&&(i=Math.max(0,i-1)),o.push(" ".repeat(i)+e),e.match(/<(div|p|h[1-6]|ul|ol|li|table|tr|td|th|blockquote|pre)[^>]*>$/i)&&!e.match(/<(div|p|h[1-6]|ul|ol|li|table|tr|td|th|blockquote|pre)[^>]*>.*<\/\1>/i)&&i++)}),o.join("\n")}destroy(){if(!this._destroyed){if(this._destroyed=!0,this._saveStateTimer&&(clearTimeout(this._saveStateTimer),this._saveStateTimer=null),this._closeDropdowns&&t.removeEventListener("click",this._closeDropdowns),this._onResizeMove&&t.removeEventListener("mousemove",this._onResizeMove),this._onResizeUp&&t.removeEventListener("mouseup",this._onResizeUp),this._imageObserver&&(this._imageObserver.disconnect(),this._imageObserver=null),this._onFormSubmit&&this.element&&this.element.form&&(this.element.form.removeEventListener("submit",this._onFormSubmit,!0),this._onFormSubmit=null),this._onToolbarMouseDown&&this.toolbar&&(this.toolbar.removeEventListener("mousedown",this._onToolbarMouseDown),this._onToolbarMouseDown=null),this._onSelectionChange&&this.iframeDoc&&(this.iframeDoc.removeEventListener("selectionchange",this._onSelectionChange),this._onSelectionChange=null),this._openPickers&&(Array.from(this._openPickers).forEach(e=>{try{e()}catch(e){}}),this._openPickers.clear()),this._activeResize){try{this._activeResize()}catch(e){}this._activeResize=null}if(this._activeReaders&&(this._activeReaders.forEach(e=>{try{e.abort()}catch(e){}}),this._activeReaders.clear()),this._closeSearchPanel){try{this._closeSearchPanel()}catch(e){}this._closeSearchPanel=null}this.searchPanel&&(this.searchPanel.remove(),this.searchPanel=null),this.editorContainer.remove(),this.element.style.display="",delete this.element.dataset.liteeditorId}}}const r=["#000000","#434343","#666666","#999999","#b7b7b7","#cccccc","#d9d9d9","#efefef","#f3f3f3","#ffffff","#980000","#ff0000","#ff9900","#ffff00","#00ff00","#00ffff","#4a86e8","#0000ff","#9900ff","#ff00ff","#e6b8af","#f4cccc","#fce5cd","#fff2cc","#d9ead3","#d0e0e3","#c9daf8","#cfe2f3","#d9d2e9","#ead1dc","#cc4125","#e06666","#f6b26b","#ffd966","#93c47d","#76a5af","#6d9eeb","#6fa8dc","#8e7cc3","#c27ba0"],l={undo:{title:"Undo",icon:"↶",type:"button"},redo:{title:"Redo",icon:"↷",type:"button"},blocks:{title:"Blocks",icon:"¶",type:"dropdown",showValue:!0,defaultLabel:"Paragraph",options:[{label:"Paragraph",value:"p",action:e=>{e.execCommand("formatBlock","p");const t=e.toolbar.querySelector('[data-command="blocks"] .liteeditor-btn-label');t&&(t.textContent="Paragraph")}},{label:"Heading 1",value:"h1",action:e=>{e.execCommand("formatBlock","h1");const t=e.toolbar.querySelector('[data-command="blocks"] .liteeditor-btn-label');t&&(t.textContent="Heading 1")}},{label:"Heading 2",value:"h2",action:e=>{e.execCommand("formatBlock","h2");const t=e.toolbar.querySelector('[data-command="blocks"] .liteeditor-btn-label');t&&(t.textContent="Heading 2")}},{label:"Heading 3",value:"h3",action:e=>{e.execCommand("formatBlock","h3");const t=e.toolbar.querySelector('[data-command="blocks"] .liteeditor-btn-label');t&&(t.textContent="Heading 3")}},{label:"Heading 4",value:"h4",action:e=>{e.execCommand("formatBlock","h4");const t=e.toolbar.querySelector('[data-command="blocks"] .liteeditor-btn-label');t&&(t.textContent="Heading 4")}},{label:"Heading 5",value:"h5",action:e=>{e.execCommand("formatBlock","h5");const t=e.toolbar.querySelector('[data-command="blocks"] .liteeditor-btn-label');t&&(t.textContent="Heading 5")}},{label:"Heading 6",value:"h6",action:e=>{e.execCommand("formatBlock","h6");const t=e.toolbar.querySelector('[data-command="blocks"] .liteeditor-btn-label');t&&(t.textContent="Heading 6")}},{label:"Preformatted",value:"pre",action:e=>{e.execCommand("formatBlock","pre");const t=e.toolbar.querySelector('[data-command="blocks"] .liteeditor-btn-label');t&&(t.textContent="Preformatted")}},{label:"Quote",value:"blockquote",action:e=>{e.execCommand("formatBlock","blockquote");const t=e.toolbar.querySelector('[data-command="blocks"] .liteeditor-btn-label');t&&(t.textContent="Quote")}}]},fontfamily:{title:"Font Family",icon:"Aa",type:"dropdown",showValue:!0,defaultLabel:"System Font",options:[{label:"System Font",value:""},{label:"Arial",value:"Arial, sans-serif"},{label:"Courier New",value:"Courier New, monospace"},{label:"Georgia",value:"Georgia, serif"},{label:"Times New Roman",value:"Times New Roman, serif"},{label:"Trebuchet MS",value:"Trebuchet MS, sans-serif"},{label:"Verdana",value:"Verdana, sans-serif"}].map(e=>({label:e.label,action:t=>{e.value?t.execCommand("fontName",e.value):t.removeFormatting();const i=t.toolbar.querySelector('[data-command="fontfamily"] .liteeditor-btn-label');i&&(i.textContent=e.label)}}))},fontsize:{title:"Font Size",icon:"A⁺",type:"dropdown",showValue:!0,defaultLabel:"12pt",options:["8pt","10pt","12pt","14pt","16pt","18pt","20pt","24pt","28pt","32pt","36pt","48pt"].map(e=>({label:e,action:t=>{t.setFontSize(e);const i=t.toolbar.querySelector('[data-command="fontsize"] .liteeditor-btn-label');i&&(i.textContent=e)}}))},bold:{title:"Bold",icon:"<strong>B</strong>",type:"button",value:null},italic:{title:"Italic",icon:"<em>I</em>",type:"button",value:null},underline:{title:"Underline",icon:"<u>U</u>",type:"button",value:null},strikethrough:{title:"Strikethrough",icon:"<s>S</s>",type:"button",value:null},link:{title:"Insert Link",icon:"🔗",type:"dialog",action:e=>{e.showLinkModal()}},image:{title:"Insert Image",icon:"🖼",type:"dialog",action:e=>{e.showImageModal()}},media:{title:"Insert Media",icon:"📹",type:"dialog",action:e=>{e.showMediaModal()}},table:{title:"Insert Table",icon:"⊞",type:"dialog",action:e=>{e.showTableModal()}},align:{title:"Align",icon:'<svg width="14" height="14" viewBox="0 0 14 14"><line x1="1" y1="3" x2="13" y2="3" stroke="currentColor" stroke-width="1.5"/><line x1="1" y1="6.5" x2="9" y2="6.5" stroke="currentColor" stroke-width="1.5"/><line x1="1" y1="10" x2="13" y2="10" stroke="currentColor" stroke-width="1.5"/></svg>',type:"dropdown",dropdownOpts:{detectActive:e=>e.detectCurrentAlignment()},options:[{key:"left",label:"Left",icon:'<svg width="14" height="14" viewBox="0 0 14 14"><line x1="1" y1="3" x2="13" y2="3" stroke="currentColor" stroke-width="1.5"/><line x1="1" y1="6.5" x2="9" y2="6.5" stroke="currentColor" stroke-width="1.5"/><line x1="1" y1="10" x2="13" y2="10" stroke="currentColor" stroke-width="1.5"/></svg>',action:e=>e.setAlignment("left")},{key:"center",label:"Center",icon:'<svg width="14" height="14" viewBox="0 0 14 14"><line x1="1" y1="3" x2="13" y2="3" stroke="currentColor" stroke-width="1.5"/><line x1="3" y1="6.5" x2="11" y2="6.5" stroke="currentColor" stroke-width="1.5"/><line x1="1" y1="10" x2="13" y2="10" stroke="currentColor" stroke-width="1.5"/></svg>',action:e=>e.setAlignment("center")},{key:"right",label:"Right",icon:'<svg width="14" height="14" viewBox="0 0 14 14"><line x1="1" y1="3" x2="13" y2="3" stroke="currentColor" stroke-width="1.5"/><line x1="5" y1="6.5" x2="13" y2="6.5" stroke="currentColor" stroke-width="1.5"/><line x1="1" y1="10" x2="13" y2="10" stroke="currentColor" stroke-width="1.5"/></svg>',action:e=>e.setAlignment("right")},{key:"justify",label:"Justify",icon:'<svg width="14" height="14" viewBox="0 0 14 14"><line x1="1" y1="3" x2="13" y2="3" stroke="currentColor" stroke-width="1.5"/><line x1="1" y1="6.5" x2="13" y2="6.5" stroke="currentColor" stroke-width="1.5"/><line x1="1" y1="10" x2="13" y2="10" stroke="currentColor" stroke-width="1.5"/></svg>',action:e=>e.setAlignment("justify")}]},alignleft:{title:"Align Left",icon:'<svg width="14" height="14" viewBox="0 0 14 14"><line x1="1" y1="3" x2="13" y2="3" stroke="currentColor" stroke-width="1.5"/><line x1="1" y1="6.5" x2="9" y2="6.5" stroke="currentColor" stroke-width="1.5"/><line x1="1" y1="10" x2="13" y2="10" stroke="currentColor" stroke-width="1.5"/></svg>',type:"dialog",action:e=>e.setAlignment("left")},aligncenter:{title:"Align Center",icon:'<svg width="14" height="14" viewBox="0 0 14 14"><line x1="1" y1="3" x2="13" y2="3" stroke="currentColor" stroke-width="1.5"/><line x1="3" y1="6.5" x2="11" y2="6.5" stroke="currentColor" stroke-width="1.5"/><line x1="1" y1="10" x2="13" y2="10" stroke="currentColor" stroke-width="1.5"/></svg>',type:"dialog",action:e=>e.setAlignment("center")},alignright:{title:"Align Right",icon:'<svg width="14" height="14" viewBox="0 0 14 14"><line x1="1" y1="3" x2="13" y2="3" stroke="currentColor" stroke-width="1.5"/><line x1="5" y1="6.5" x2="13" y2="6.5" stroke="currentColor" stroke-width="1.5"/><line x1="1" y1="10" x2="13" y2="10" stroke="currentColor" stroke-width="1.5"/></svg>',type:"dialog",action:e=>e.setAlignment("right")},alignjustify:{title:"Justify",icon:'<svg width="14" height="14" viewBox="0 0 14 14"><line x1="1" y1="3" x2="13" y2="3" stroke="currentColor" stroke-width="1.5"/><line x1="1" y1="6.5" x2="13" y2="6.5" stroke="currentColor" stroke-width="1.5"/><line x1="1" y1="10" x2="13" y2="10" stroke="currentColor" stroke-width="1.5"/></svg>',type:"dialog",action:e=>e.setAlignment("justify")},forecolor:{title:"Text Color",icon:'<span style="display:inline-block;border-bottom:3px solid #e53935;padding:0 2px;font-weight:bold;">A</span>',type:"dialog",action:e=>e.showColorPicker("forecolor")},backcolor:{title:"Background Color",icon:'<span style="display:inline-block;background:#fff59d;padding:0 4px;font-weight:bold;border-radius:2px;">A</span>',type:"dialog",action:e=>e.showColorPicker("backcolor")},lineheight:{title:"Line Height",icon:"≣",type:"dialog",action:e=>e.showLineHeightPicker()},numlist:function(){const e=e=>`<ol class="liteeditor-list-card" style="list-style-type:${e}"><li><span></span></li><li><span></span></li><li><span></span></li></ol>`;return{title:"Numbered List",icon:'<svg width="16" height="14" viewBox="0 0 16 14" fill="none"><text x="0" y="4" font-size="4" font-family="Arial,sans-serif" font-weight="600" fill="currentColor">1.</text><line x1="5" y1="3" x2="15" y2="3" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/><text x="0" y="8.5" font-size="4" font-family="Arial,sans-serif" font-weight="600" fill="currentColor">2.</text><line x1="5" y1="7.5" x2="15" y2="7.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/><text x="0" y="13" font-size="4" font-family="Arial,sans-serif" font-weight="600" fill="currentColor">3.</text><line x1="5" y1="12" x2="15" y2="12" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>',type:"dropdown",dropdownOpts:{variant:"grid",detectActive:e=>e.detectCurrentListStyle("ol")},options:[{key:"none",label:"None (remove list)",html:'<div class="liteeditor-list-card liteeditor-list-card-none"><span></span>None</div>',action:e=>e.removeList()},{key:"decimal",label:"Default (1. 2. 3.)",html:e("decimal"),action:e=>e.setListStyle("ol","decimal")},{key:"lower-alpha",label:"Lower alpha (a. b. c.)",html:e("lower-alpha"),action:e=>e.setListStyle("ol","lower-alpha")},{key:"lower-roman",label:"Lower roman (i. ii. iii.)",html:e("lower-roman"),action:e=>e.setListStyle("ol","lower-roman")},{key:"upper-alpha",label:"Upper alpha (A. B. C.)",html:e("upper-alpha"),action:e=>e.setListStyle("ol","upper-alpha")},{key:"upper-roman",label:"Upper roman (I. II. III.)",html:e("upper-roman"),action:e=>e.setListStyle("ol","upper-roman")}]}}(),bullist:function(){const e=e=>`<ul class="liteeditor-list-card" style="list-style-type:${e}"><li><span></span></li><li><span></span></li><li><span></span></li></ul>`;return{title:"Bullet List",icon:'<svg width="16" height="14" viewBox="0 0 16 14" fill="none"><circle cx="2" cy="3" r="1.2" fill="currentColor"/><line x1="6" y1="3" x2="15" y2="3" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/><circle cx="2" cy="7" r="1.2" fill="currentColor"/><line x1="6" y1="7" x2="15" y2="7" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/><circle cx="2" cy="11" r="1.2" fill="currentColor"/><line x1="6" y1="11" x2="15" y2="11" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>',type:"dropdown",dropdownOpts:{variant:"grid",detectActive:e=>e.detectCurrentListStyle("ul")},options:[{key:"none",label:"None (remove list)",html:'<div class="liteeditor-list-card liteeditor-list-card-none"><span></span>None</div>',action:e=>e.removeList()},{key:"default",label:"Default (Nested)",html:'<ul class="liteeditor-list-card liteeditor-list-card-nested" style="list-style-type:disc"><li><span></span><ul style="list-style-type:circle"><li><span></span><ul style="list-style-type:square"><li><span></span></li></ul></li></ul></li></ul>',action:e=>e.setListStyle("ul","default")},{key:"disc",label:"Disc",html:e("disc"),action:e=>e.setListStyle("ul","disc")},{key:"circle",label:"Circle",html:e("circle"),action:e=>e.setListStyle("ul","circle")},{key:"square",label:"Square",html:e("square"),action:e=>e.setListStyle("ul","square")}]}}(),indent:{title:"Indent",icon:"→",type:"button",value:null},outdent:{title:"Outdent",icon:"←",type:"button",value:null},emoticons:{title:"Emoticons",icon:"😀",type:"dropdown",options:["😀","😃","😄","😁","😅","😂","🤣","😊","😇","🙂","😉","😌","😍","🥰","😘","😗","😙","😚","😋","😛","😝","😜","🤪","🤨","🧐","🤓","😎","🤩","🥳","👍","👎","👌","✌️","🤞","🤝","👏","🙌","❤️","💔","💕","💖","💗","💙","💚","💛","🧡","💜","🖤","💯","✨","⭐","🌟","💫","🔥","💥"].map(e=>({label:e,action:t=>t.execCommand("insertHTML",e)}))},charmap:{title:"Special Characters",icon:"Ω",type:"dropdown",options:["©","®","™","€","£","¥","¢","§","¶","°","±","×","÷","≠","≈","≤","≥","µ","π","∞","∑","√","∫","∂","α","β","γ","δ","←","→","↑","↓","↔","⇐","⇒","⇑","⇓","⇔","•","◦","▪","▫","□","■","○","●","△","▲","▽","▼"].map(e=>({label:e,action:t=>t.execCommand("insertHTML",e)}))},removeformat:{title:"Clear Formatting",icon:'<svg width="14" height="14" viewBox="0 0 16 16" fill="none"><path d="M3.5 3h9" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/><path d="M6.5 3l-1.5 9" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/><path d="M9.5 3l-.6 3.6" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/><path d="M10 10.5l3 3M13 10.5l-3 3" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>',type:"button",value:null},sourcecode:{title:"Source Code",icon:"&lt;/&gt;",type:"dialog",action:e=>{e.toggleSourceCode()}},searchreplace:{title:"Search & Replace",icon:"🔍",type:"dialog",action:e=>{e.showSearchReplace()}},codesample:{title:"Code Sample",icon:"{ }",type:"dialog",action:e=>{e.showCodeSampleModal()}},visualblocks:{title:"Visual Blocks",icon:"☐",type:"dialog",action:e=>{e.contentArea.classList.toggle("liteeditor-visualblocks");const t=e.toolbar.querySelector('[data-command="visualblocks"]');t&&t.classList.toggle("active",e.contentArea.classList.contains("liteeditor-visualblocks"))}},anchor:{title:"Insert Anchor",icon:"⚓",type:"dialog",action:e=>{e.showAnchorModal()}}},a={anchor:class{constructor(e){this.editor=e}},autolink:class{constructor(e){this.editor=e,this.init()}init(){this.editor.contentArea.addEventListener("keyup",e=>{" "!==e.key&&"Enter"!==e.key||this.detectLinks(e.key)})}detectLinks(e){const t=this.editor.iframeDoc,i=/https?:\/\/[^\s<>]+?(?=[.,;:!?\)\]'"]*(?:\s|$))/g,n=this.editor.iframe.contentWindow.getSelection();if(!n||0===n.rangeCount)return;const o=n.getRangeAt(0);if(!o.collapsed)return;let r=o.startContainer,l=o.startOffset;if(r.nodeType!==Node.TEXT_NODE){const e=i=>{let n=i.previousSibling;for(;n;){if(n.nodeType===Node.TEXT_NODE&&n.nodeValue.length)return n;if(n.nodeType===Node.ELEMENT_NODE){const e=t.createTreeWalker(n,NodeFilter.SHOW_TEXT,null);let i=null;for(;e.nextNode();)i=e.currentNode;if(i)return i}n=n.previousSibling}return i.parentNode?e(i.parentNode):null},i=e(r);if(!i)return;r=i,l=i.nodeValue.length}if(r.parentNode&&r.parentNode.closest&&r.parentNode.closest("a"))return;const a=r.nodeValue.slice(0,l);i.lastIndex=0;let s,c=null;for(;null!==(s=i.exec(a));)c=s;if(!c)return;const d=c.index,h=c[0],p=d+h.length,u=r.splitText(p),m=r.splitText(d),f=t.createElement("a");if(f.href=h,f.textContent=h,f.target="_blank",f.rel="noopener noreferrer",m.parentNode.replaceChild(f,m)," "===e){const e=t.createRange(),i=Math.min(1,u.nodeValue.length);e.setStart(u,i),e.collapse(!0),n.removeAllRanges(),n.addRange(e)}}},charmap:class{constructor(e){this.editor=e}},codesample:class{constructor(e){this.editor=e}},emoticons:class{constructor(e){this.editor=e}},image:class{constructor(e){this.editor=e}},link:class{constructor(e){this.editor=e}},lists:class{constructor(e){this.editor=e}},media:class{constructor(e){this.editor=e}},searchreplace:class{constructor(e){this.editor=e}},table:class{constructor(e){this.editor=e}},visualblocks:class{constructor(e){this.editor=e,this.init()}init(){const e=this.editor.iframeDoc.createElement("style");e.id="liteeditor-visualblocks-style";const t=["p","h1","h2","h3","h4","h5","h6","div","blockquote","ul","ol","table","pre","section","article","aside","header","footer"],i=t.map(e=>`body.liteeditor-visualblocks ${e}`).join(",\n"),n=t.map(e=>`body.liteeditor-visualblocks ${e}::before`).join(",\n"),o=t.map(e=>`body.liteeditor-visualblocks ${e}::before { content: '${e}'; }`).join("\n");e.textContent=`\n ${i} {\n outline: 1px dashed #bbb;\n outline-offset: 2px;\n position: relative;\n padding-top: 20px !important;\n margin-top: 8px;\n }\n ${n} {\n position: absolute;\n top: 0; left: 0;\n font-size: 10px; font-weight: bold;\n color: #999; background: #f0f0f0;\n padding: 1px 6px; border-radius: 0 0 3px 0;\n text-transform: uppercase;\n font-family: -apple-system, BlinkMacSystemFont, sans-serif;\n line-height: 1.4;\n }\n ${o}\n `,this.editor.iframeDoc.head.appendChild(e)}},wordcount:class{constructor(e){this.editor=e,this.init()}init(){const e=t.createElement("div");e.className="liteeditor-wordcount",this.editor.editorContainer.appendChild(e);const i=()=>this.updateCount(e);this.editor.addContentListener(i),i()}updateCount(e){const t=this.editor.contentArea.textContent||"",i=t.trim().split(/\s+/).filter(e=>e.length>0).length,n=t.length;e.textContent=`Words: ${i} | Characters: ${n}`}}};e.liteeditor=new n}(window,document);