@anywhichway/nerd-editor
Version:
A JavaScript rich text editor based on and with support for custom elements.
1 lines • 25.9 kB
JavaScript
(()=>{"use strict";const e=({tagName:e,attributes:t={},innerHTML:i="",innerText:n=""})=>{const o=document.createElement(e);return Object.entries(t).forEach((([e,t])=>{if(t&&"object"==typeof t){if("style"===e)return void Object.entries(t).forEach((([e,t])=>{o.style[e]=t+""}));try{t=JSON.stringify(t)}catch(e){t=e.message}}o.setAttribute(e,t)})),i?o.innerHTML=i:n&&(o.innerText=n),o},t={a:{popover(){},editor(){}},audio:{popover(){},editor(){}},blockquote:{popover:['<label><input type="radio" name="transform" value="q"> Quote</label>','<label><input type="radio" name="transform" value="blockquote"> Block Quote</label>'].join("")},code:{popover:['<select name="class">',hljs.listLanguages().reduce(((e,t)=>e+`<option value="language-${t}">${t}</option>`),""),"</select>",'<label><input type="radio" name="style.display" value=""> Inline</label>','<label><input type="radio" name="style.display" value="block"> Block</label>'].join(""),editor:['<select name="class">',hljs.listLanguages().reduce(((e,t)=>e+`<option value="language-${t}">${t}</option>`),""),"</select>",'<textarea style="display:block;white-space:nowrap" name="innerText" title="Code" spellcheck="false" placeholder="code, e.g. function() { return 1 + 1 }">','<div name="preview"></div>'].join(""),render(){hljs.highlightElement(this)},autoAttributes:{spellcheck:!1}},details:{popover(){},editor(){}},"data-block":{popover:['<label><input type="radio" name="style.display" value=""> Inline</label>','<label><input type="radio" name="style.display" value="block"> Block</label>'].join(""),editor:['<input type="url" name="attribute.src">'].join("")},img:{popover:['<label><input type="radio" name="style.float" value="left"> Left</label>','<label><input type="radio" name="style.float" value=""> Normal</label>','<label><input type="radio" name="style.float" value="right"> Right</label>'].join(""),editor:['<input type="text" name="attribute.src" title="Current Image Source" placeholder="No current source" readoly disabled>','<input type="file" name="attribute.src" title="Select File" accept="image/*">','<div><label><input type="radio" name="style.float" value="left"> Left</label>','<label><input type="radio" name="style.float" value=""> Normal</label>','<label><input type="radio" name="style.float" value="right"> Right</label></div>','<div name="preview"></div>','<div><input type="text" name="attribute.height" title="Image Height" placeholder="height #% or #px">','<input type="text" name="attribute.width" title="Image Width" placeholder="width #% or #px"></div>','<label><input name="style.scale.%" type="range" title="Image Scale" min="0" max="100" value="100"> Scale</label>'].join("")},"inline-function":{popover:['<label><input type="checkbox" name="attribute.showfunction" value="true">Show Function</label>','<label><input type="radio" name="style.display" value=""> Inline</label>','<label><input type="radio" name="style.display" value="block"> Block</label>'].join(""),editor:['<label><input type="checkbox" name="attribute.showfunction" value="true">Show Function</label>','<input type="text" name="element.expression.innerHTML" title="Expression" placeholder="Expression, e.g. 2 + 2">','<div name="preview"></div>'].join("")},"math-science-formula":{popover(){},editor(){}},"sheet-music":{popover(){},editor(){}},"plotly-chart":{popover(){},editor(){}},ol:{popover(){}},q:{popover:['<label><input type="radio" name="transform" value="q"> Quote</label>','<label><input type="radio" name="transform" value="blockquote"> Block Quote</label>'].join("")},table:{popover(){},editor(){}},ul:{popover(){}},video:{popover(){},editor(){}}},i={formula:{match:/(\\[\[\(][\S\s]+)/s,matchEnd:/(\\[\]\)])/s,template:t=>((t=t.replace("\\[","").replace("\\(","").replace("\\]","").replace("\\)","")).endsWith("\\")&&(t=t.substring(0,t.length-1)),t.startsWith("\\ce")&!t.includes("{")?e({tagName:"span",innerHTML:"Chemical Formula ..."}):e({tagName:"math-science-formula",innerHTML:t})),options(e,t){const i=e.split("{").length,n=e.split("}").length,o=i>n?"}".repeat(i-n):"";t([e=e.replaceAll(/->/g,"→")+o])},content(t){const i=t.startsWith("\\[")?"block":"";(t=t.replace("\\[","").replace("\\(","").replace("\\]","").replace("\\)","")).endsWith("\\")&&(t=t.substring(0,t.length-1));const n=e({tagName:"math-science-formula",attributes:{style:{display:i}},innerHTML:t});return requestAnimationFrame((()=>{n.nextSibling&&0!==n.nextSibling.textContent.length||n.insertAdjacentHTML("afterend"," ")})),n}},mention:{mentions:[],match:/\s(@.*\+?)/s,template(t){if(t.href)return e({tagName:"div",innerHTML:`${t.icon} ${t.name}`});const i=t.gravatar||e({tagName:"gravatar-display",attributes:{username:t.name,style:{display:"none"}},innerHTML:` ${t.name} (Gravatar)`});return t.gravatar||(t.gravatar=i,i.addEventListener("loaded",(()=>{"none"===i.style.display&&(i.style.display="block")})),setTimeout((()=>{if("none"===i.style.display){i.remove();const e=this.mentions.findIndex((e=>e.name===t.name));e>=0&&this.mentions.splice(e,1)}}),2e3)),i},options(e,t){if("@"===e)return void t([]);let i;(e=e.substring(1)).endsWith("+")&&(e=e.substring(0,e.length-1),i=!0),this.mentions.forEach((e=>{e.profile=i})),this.mentions.find((t=>t.name===e))||this.mentions.unshift({name:e,profile:i}),t([{name:e,href:`https://www.facebook.com/${e}`,icon:'<i class="fa-brands fa-facebook"></i>'},{name:e,href:`https://www.github.com/${e}`,icon:'<i class="fa-brands fa-github">'},{name:e,href:`https://www.instagram.com/${e}`,icon:'<i class="fa-brands fa-instagram">'},{name:e,href:`https://www.linkedin.com/in/${e}`,icon:'<i class="fa-brands fa-linkedin"></i>'},{name:e,href:`https://www.twitter.com/${e}`,icon:'<i class="fa-brands fa-twitter"></i>'},...this.mentions.filter((t=>e.startsWith(t.name)))])},content(t){if(t.href)return e({tagName:"a",attributes:{href:t.href,target:"_tab"},innerHTML:`${t.icon} ${t.name}`});const i=t.gravatar.cloneNode(!0);return t.profile?(i.setAttribute("showprofile","true"),i.innerHTML='<div style="float:right">${name.formatted}<br>\n${displayName}</div>'):(i.setAttribute("showprofile","false"),i.innerHTML=`<div style="float:right;"> ${t.name}</div>`),i.style.display="inline-block",i.render(),requestAnimationFrame((()=>{i.nextSibling&&0!==i.nextSibling.textContent.length||i.insertAdjacentHTML("afterend"," ")})),i}}},n=e({tagName:"cursor",attributes:{contenteditable:!1,display:"none"}}),o=e({tagName:"popper",attributes:{style:{position:"absolute",display:"none",zIndex:100,backgroundColor:"whitesmoke"}}});document.body.appendChild(o);const l=e=>{o.style.display="none";const t=window.getSelection(),{anchorNode:l,anchorOffset:a,focusNode:r,focusOffset:s}=t,c=t.anchorNode;if(c.nodeType===Node.TEXT_NODE){const d=c.textContent.substring(0,t.anchorOffset);Object.entries(i).some((([i,c])=>{const{match:u,matchEnd:p=/.+\s/s,options:h,template:f,content:m}=((e,t,i)=>{const n=Object.assign({},e);t||=n;for(const e in n){const i=n[e];"function"==typeof i&&(n[e]=i.bind(t))}return n})(c),b=(d.match(u)||[])[1],g=!!b&&b.match(p);if(b){if(g)t.setBaseAndExtent(l,s-b.length,r,a),e.replaceSelection(m(b));else{const i=i=>{const c=document.createElement("div");(i=i.map((i=>{const n=f(i);return n.onclick=()=>{o.style.display="none",t.setBaseAndExtent(l,s-b.length,r,a),e.replaceSelection(m(i))},n}))).forEach((e=>c.appendChild(e))),((e,t,{position:i={},offset:n={}}={})=>{const l=e.getBoundingClientRect(),a=l[i.vertical||"bottom"],r=l[i.horizontal||"right"];o.innerHTML="",o.appendChild(t),o.style.top=`calc(${a}px + ${n.vertical||"0px"})`,o.style.left=`calc(${r}px + ${n.horizontal||"0px"})`,o.style.display=""})(n,c,{position:{horizontal:"left"},offset:{horizontal:-(b.length-2)+"ch"}}),t.setBaseAndExtent(l,a,r,s)};t.getRangeAt(0).surroundContents(n),h(b,i)}return!0}}))}},a={file:{type:"select",innerHTML:["<option disabled selected default hidden>File</option>",'<option value=open">Open</option>','<option value="preview">Preview</option>','<option value="save">Save</option>'].join(""),title:"File options",onclick({path:e}){const t=e[0],i=this.editor[t.value],n=()=>{t.style.height="",t.removeEventListener("blur",n),t.value="File"};t.style.height="0px",t.addEventListener("blur",n),"function"==typeof i&&(i.call(this.editor),n())}},edit:{type:"select",innerHTML:["<option disabled selected default hidden>Edit</option>",'<option value="undo">Undo</option>','<option value="redo">Redo</option>','<option value="find">Find</option>','<option value="replace">Replace</option>'].join(""),title:"Edit options",onclick({path:e}){const t=e[0],i=this.editor[t.value],n=()=>{t.style.height="",t.removeEventListener("blur",n),t.value="Edit"};t.style.height="0px",t.addEventListener("blur",n),"function"==typeof i&&(i.call(this.editor),n())}},heading:{type:"select",innerHTML:["<option disabled selected default hidden>Heading</option>","<option>H1</option>","<option>H2</option>","<option>H3</option>","<option>H4</option>","<option>H5</option>","<option>H6</option>"].join(""),title:"Format Heading",onclick({path:e}){const t=e[0],i=parseInt(t.value[1]),n=()=>{t.style.height="",t.removeEventListener("blur",n),t.value="Heading"};t.style.height="0px",t.addEventListener("blur",n),isNaN(i)||(this.editor.wrapSelection(t.value),n())}},i:{innerHTML:"<i>I</i>",title:"Italic",onclick(){this.editor.wrapSelection("i")}},b:{innerHTML:"<b>B</b>",title:"Bold",onclick(){this.editor.wrapSelection("b")}},u:{innerHTML:"<u>U</u>",title:"Underline",onclick(){this.editor.wrapSelection("u")}},del:{innerHTML:"<del>Del</del>",title:"Deleted",onclick(){this.editor.wrapSelection("del")}},ins:{innerHTML:"<ins>Ins</ins>",title:"Inserted",css:"ins { text-decoration-line: underline; text-decoration-style: wavy; }",onclick(){this.editor.wrapSelection("ins")}},kbd:{innerHTML:"<kbd>Key</kbd>",icon:'<i class="fa-light fa-keyboard"></i>',title:"Keyboard Key",onclick(){this.editor.wrapSelection("kbd")}},aside:{innerHTML:"Aside",icon:'<i class="fa-light fa-sidebar-flip"></i>',title:"Aside",onclick(){this.editor.wrapSelection("aside")}},details:{innerHTML:"Details",icon:'Details <i class="fa-solid fa-caret-down"></i>',title:"Details",onclick(){this.editor.wrapSelection("details");const{anchorNode:e}=window.getSelection(),t=document.createElement("summary"),i=e.firstChild.textContent.substring(0,15)+" ...";t.innerHTML=i,e.insertBefore(t,e.firstChild)}},q:{innerHTML:"<q>Quote</q>",icon:'<i class="fa-solid fa-quotes"></i>',title:"Quote",onclick(){this.editor.wrapSelection("q")}},abbr:{innerHTML:"<abbr>Abrv</abbr>",title:"Abbreviation",css:"abbr { font-style: italic; font-weight: 100;}",onclick(){this.editor.wrapSelection("abbr")}},samp:{innerHTML:"<samp>Sample</samp",title:"Sample",icon:'<i class="fa-solid fa-laptop-code"></i>',onclick(){this.editor.wrapSelection("samp")}},blockquote:{innerHTML:"<blockquote>Quote</blockquote>",icon:'<i class="fa-regular fa-block-quote"></i>',title:"Block Quote",onclick(){this.editor.wrapSelection("blockquote")}},code:{innerHTML:"</>",title:"Code",onclick(){this.editor.wrapSelection("code")}},sup:{innerHTML:'<span style="font-size:80%">x<sup>y</sup></span>',title:"Superscript",onclick(){this.editor.wrapSelection("sup")}},sub:{innerHTML:'<span style="font-size:80%;vertical-align:top;">x<sub>y</sub></span>',title:"Subscript",onclick(){this.editor.wrapSelection("sub")}},var:{innerHTML:"<var>Var</var>",title:"Variable",onclick(){this.editor.wrapSelection("var")}},function:{innerHTML:"<i>f(x)</i>",title:"Inline Function",onclick(){const e=document.createElement("inline-function"),t=document.createElement("expression");t.innerHTML=window.getSelection().toString(),e.innerHTML='\n <script src="https://cdn.jsdelivr.net/npm/mathjs@11.1.0/lib/browser/math.min.js"><\/script>\n <script>\n\n <\/script>',e.children[1].innerHTML='(value) => {\n let result;\n try {\n result = Function("math","with(math) { return " + value + "}")(math);\n } catch(e) {\n try {\n result = math.evaluate(value)\n } catch(e) {\n return e + "";\n }\n }\n if(result && result.toString) {\n return result.toString();\n }\n return result;\n }',e.appendChild(t),this.editor.replaceSelection(e)}},formula:{innerHTML:"Σ",title:"Math/Science Formula",onclick(){this.editor.wrapSelection("math-science-formula")}},datablock:{innerHTML:"Data",title:"Data Block",icon:'<i class="fa-light fa-database"></i>',onclick(){this.editor.wrapSelection("data-block",{asText:!0})}},music:{innerHTML:"Music",title:"Sheet Music (ABC Notation)",icon:'<i class="fa-regular fa-music"></i>',onclick(){this.editor.replaceSelection("sheet-music")}},chart:{innerHTML:"Chart",title:"Chart",icon:'<i class="fa-regular fa-chart-pie"></i>',onclick(){this.editor.wrapSelection("plotly-chart",{asText:!0})}},img:{innerHTML:"Img",title:"Image",icon:'<i class="fa-light fa-image"></i>',onclick(){const e=this.editor.replaceSelection("img");e.setAttribute("src","test"),this.editor.edit(e)}},video:{innerHTML:"Video",title:"Video File",icon:'<i class="fa-light fa-video"></i>',onclick(){const e=this.editor.replaceSelection("video");img.setAttribute("src","test"),this.editor.edit(e)}},audio:{innerHTML:"Audio",title:"Audio File",icon:'<i class="fa-light fa-headphones"></i>',onclick(){const e=this.editor.replaceSelection("audio");img.setAttribute("src","test"),this.editor.edit(e)}},link:{innerHTML:"<a>Link</a>",title:"Link",icon:'<i class="fa-light fa-link-horizontal"></i>',onclick(){const e=this.editor.replaceSelection("a");e.setAttribute("href","test"),this.editor.edit(e)}},table:{innerHTML:"Table",title:"Table",icon:'<i class="fa-light fa-table"></i>',onclick(){const e=this.editor.createElement({tagName:"table",innerHTML:"<tr><td>Test</td></tr>"});this.editor.replaceSelection(e),this.editor.edit(e)}},ul:{innerHTML:"UL",title:"Unordered List",icon:'<i class="fa-light fa-list-ul"></i>',onclick(){this.editor.replaceSelection(this.editor.createElement({tagName:"ul",innerHTML:"<li> </li>"}))}},ol:{innerHTML:"OL",title:"Ordered List",icon:'<i class="fa-light fa-list-ol"></i>',onclick(){this.editor.replaceSelection(this.editor.createElement({tagName:"ol",innerHTML:"<li> </li>"}))}},unformat:{innerHTML:"Unformat",title:"Unformat",icon:'<i class="fa-regular fa-eraser"></i>',onclick(){this.editor.unformatSelection()}},"editor-dialog":{innerHTML:"Edit",title:"Edit element",icon:'<i class="fa-regular fa-pencil"></i>',onclick(){this.editor.editSelection()}},delete:{innerHTML:"Delete",title:"Delete selection",icon:'<i class="fa-regular fa-trash"></i>',onclick(){this.editor.deleteSelection()}},undo:{innerHTML:"Undo",title:"Undo",icon:'<i class="fa-regular fa-rotate-left"></i>',onclick(){this.editor.undo()}},redo:{innerHTML:"Redo",title:"Redo",icon:'<i class="fa-regular fa-rotate-right"></i>',onclick(){this.editor.redo()}},repl:{innerHTML:"</<blink>_</blink>>",title:"REPL",css:"@keyframes condemned_blink_effect { 0% { visibility: hidden; } 50% { visibility: hidden; } 100% { visibility: visible; } } blink { animation: 2s linear infinite condemned_blink_effect; }",onclick(){this.editor.replaceSelection(this.editor.createElement({tagName:"repl-host",attributes:{head:"",css:"",body:"",javascript:"",contenteditable:!1}}))}}},r=e({tagName:"dialog",attributes:{style:{position:"absolute"}},innerHTML:['<div class="ne-dialog-header"></div>','<div class="ne-dialog-content" style="display:inline-block"></div>','<div style="display:inline-block;margin-left:1ch"><ne-control-editor-dialog></ne-control-editor-dialog><ne-control-delete></ne-control-delete></div>','<div class="ne-dialog-footer"></div>'].join("")});r.querySelector("ne-control-delete").addEventListener("click",(()=>r.close())),r.querySelector("ne-control-editor-dialog").addEventListener("click",(()=>r.close()));const s=e({tagName:"dialog",attributes:{style:{position:"absolute"}},innerHTML:['<div class="ne-dialog-header"></div>','<div class="ne-dialog-content"></div>','<div class="ne-dialog-footer" style="display:inline-block">','<div style="display:inline-block;float:right;margin-top:1em"><button name="save">Save</button><button name="cancel">Cancel</button></div>'].join("")});s.querySelector('[name="cancel"]').addEventListener("click",(()=>s.close())),s.querySelector('[name="save"]').addEventListener("click",(()=>s.close("save")));const c=["TABLE","UL","OL","REPL-HOST","BLOCKQUOTE","ASIDE","P","H1","H2","H3","H4","H5","H6","PLOTLY-CHART","SHEET-MUSIC","DATA-BLOCK"],d=e=>{const t=e.history,i=e.querySelector('[slot="content"]');t.back.length&&t.back[t.back.length-1]==i.innerHTML||t.back.push(i.innerHTML)};function u(e){if(!e)return null;if(3==e.nodeType)return e;for(let t of e.childNodes){if(3==t.nodeType)return t;{let e=u(t);if(null!==e)return e}}return null}function p(e,t){[...e.children].some((e=>{e!==t&&e.contains(t)&&e.insertAdjacentElement("afterend",t)}))}self.properties({history:{forward:[],back:[]},createControl({name:e,innerHTML:t,type:i="button",title:n="",...o}){const l=this.shadowRoot.getElementById("ne-control").innerHTML.replaceAll(/button/g,i),a=Function("properties","with(properties) { return `"+l+"`}")({innerHTML:t,title:n});quickComponent({html:a,as:`ne-control-${e}`,properties:{editor:this,...o}})},createElement:e,initialize(){const e=this.querySelector('[slot="content"]'),i=this.querySelector('[slot="footer"]');i.style.display="block",i.style.clear="both",[...this.shadowRoot.querySelectorAll("template[as]")].forEach((e=>{quickComponent({html:e.innerHTML,as:e.getAttribute("as"),properties:{editor:this}})})),Object.entries(a).forEach((([e,t])=>{this.createControl({name:e,...t})})),e.addEventListener("keydown",(e=>{if(13===e.keyCode&&(e.preventDefault(),this.replaceSelection(this.createElement({tagName:"p",innerHTML:"<br>"}))),e.ctrlKey){const t=e.key.toUpperCase();if("Z"!==t&&d(this),"Z"===t)return e.preventDefault(),e.stopImmediatePropagation(),e.shiftKey?void this.redo():void this.undo()}else d(this),this.history.forward=[],l()})),e.addEventListener("keyup",(e=>{l(this)})),e.addEventListener("dblclick",(e=>{const{target:i}=e,n=window.getSelection(),o=n.toString(),{anchorNode:l,anchorOffset:a,focusNode:s,focusOffset:c}=n,d=o.charCodeAt(0),u=o.charCodeAt(o.length-1);if(![32,160].includes(d)&&[32,160].includes(u)&&n.setBaseAndExtent(l,a,s,c-(o.length-o.trim().length)),this.editable(i)){this.currentSelection=i;const e=i.popover||t[i.tagName.toLowerCase()]?.popover;if(e)if("function"==typeof e)e.call(i);else{const n=i.render||t[i.tagName.toLowerCase()]?.render;this.dialog({target:i,sourceNodeOrHTML:e,dialogNode:r,dismissOnChange:!0,render:n})}}else this.currentSelection=null})),e.setAttribute("contenteditable","true"),e.addEventListener("mousemove",(({path:e})=>{e&&this.editable(e[0])})),document.body.appendChild(r),document.body.appendChild(s),this.elementEditorDialog=s,e.addEventListener("click",(e=>{console.log(e);const{target:t}=e;"P"===t.tagName&&(1===t.childNodes.length&&1===t.children.length&&"BR"===t.children[0].tagName&&window.getSelection().setBaseAndExtent(t,0,t,1),e.preventDefault())}))},connected(){},editSelection(){this.currentSelection&&this.edit(this.currentSelection)},edit(e){const i=e.editor||t[e.tagName.toLowerCase()]?.editor,n=e.render||t[e.tagName.toLowerCase()]?.render;i&&("function"==typeof i?i.call(e):this.dialog({target:e,sourceNodeOrHTML:i,dialogNode:this.elementEditorDialog,render:n}))},editable(e){if(!e)return;const i=e.tagName.toLowerCase();return t[i]?.autoAttributes&&Object.entries(t[i]?.autoAttributes).forEach((([t,i])=>{"style"===t&&i&&"object"==typeof i?Object.entries(i).forEach((([t,i])=>e.style[t]=i)):e.setAttribute(t,"string"==typeof i?i:JSON.stringify(i))})),e?.editor||e?.popover||t[i]?.editor||t[i]?.popover?(e.classList.add("ne-editable"),!0):void 0},dialog({target:e,sourceNodeOrHTML:i,dialogNode:n,dismissOnChange:o,render:l}){const a=t=>{[...n.querySelectorAll("[name]")].forEach((i=>{if(!["INPUT","SELECT","TEXTAREA"].includes(i.tagName)||i.hasAttribute("readonly")||i.hasAttribute("disabled"))return;const[n,o,l,a]=i.getAttribute("name").split("."),r="TEXTAREA"===i.tagName?"text":"SELECT"===i.tagName?"select":i.getAttribute("type")||"text";if(!["innerHTML","innerText","slot","class","attribute","style","element","transform"].includes(n))return void console.warn(n+" is an unknown update type");if("radio"===r&&!i.checked)return;let s;if("checkbox"===r)s=i.checked;else if("file"===r){const e=i.files[0];e&&(s=URL.createObjectURL(e))}else s=i.value;if(null!=s)if("transform"===n){const t=[...e.attributes].reduce(((e,{name:t,value:i})=>(e[t]=i,e)),{});e.replaceWith(this.createElement({tagName:s,attributes:t,innerHTML:e.innerHTML}))}else if("innerHTML"===n)t.innerHTML=s;else if("innerText"===n)t.innerText=s;else if("slot"===n)if(o){const e=t.querySelector(`[slot="${o}"]`);e&&(e.innerHTML=s)}else t.innerHTML=s;else"class"===n?t.className=s:"element"===n?[...t.querySelectorAll(o)].forEach((e=>{"innerHTML"===l?e.innerHTML=s:"attribute"===l?e.setAttribute(a,s):"style"===l&&(e.style[a]=s)})):"attribute"===n?(console.log(t,o,s),t.setAttribute(o,s)):"style"===n&&(console.log(t,o,s,l),t.style[o]=s+(l||""))})),l&&l.call(e)},{top:r,left:s}=e.getBoundingClientRect(),c=n.querySelector(".ne-dialog-content"),u=e.editor||t[e.tagName.toLowerCase()]?.editor,p=n.querySelector("ne-control-editor-dialog");"string"==typeof i?c.innerHTML=i:(c.innerHTML="",c.appendChild(i)),p&&(p.style.display=u?"":"none");const h=c.querySelector('[name="preview"]');h&&(h.innerHTML="",h.appendChild(e.cloneNode(!0))),[...n.querySelectorAll("[name]")].forEach((t=>{if(!["INPUT","SELECT","TEXTAREA"].includes(t.tagName))return;const[i,l,r,s]=t.getAttribute("name").split("."),c="TEXTAREA"===t.tagName?"text":"SELECT"===t.tagName?"select":t.getAttribute("type")||"text";if("file"===c)t.setAttribute("placeholder",e.getAttribute(l));else if("transform"===i){const i=e.tagName.toLowerCase();"radio"===c?t.value===i&&(t.checked=!0):t.value=i}else if("innerHTML"===i)t.value=e.innerHTML;else if("innerText"===i)t.value=e.innerText;else if("slot"===i)if(l){const i=e.querySelector(`[slot="${l}"]`);i&&(t.value=i.innerHTML)}else t.value=e.innerHTML;else if("class"===i)t.value=e.classList[0]||"";else if("element"===i)[...e.querySelectorAll(l)].forEach((e=>{"innerHTML"===r?t.value=e.innerHTML:"attribute"===r?t.value=e.getAttribute(s)||"":"style"===r&&(t.value=e.style[s])}));else{if(!["attribute","style"].includes(i))return void console.warn(i+" is an unknown update type");const n="attribute"===i?e.getAttribute(l):r?parseFloat(e.style[l]):e.style[l];"style"===i&&r&&isNaN(n)||("radio"===c?t.value===n&&(t.checked=!0):"checkbox"===c?(""===t.value||t.value===n||"on"===t.value&&"true"===n)&&(t.checked=!0):t.value=n)}o?t.onchange=()=>{n.returnValue=t.getAttribute("name"),n.close()}:h&&(console.log("preview",t),t.onchange=e=>{console.log(e),a(h.firstElementChild)},t.oninput=e=>{console.log(e),a(h.firstElementChild)})})),n.style.top=r+20+"px",n.style.left=s+"px",n.style.margin="0px",n.showModal(),n.onclose=t=>{n.returnValue&&e.isConnected&&(d(this),a(e))}},deleteSelection(){if(d(this),this.currentSelection)return this.currentSelection.remove(),void(this.currentSelection=null);const e=window.getSelection().getRangeAt(0);e&&e.deleteContents()},wrapSelection(e,{asText:t}={}){const i=window.getSelection();if("string"==typeof e&&(e=document.createElement(e)),d(this),this.editable(e),t){const t=(new DOMParser).parseFromString(i.toString(),"text/html");e.innerText=t.body.textContent,this.replaceSelection(e)}else{const t=c.includes(e.tagName)?this.querySelector('[slot="content"]'):null,{firstNode:n,lastNode:o}=function(e,t,{root:i}={}){let n,o,l;e=e.getRangeAt?e.getRangeAt(0):e;for(let a of function(e){let t=[],i=e.startContainer,n=!0;for(;n;){let o=i==e.startContainer?e.startOffset:0,l=i==e.endContainer?e.endOffset:i.textContent.length,a=document.createRange();for(a.setStart(i,o),a.setEnd(i,l),t.push(a),n=!1;!n&&i!=e.endContainer;){let e=u(i.nextSibling);if(e)i=e,n=!0;else if(i.nextSibling)i=i.nextSibling;else{if(!i.parentNode)break;i=i.parentNode}}}return t}(e))n=t.cloneNode(!0),o||=n,l=n,document.body.appendChild(n),a.surroundContents(n),i&&p(i,n);return{firstNode:o,lastNode:l}}(i,e,{root:t});i.setBaseAndExtent(n,0,o,o.childNodes.length),o.nextSibling&&0!==o.nextSibling.textContent.length||o.insertAdjacentHTML("afterend"," ")}return e},replaceSelection(e){const t=window.getSelection(),i=t.getRangeAt(0);return"string"==typeof e&&(e=document.createElement(e)),d(this),this.editable(e),i.deleteContents(),i.insertNode(e),c.includes(e.tagName)?(p(this.querySelector('[slot="content"]'),e),t.setBaseAndExtent(e,0,e,e.childNodes.length)):(t.setBaseAndExtent(e,0,e,e.childNodes.length),e.nextSibling&&0!==e.nextSibling.textContent.length||e.insertAdjacentHTML("afterend"," ")),e},unformatSelection(){const e=window.getSelection(),t=e.getRangeAt(0);if(!t||t.commonAncestorContainer.nodeType===Node.TEXT_NODE)return;const i=(new DOMParser).parseFromString(e.toString(),"text/html").body.innerText;d(this),t.deleteContents();const n=e.anchorNode.childNodes[e.anchorOffset-1];return n.nodeType===Node.ELEMENT_NODE?e.anchorNode.childNodes[e.anchorOffset-1].insertAdjacentText("afterend",i):n.data+=i,e},undo(){const e=this.history,t=this.querySelector('[slot="content"]');e.back.length&&(e.forward.push(t.innerHTML),t.innerHTML=e.back.pop())},redo(){const e=this.history,t=this.querySelector('[slot="content"]');e.forward.length&&(e.back.push(t.innerHTML),t.innerHTML=e.forward.pop())}})})();