markdown-text-editor 1.9.3 → 1.9.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.
@@ -172,9 +172,8 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
172
172
  `),s=0,c=0,l=o.map((e,t)=>e.startsWith(` `)?(t===0&&(s=1),c++,e.substring(1)):e.startsWith(` `)?(t===0&&(s=4),c+=4,e.substring(4)):e).join(`
173
173
  `);this._applyChange(r.substring(0,i)+l+r.substring(a),Math.max(i,t-s),Math.max(i,n-c))}_applyChange(e,t,n){this.textarea.value=e,this.textarea.setSelectionRange(t,n)}},Tr=class{constructor(e){this.editor=e,this.textarea=e.usertextarea,this._keydownHandler=e=>{e.key===`Enter`&&this.handleEnter(e)},this.textarea.addEventListener(`keydown`,this._keydownHandler)}destroy(){this.textarea.removeEventListener(`keydown`,this._keydownHandler)}handleEnter(e){let{selectionStart:t,value:n}=this.textarea,r=n.lastIndexOf(`
174
174
  `,t-1)+1,i=n.substring(r,t),a=i.match(/^(\s*)(\d+)\.\s/),o=i.match(/^(\s*)([\-\*] )\[[\s xX]\] /),s=i.match(/^(\s*)([\-\*] )\s*/);if(i.match(/^(\s*)(\d+\.\s|[\-\*] \[[\s xX]\] |[\-\*]\s)$/)){e.preventDefault();let i=n.substring(0,r),a=n.substring(t);this.textarea.value=i+`
175
- `+a,this.textarea.setSelectionRange(r+1,r+1),this.editor.render(),this.editor.notifyChange();return}let c=null;if(a?c=`${a[1]}${parseInt(a[2])+1}. `:o?c=`${o[1]}${o[2]}[ ] `:s&&(c=`${s[1]}${s[2]}`),c){e.preventDefault();let r=`\n${c}`,i=n.substring(0,t),a=n.substring(t);this.textarea.value=i+r+a;let o=t+r.length;this.textarea.setSelectionRange(o,o),this.editor.render(),this.editor.notifyChange()}}},Er=[{key:`b`,ctrl:!0,shift:!1,ToolClass:kn,label:`Ctrl+B`,btnClass:`bold-btn`},{key:`i`,ctrl:!0,shift:!1,ToolClass:An,label:`Ctrl+I`,btnClass:`italic-btn`},{key:`k`,ctrl:!0,shift:!1,ToolClass:$,label:`Ctrl+K`,btnClass:`link-btn`},{key:"`",ctrl:!0,shift:!1,ToolClass:Wn,label:"Ctrl+`",btnClass:`code-btn`},{key:`s`,ctrl:!0,shift:!0,ToolClass:jn,label:`Ctrl+Shift+S`,btnClass:`strikethrough-btn`},{key:`l`,ctrl:!0,shift:!1,ToolClass:Mn,label:`Ctrl+L`,btnClass:`ul-btn`}];function Dr(e){let t=String(e).split(`+`).map(e=>e.trim().toLowerCase()),n=t.pop();return n?{key:n,ctrl:t.includes(`ctrl`)||t.includes(`cmd`)||t.includes(`meta`),shift:t.includes(`shift`),alt:t.includes(`alt`)}:null}var Or=class{constructor(e){this.editor=e,this.toolShortcuts=(e.toolbarInstance?.tools??[]).filter(e=>e.shortcut).map(e=>({tool:e,combo:Dr(e.shortcut)})).filter(e=>e.combo),this._handler=this._onKeyDown.bind(this),this._docHandler=this._onDocKeyDown.bind(this),e.usertextarea.addEventListener(`keydown`,this._handler),document.addEventListener(`keydown`,this._docHandler),this._updateTooltips()}_onKeyDown(e){let t=e.ctrlKey||e.metaKey,n=e.shiftKey,r=e.key.toLowerCase();if(t&&n&&r===`f`){e.preventDefault(),this.editor.editorContainer.querySelector(`.preview-btn`)?.click();return}if(t&&!n&&[`1`,`2`,`3`].includes(e.key)){e.preventDefault(),new Ln(this.editor).applyHeading(parseInt(e.key));return}for(let{tool:i,combo:a}of this.toolShortcuts)if(r===a.key&&t===a.ctrl&&n===a.shift&&e.altKey===a.alt){e.preventDefault(),i.applySyntax(e);return}for(let i of Er)if(r===i.key&&t===i.ctrl&&n===i.shift){e.preventDefault(),new i.ToolClass(this.editor).applySyntax(e);return}}_onDocKeyDown(e){if(e.key===`F11`){let t=this.editor.editorContainer.contains(document.activeElement),n=this.editor.editorContainer.classList.contains(`is-fullscreen`);(t||n)&&(e.preventDefault(),this.editor.editorContainer.querySelector(`.preview-btn`)?.click())}}_updateTooltips(){for(let{btnClass:e,label:t}of Er){let n=this.editor.editorContainer.querySelector(`.${e}`);n&&(n.title+=` (${t})`)}let e=this.editor.editorContainer.querySelector(`.heading-btn`);e&&(e.title+=` (Ctrl+1/2/3)`);let t=this.editor.editorContainer.querySelector(`.preview-btn`);t&&(t.title+=` (F11)`);for(let{tool:e}of this.toolShortcuts)e.button&&(e.button.title+=` (${e.shortcut})`)}destroy(){this.editor.usertextarea.removeEventListener(`keydown`,this._handler),document.removeEventListener(`keydown`,this._docHandler)}},kr=class{constructor(e){this.editor=e,this._matches=[],this._currentIndex=-1,this._caseSensitive=!1,this._panel=null,this._findInput=null,this._replaceInput=null,this._countEl=null,this._replaceRow=null,this._caseSensitiveBtn=null,this._highlightEl=null,this._scrollHandler=null,this._taHandler=this._onTextareaKeyDown.bind(this),e.usertextarea.addEventListener(`keydown`,this._taHandler)}_onTextareaKeyDown(e){let t=e.ctrlKey||e.metaKey;t&&e.key===`f`?(e.preventDefault(),this.open(!1)):t&&e.key===`h`&&(e.preventDefault(),this.open(!0))}open(e=!1){this._panel||this._buildPanel(),this._panel.hidden=!1,e&&(this._replaceRow.hidden=!1),this._findInput.focus(),this._findInput.select();let t=this.editor.usertextarea.value.substring(this.editor.usertextarea.selectionStart,this.editor.usertextarea.selectionEnd);t&&!t.includes(`
176
- `)&&(this._findInput.value=t),this._scrollHandler||(this._scrollHandler=()=>this._showMatchHighlight(),this.editor.usertextarea.addEventListener(`scroll`,this._scrollHandler)),this._search()}close(){if(!this._panel)return;this._panel.hidden=!0,this._clearMatchHighlight(),this._scrollHandler&&=(this.editor.usertextarea.removeEventListener(`scroll`,this._scrollHandler),null);let e=this.editor.usertextarea;if(this._currentIndex!==-1&&this._matches.length){let{start:t,end:n}=this._matches[this._currentIndex];e.focus(),e.setSelectionRange(t,n)}else e.focus();this._matches=[],this._currentIndex=-1}_buildPanel(){let e=document.createElement(`div`);e.className=`find-replace-panel fj:absolute fj:top-1 fj:right-1 fj:z-20 fj:me-surface fj:me-surface-outline fj:me-surface-rounded fj:p-1.5 fj:flex fj:flex-col fj:gap-1 fj:shadow-lg`,e.setAttribute(`role`,`search`),e.setAttribute(`aria-label`,`Find and replace`);let t=document.createElement(`div`);t.className=`fj:flex fj:items-center fj:gap-1`,this._findInput=document.createElement(`input`),this._findInput.type=`text`,this._findInput.placeholder=`Find`,this._findInput.className=`fj:me-input fj:me-input-xs fj:w-36`,this._findInput.setAttribute(`aria-label`,`Find`),this._findInput.addEventListener(`input`,()=>this._search()),this._findInput.addEventListener(`keydown`,e=>{e.key===`Enter`&&(e.shiftKey?this._prev():this._next()),e.key===`Escape`&&(e.preventDefault(),this.close())}),this._countEl=document.createElement(`span`),this._countEl.className=`fj:text-xs fj:opacity-50 fj:whitespace-nowrap fj:min-w-[3.5rem] fj:text-center fj:select-none`,this._countEl.setAttribute(`aria-live`,`polite`);let n=this._iconBtn(`Previous match`,`<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="m18 15-6-6-6 6"/></svg>`);n.addEventListener(`click`,()=>this._prev());let r=this._iconBtn(`Next match`,`<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6"/></svg>`);r.addEventListener(`click`,()=>this._next()),this._caseSensitiveBtn=document.createElement(`button`),this._caseSensitiveBtn.type=`button`,this._caseSensitiveBtn.className=`fj:me-btn fj:me-btn-xs fj:me-btn-square fj:me-btn-ghost fj:text-xs fj:font-bold`,this._caseSensitiveBtn.textContent=`Aa`,this._caseSensitiveBtn.setAttribute(`aria-label`,`Match case`),this._caseSensitiveBtn.setAttribute(`aria-pressed`,`false`),this._caseSensitiveBtn.title=`Match case`,this._caseSensitiveBtn.addEventListener(`click`,()=>{this._caseSensitive=!this._caseSensitive,this._caseSensitiveBtn.setAttribute(`aria-pressed`,String(this._caseSensitive)),this._caseSensitiveBtn.classList.toggle(`fj:me-btn-active`,this._caseSensitive),this._search()});let i=document.createElement(`button`);i.type=`button`,i.className=`fj:me-btn fj:me-btn-xs fj:me-btn-ghost fj:text-xs fj:px-1.5`,i.textContent=`Replace`,i.setAttribute(`aria-label`,`Toggle replace row`),i.addEventListener(`click`,()=>{this._replaceRow.hidden=!this._replaceRow.hidden,this._replaceRow.hidden||this._replaceInput.focus()});let a=this._iconBtn(`Close`,`<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M18 6 6 18"/><path d="m6 6 12 12"/></svg>`);a.addEventListener(`click`,()=>this.close()),t.append(this._findInput,this._countEl,n,r,this._caseSensitiveBtn,i,a),this._replaceRow=document.createElement(`div`),this._replaceRow.className=`fj:flex fj:items-center fj:gap-1`,this._replaceRow.hidden=!0,this._replaceInput=document.createElement(`input`),this._replaceInput.type=`text`,this._replaceInput.placeholder=`Replace`,this._replaceInput.className=`fj:me-input fj:me-input-xs fj:w-36`,this._replaceInput.setAttribute(`aria-label`,`Replace with`),this._replaceInput.addEventListener(`keydown`,e=>{e.key===`Enter`&&this._replace(),e.key===`Escape`&&(e.preventDefault(),this.close())});let o=document.createElement(`button`);o.type=`button`,o.className=`fj:me-btn fj:me-btn-xs fj:me-btn-ghost fj:text-xs fj:px-1.5`,o.textContent=`Replace`,o.addEventListener(`click`,()=>this._replace());let s=document.createElement(`button`);s.type=`button`,s.className=`fj:me-btn fj:me-btn-xs fj:me-btn-ghost fj:text-xs fj:px-1.5`,s.textContent=`All`,s.setAttribute(`aria-label`,`Replace all`),s.addEventListener(`click`,()=>this._replaceAll()),this._replaceRow.append(this._replaceInput,o,s),e.append(t,this._replaceRow),this.editor.markdownEditorDiv.appendChild(e),this._panel=e}_iconBtn(e,t){let n=document.createElement(`button`);n.type=`button`,n.className=`fj:me-btn fj:me-btn-xs fj:me-btn-square fj:me-btn-ghost`,n.setAttribute(`aria-label`,e),n.innerHTML=t;let r=n.querySelector(`svg`);return r&&r.setAttribute(`aria-hidden`,`true`),n}_search(){let e=this._findInput?.value??``,t=this.editor.usertextarea.value;if(!e){this._matches=[],this._currentIndex=-1,this._clearMatchHighlight(),this._updateCount();return}let n=this._caseSensitive?t:t.toLowerCase(),r=this._caseSensitive?e:e.toLowerCase();this._matches=[];let i=0;for(;i<=n.length-r.length;){let t=n.indexOf(r,i);if(t===-1)break;this._matches.push({start:t,end:t+e.length}),i=t+1}this._currentIndex=this._matches.length>0?Math.min(Math.max(this._currentIndex,0),this._matches.length-1):-1,this._selectCurrent(),this._updateCount()}_next(){this._matches.length!==0&&(this._currentIndex=(this._currentIndex+1)%this._matches.length,this._selectCurrent(),this._updateCount())}_prev(){this._matches.length!==0&&(this._currentIndex=(this._currentIndex-1+this._matches.length)%this._matches.length,this._selectCurrent(),this._updateCount())}_selectCurrent(){if(this._currentIndex===-1||this._matches.length===0){this._clearMatchHighlight();return}let{start:e}=this._matches[this._currentIndex];this._scrollToMatch(this.editor.usertextarea,e),this._showMatchHighlight()}_scrollToMatch(e,t){let n=parseInt(window.getComputedStyle(e).lineHeight)||20,r=e.value.substring(0,t).split(`
177
- `).length-1,i=Math.floor(e.clientHeight/n);e.scrollTop=Math.max(0,(r-Math.floor(i/2))*n)}_showMatchHighlight(){if(this._clearMatchHighlight(),this._currentIndex===-1||!this._matches.length)return;let{start:e,end:t}=this._matches[this._currentIndex],n=this.editor.usertextarea,r=window.getComputedStyle(n),i=n.parentElement,a=document.createElement(`div`);Object.assign(a.style,{position:`absolute`,visibility:`hidden`,pointerEvents:`none`,top:`0`,left:`0`,right:`0`,whiteSpace:`pre-wrap`,wordBreak:`break-word`,overflowWrap:`break-word`,font:r.font,lineHeight:r.lineHeight,paddingTop:r.paddingTop,paddingRight:r.paddingRight,paddingBottom:r.paddingBottom,paddingLeft:r.paddingLeft,boxSizing:`border-box`});let o=document.createElement(`span`);o.textContent=n.value.substring(e,t)||`​`,a.appendChild(document.createTextNode(n.value.substring(0,e))),a.appendChild(o),a.appendChild(document.createTextNode(n.value.substring(t))),i.appendChild(a);try{let e=i.getBoundingClientRect(),t=o.getBoundingClientRect(),r=document.createElement(`div`);Object.assign(r.style,{position:`absolute`,top:t.top-e.top-n.scrollTop+`px`,left:t.left-e.left+`px`,width:Math.max(t.width,2)+`px`,height:t.height+`px`,background:`color-mix(in oklch, var(--color-primary, oklch(0.6 0.2 250)), transparent 55%)`,borderRadius:`2px`,pointerEvents:`none`,zIndex:`2`}),i.appendChild(r),this._highlightEl=r}finally{i.removeChild(a)}}_clearMatchHighlight(){this._highlightEl?.remove(),this._highlightEl=null}_updateCount(){this._countEl&&(this._matches.length===0?this._countEl.textContent=this._findInput?.value?`No results`:``:this._countEl.textContent=`${this._currentIndex+1} of ${this._matches.length}`)}_replace(){if(this._currentIndex===-1)return;let{start:e,end:t}=this._matches[this._currentIndex],n=this.editor.usertextarea,r=this._replaceInput.value;n.value=n.value.substring(0,e)+r+n.value.substring(t),this.editor.render(),this.editor.notifyChange(),this._search()}_replaceAll(){let e=this._findInput?.value;if(!e)return;let t=this._replaceInput.value,n=this.editor.usertextarea,r=e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`),i=this._caseSensitive?`g`:`gi`;n.value=n.value.replace(new RegExp(r,i),t),this.editor.render(),this.editor.notifyChange(),this._currentIndex=0,this._search()}destroy(){this.editor.usertextarea.removeEventListener(`keydown`,this._taHandler),this._scrollHandler&&this.editor.usertextarea.removeEventListener(`scroll`,this._scrollHandler),this._clearMatchHighlight(),this._panel?.remove()}},Ar=/^https?:\/\/\S+$/i,jr=class{constructor(e){this.editor=e,this.textarea=e.usertextarea,this._pasteHandler=e=>this._onPaste(e),this._dropHandler=e=>this._onDrop(e),this._dragOverHandler=e=>{this._carriesFiles(e.dataTransfer)&&e.preventDefault()},this.textarea.addEventListener(`paste`,this._pasteHandler),this.textarea.addEventListener(`drop`,this._dropHandler),this.textarea.addEventListener(`dragover`,this._dragOverHandler)}destroy(){this.textarea.removeEventListener(`paste`,this._pasteHandler),this.textarea.removeEventListener(`drop`,this._dropHandler),this.textarea.removeEventListener(`dragover`,this._dragOverHandler)}_carriesFiles(e){return Array.from(e?.types??[]).includes(`Files`)}_imageFiles(e){return Array.from(e?.files??[]).filter(e=>e.type?.startsWith(`image/`))}_onPaste(e){let t=this._imageFiles(e.clipboardData);if(t.length){if(!this.editor.imageUpload){console.warn(`[MarkdownEditor] An image was pasted but no upload endpoint is configured. Add { image: { fileInput: { uploadUrl: "..." } } } to the toolbar to enable it.`);return}e.preventDefault(),this._uploadAll(t);return}let n=e.clipboardData?.getData(`text/plain`)?.trim(),{selectionStart:r,selectionEnd:i}=this.textarea;if(n&&i>r&&Ar.test(n)){e.preventDefault();let t=`[${this.textarea.value.slice(r,i)}](${n})`;this.editor.insertText(t,t.length,0)}}_onDrop(e){if(!this._carriesFiles(e.dataTransfer))return;e.preventDefault();let t=this._imageFiles(e.dataTransfer);if(t.length){if(!this.editor.imageUpload){console.warn(`[MarkdownEditor] An image was dropped but no upload endpoint is configured. Add { image: { fileInput: { uploadUrl: "..." } } } to the toolbar to enable it.`);return}this._uploadAll(t)}}async _uploadAll(e){for(let t of e){let e=`![${this.editor.label(`Uploading...`)}]()`;this.editor.insertText(e,e.length,0);try{let{path:n,alt:r}=await Rn(t,this.editor.imageUpload);this._replace(e,`![${r}](${n})`)}catch(t){this._replace(e,`![${this.editor.label(`Upload failed`)}]()`),console.error(`[MarkdownEditor] Image upload failed.`,t)}}}_replace(e,t){let n=this.textarea,r=n.value.indexOf(e);if(r===-1)return;n.value=n.value.slice(0,r)+t+n.value.slice(r+e.length);let i=r+t.length;n.setSelectionRange(i,i),this.editor.render(),this.editor.notifyChange()}},Mr=new ot({breaks:!0}),Nr=class{constructor(e,t={}){this.usertextarea=typeof e==`string`?document.querySelector(e):e,this.options=t,this.mode=t.mode||`plain`,this.preview=!this.options.toolbar||this.options.toolbar.includes(`preview`),this.footerOptions=this._parseFooterOptions(t.footer),this.variables=this._parseVariables(t.toolbar),this.imageUpload=this._parseImageUpload(t.toolbar),this.previewTimer=null,this.init(),this.undoRedoManager=new Cr(this),this.listManager=new Tr(this),this.indentManager=new wr(this),this.shortcutManager=new Or(this),this.findReplace=new kr(this),this.pasteManager=new jr(this)}label(e){return this.options.labels?.[e]??e}_parseImageUpload(e){let t=(Array.isArray(e)?e:[]).find(e=>e&&typeof e==`object`&&e.image)?.image?.fileInput;return t?.uploadUrl?t:null}_parseVariables(e){let t=(Array.isArray(e)?e:[]).find(e=>e&&typeof e==`object`&&Array.isArray(e.variables));return t?t.variables:[]}_parseFooterOptions(e){if(e===!1)return null;let t=e??{};return{line:t.line!==!1,col:t.col!==!1,chars:t.chars!==!1,words:t.words===!0}}init(){this.createEditor(),this.addToolbar(),this.addFooter(),this._toolbarH=this.editorContainer.querySelector(`.toolbar`)?.offsetHeight??0,this._footerH=this.editorContainer.querySelector(`.editor-footer`)?.offsetHeight??0,this._autoGrow()}createEditor(){this.isTextareaValid()&&(this.applyDefaultAttributes(),this.buildEditorLayout(),this.addInputListener(),this.render())}isTextareaValid(){return this.usertextarea.tagName===`TEXTAREA`}applyDefaultAttributes(){this.usertextarea.id&&document.querySelector(`label[for="${this.usertextarea.id}"]`)||this.usertextarea.getAttribute(`aria-label`)||this.usertextarea.getAttribute(`aria-labelledby`)||(this.usertextarea.setAttribute(`aria-label`,this.options.label||`Markdown editor`),this._addedAriaLabel=!0),this.usertextarea.classList.add(`editor-textarea`,`fj:focus:ring-0`,`fj:focus:outline-0`,`fj:border-0`,`fj:border-base-soft`,`fj:px-4`,`fj:py-2`,`fj:max-w-full`,`fj:w-full`,`fj:h-full`,`fj:bg-transparent`,`fj:outline-0`,`fj:appearance-none`,`fj:overflow-y-auto`,`fj:resize-none`),this.usertextarea.hasAttribute(`placeholder`)||(this.usertextarea.placeholder=this.options.placeholder||`Write your markdown...`)}buildEditorLayout(){this.editorContainer=document.createElement(`div`),this.editorContainer.className=`
175
+ `+a,this.textarea.setSelectionRange(r+1,r+1),this.editor.render(),this.editor.notifyChange();return}let c=null;if(a?c=`${a[1]}${parseInt(a[2])+1}. `:o?c=`${o[1]}${o[2]}[ ] `:s&&(c=`${s[1]}${s[2]}`),c){e.preventDefault();let r=`\n${c}`,i=n.substring(0,t),a=n.substring(t);this.textarea.value=i+r+a;let o=t+r.length;this.textarea.setSelectionRange(o,o),this.editor.render(),this.editor.notifyChange()}}},Er=[{key:`b`,ctrl:!0,shift:!1,ToolClass:kn,label:`Ctrl+B`,btnClass:`bold-btn`},{key:`i`,ctrl:!0,shift:!1,ToolClass:An,label:`Ctrl+I`,btnClass:`italic-btn`},{key:`k`,ctrl:!0,shift:!1,ToolClass:$,label:`Ctrl+K`,btnClass:`link-btn`},{key:"`",ctrl:!0,shift:!1,ToolClass:Wn,label:"Ctrl+`",btnClass:`code-btn`},{key:`s`,ctrl:!0,shift:!0,ToolClass:jn,label:`Ctrl+Shift+S`,btnClass:`strikethrough-btn`},{key:`l`,ctrl:!0,shift:!1,ToolClass:Mn,label:`Ctrl+L`,btnClass:`ul-btn`}];function Dr(e){let t=String(e).split(`+`).map(e=>e.trim().toLowerCase()),n=t.pop();return n?{key:n,ctrl:t.includes(`ctrl`)||t.includes(`cmd`)||t.includes(`meta`),shift:t.includes(`shift`),alt:t.includes(`alt`)}:null}var Or=class{constructor(e){this.editor=e,this.toolShortcuts=(e.toolbarInstance?.tools??[]).filter(e=>e.shortcut).map(e=>({tool:e,combo:Dr(e.shortcut)})).filter(e=>e.combo),this._handler=this._onKeyDown.bind(this),this._docHandler=this._onDocKeyDown.bind(this),e.usertextarea.addEventListener(`keydown`,this._handler),document.addEventListener(`keydown`,this._docHandler),this._updateTooltips()}_onKeyDown(e){let t=e.ctrlKey||e.metaKey,n=e.shiftKey,r=e.key.toLowerCase();if(t&&n&&r===`f`){e.preventDefault(),this.editor.editorContainer.querySelector(`.preview-btn`)?.click();return}if(t&&!n&&[`1`,`2`,`3`].includes(e.key)){e.preventDefault(),new Ln(this.editor).applyHeading(parseInt(e.key));return}for(let{tool:i,combo:a}of this.toolShortcuts)if(r===a.key&&t===a.ctrl&&n===a.shift&&e.altKey===a.alt){e.preventDefault(),i.applySyntax(e);return}for(let i of Er)if(r===i.key&&t===i.ctrl&&n===i.shift){e.preventDefault(),new i.ToolClass(this.editor).applySyntax(e);return}}_onDocKeyDown(e){if(e.key===`F11`){let t=this.editor.editorContainer.contains(document.activeElement),n=this.editor.editorContainer.classList.contains(`is-fullscreen`);(t||n)&&(e.preventDefault(),this.editor.editorContainer.querySelector(`.preview-btn`)?.click())}}_updateTooltips(){for(let{btnClass:e,label:t}of Er){let n=this.editor.editorContainer.querySelector(`.${e}`);n&&(n.title+=` (${t})`)}let e=this.editor.editorContainer.querySelector(`.heading-btn`);e&&(e.title+=` (Ctrl+1/2/3)`);let t=this.editor.editorContainer.querySelector(`.preview-btn`);t&&(t.title+=` (F11)`);for(let{tool:e}of this.toolShortcuts)e.button&&(e.button.title+=` (${e.shortcut})`)}destroy(){this.editor.usertextarea.removeEventListener(`keydown`,this._handler),document.removeEventListener(`keydown`,this._docHandler)}},kr=class{constructor(e){this.editor=e,this._matches=[],this._currentIndex=-1,this._caseSensitive=!1,this._panel=null,this._findInput=null,this._replaceInput=null,this._countEl=null,this._replaceRow=null,this._caseSensitiveBtn=null,this._highlightEl=null,this._matchTop=null,this._matchHeight=0,this._scrollHandler=null,this._taHandler=this._onTextareaKeyDown.bind(this),e.usertextarea.addEventListener(`keydown`,this._taHandler)}_onTextareaKeyDown(e){let t=e.ctrlKey||e.metaKey;t&&e.key===`f`?(e.preventDefault(),this.open(!1)):t&&e.key===`h`&&(e.preventDefault(),this.open(!0))}open(e=!1){this._panel||this._buildPanel(),this._panel.hidden=!1,e&&(this._replaceRow.hidden=!1),this._findInput.focus(),this._findInput.select();let t=this.editor.usertextarea.value.substring(this.editor.usertextarea.selectionStart,this.editor.usertextarea.selectionEnd);t&&!t.includes(`
176
+ `)&&(this._findInput.value=t),this._scrollHandler||(this._scrollHandler=()=>this._showMatchHighlight(),this.editor.usertextarea.addEventListener(`scroll`,this._scrollHandler)),this._search()}close(){if(!this._panel)return;this._panel.hidden=!0,this._clearMatchHighlight(),this._scrollHandler&&=(this.editor.usertextarea.removeEventListener(`scroll`,this._scrollHandler),null);let e=this.editor.usertextarea;if(this._currentIndex!==-1&&this._matches.length){let{start:t,end:n}=this._matches[this._currentIndex];e.focus(),e.setSelectionRange(t,n)}else e.focus();this._matches=[],this._currentIndex=-1}_buildPanel(){let e=document.createElement(`div`);e.className=`find-replace-panel fj:absolute fj:top-1 fj:right-1 fj:z-20 fj:me-surface fj:me-surface-outline fj:me-surface-rounded fj:p-1.5 fj:flex fj:flex-col fj:gap-1 fj:shadow-lg`,e.setAttribute(`role`,`search`),e.setAttribute(`aria-label`,`Find and replace`);let t=document.createElement(`div`);t.className=`fj:flex fj:items-center fj:gap-1`,this._findInput=document.createElement(`input`),this._findInput.type=`text`,this._findInput.placeholder=`Find`,this._findInput.className=`fj:me-input fj:me-input-xs fj:w-36`,this._findInput.setAttribute(`aria-label`,`Find`),this._findInput.addEventListener(`input`,()=>this._search()),this._findInput.addEventListener(`keydown`,e=>{e.key===`Enter`&&(e.shiftKey?this._prev():this._next()),e.key===`Escape`&&(e.preventDefault(),this.close())}),this._countEl=document.createElement(`span`),this._countEl.className=`fj:text-xs fj:opacity-50 fj:whitespace-nowrap fj:min-w-[3.5rem] fj:text-center fj:select-none`,this._countEl.setAttribute(`aria-live`,`polite`);let n=this._iconBtn(`Previous match`,`<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="m18 15-6-6-6 6"/></svg>`);n.addEventListener(`click`,()=>this._prev());let r=this._iconBtn(`Next match`,`<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6"/></svg>`);r.addEventListener(`click`,()=>this._next()),this._caseSensitiveBtn=document.createElement(`button`),this._caseSensitiveBtn.type=`button`,this._caseSensitiveBtn.className=`fj:me-btn fj:me-btn-xs fj:me-btn-square fj:me-btn-ghost fj:text-xs fj:font-bold`,this._caseSensitiveBtn.textContent=`Aa`,this._caseSensitiveBtn.setAttribute(`aria-label`,`Match case`),this._caseSensitiveBtn.setAttribute(`aria-pressed`,`false`),this._caseSensitiveBtn.title=`Match case`,this._caseSensitiveBtn.addEventListener(`click`,()=>{this._caseSensitive=!this._caseSensitive,this._caseSensitiveBtn.setAttribute(`aria-pressed`,String(this._caseSensitive)),this._caseSensitiveBtn.classList.toggle(`fj:me-btn-active`,this._caseSensitive),this._search()});let i=document.createElement(`button`);i.type=`button`,i.className=`fj:me-btn fj:me-btn-xs fj:me-btn-ghost fj:text-xs fj:px-1.5`,i.textContent=`Replace`,i.setAttribute(`aria-label`,`Toggle replace row`),i.addEventListener(`click`,()=>{this._replaceRow.hidden=!this._replaceRow.hidden,this._replaceRow.hidden||this._replaceInput.focus()});let a=this._iconBtn(`Close`,`<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M18 6 6 18"/><path d="m6 6 12 12"/></svg>`);a.addEventListener(`click`,()=>this.close()),t.append(this._findInput,this._countEl,n,r,this._caseSensitiveBtn,i,a),this._replaceRow=document.createElement(`div`),this._replaceRow.className=`fj:flex fj:items-center fj:gap-1`,this._replaceRow.hidden=!0,this._replaceInput=document.createElement(`input`),this._replaceInput.type=`text`,this._replaceInput.placeholder=`Replace`,this._replaceInput.className=`fj:me-input fj:me-input-xs fj:w-36`,this._replaceInput.setAttribute(`aria-label`,`Replace with`),this._replaceInput.addEventListener(`keydown`,e=>{e.key===`Enter`&&this._replace(),e.key===`Escape`&&(e.preventDefault(),this.close())});let o=document.createElement(`button`);o.type=`button`,o.className=`fj:me-btn fj:me-btn-xs fj:me-btn-ghost fj:text-xs fj:px-1.5`,o.textContent=`Replace`,o.addEventListener(`click`,()=>this._replace());let s=document.createElement(`button`);s.type=`button`,s.className=`fj:me-btn fj:me-btn-xs fj:me-btn-ghost fj:text-xs fj:px-1.5`,s.textContent=`All`,s.setAttribute(`aria-label`,`Replace all`),s.addEventListener(`click`,()=>this._replaceAll()),this._replaceRow.append(this._replaceInput,o,s),e.append(t,this._replaceRow),this.editor.markdownEditorDiv.appendChild(e),this._panel=e}_iconBtn(e,t){let n=document.createElement(`button`);n.type=`button`,n.className=`fj:me-btn fj:me-btn-xs fj:me-btn-square fj:me-btn-ghost`,n.setAttribute(`aria-label`,e),n.innerHTML=t;let r=n.querySelector(`svg`);return r&&r.setAttribute(`aria-hidden`,`true`),n}_search(){let e=this._findInput?.value??``,t=this.editor.usertextarea.value;if(!e){this._matches=[],this._currentIndex=-1,this._clearMatchHighlight(),this._updateCount();return}let n=this._caseSensitive?t:t.toLowerCase(),r=this._caseSensitive?e:e.toLowerCase();this._matches=[];let i=0;for(;i<=n.length-r.length;){let t=n.indexOf(r,i);if(t===-1)break;this._matches.push({start:t,end:t+e.length}),i=t+1}this._currentIndex=this._matches.length>0?Math.min(Math.max(this._currentIndex,0),this._matches.length-1):-1,this._selectCurrent(),this._updateCount()}_next(){this._matches.length!==0&&(this._currentIndex=(this._currentIndex+1)%this._matches.length,this._selectCurrent(),this._updateCount())}_prev(){this._matches.length!==0&&(this._currentIndex=(this._currentIndex-1+this._matches.length)%this._matches.length,this._selectCurrent(),this._updateCount())}_selectCurrent(){if(this._currentIndex===-1||this._matches.length===0){this._clearMatchHighlight();return}this._showMatchHighlight(),this._scrollMatchIntoView()}_scrollMatchIntoView(){let e=this.editor.usertextarea;if(this._matchTop===null||this._matchHeight<=0)return;let t=e.clientHeight,n=e.scrollTop,r=this._matchHeight,i=n;this._matchTop-r<n?i=this._matchTop-r:this._matchTop+this._matchHeight+r>n+t&&(i=this._matchTop+this._matchHeight+r-t),i!==n&&(e.scrollTop=Math.max(0,i),this._highlightEl&&(this._highlightEl.style.top=this._matchTop-e.scrollTop+`px`))}_showMatchHighlight(){if(this._clearMatchHighlight(),this._currentIndex===-1||!this._matches.length)return;let{start:e,end:t}=this._matches[this._currentIndex],n=this.editor.usertextarea,r=window.getComputedStyle(n),i=n.parentElement,a=document.createElement(`div`);Object.assign(a.style,{position:`absolute`,visibility:`hidden`,pointerEvents:`none`,top:`0`,left:`0`,width:n.clientWidth+`px`,whiteSpace:`pre-wrap`,wordBreak:`break-word`,overflowWrap:`break-word`,font:r.font,lineHeight:r.lineHeight,paddingTop:r.paddingTop,paddingRight:r.paddingRight,paddingBottom:r.paddingBottom,paddingLeft:r.paddingLeft,boxSizing:`border-box`});let o=document.createElement(`span`);o.textContent=n.value.substring(e,t)||`​`,a.appendChild(document.createTextNode(n.value.substring(0,e))),a.appendChild(o),a.appendChild(document.createTextNode(n.value.substring(t))),i.appendChild(a);try{let e=i.getBoundingClientRect(),t=o.getBoundingClientRect();this._matchTop=t.top-e.top,this._matchHeight=t.height;let r=document.createElement(`div`);Object.assign(r.style,{position:`absolute`,top:t.top-e.top-n.scrollTop+`px`,left:t.left-e.left+`px`,width:Math.max(t.width,2)+`px`,height:t.height+`px`,background:`color-mix(in oklch, var(--color-primary, oklch(0.6 0.2 250)), transparent 55%)`,borderRadius:`2px`,pointerEvents:`none`,zIndex:`2`}),i.appendChild(r),this._highlightEl=r}finally{i.removeChild(a)}}_clearMatchHighlight(){this._highlightEl?.remove(),this._highlightEl=null,this._matchTop=null}_updateCount(){this._countEl&&(this._matches.length===0?this._countEl.textContent=this._findInput?.value?`No results`:``:this._countEl.textContent=`${this._currentIndex+1} of ${this._matches.length}`)}_replace(){if(this._currentIndex===-1)return;let{start:e,end:t}=this._matches[this._currentIndex],n=this.editor.usertextarea,r=this._replaceInput.value;n.value=n.value.substring(0,e)+r+n.value.substring(t),this.editor.render(),this.editor.notifyChange(),this._search()}_replaceAll(){let e=this._findInput?.value;if(!e)return;let t=this._replaceInput.value,n=this.editor.usertextarea,r=e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`),i=this._caseSensitive?`g`:`gi`;n.value=n.value.replace(new RegExp(r,i),t),this.editor.render(),this.editor.notifyChange(),this._currentIndex=0,this._search()}destroy(){this.editor.usertextarea.removeEventListener(`keydown`,this._taHandler),this._scrollHandler&&this.editor.usertextarea.removeEventListener(`scroll`,this._scrollHandler),this._clearMatchHighlight(),this._panel?.remove()}},Ar=/^https?:\/\/\S+$/i,jr=class{constructor(e){this.editor=e,this.textarea=e.usertextarea,this._pasteHandler=e=>this._onPaste(e),this._dropHandler=e=>this._onDrop(e),this._dragOverHandler=e=>{this._carriesFiles(e.dataTransfer)&&e.preventDefault()},this.textarea.addEventListener(`paste`,this._pasteHandler),this.textarea.addEventListener(`drop`,this._dropHandler),this.textarea.addEventListener(`dragover`,this._dragOverHandler)}destroy(){this.textarea.removeEventListener(`paste`,this._pasteHandler),this.textarea.removeEventListener(`drop`,this._dropHandler),this.textarea.removeEventListener(`dragover`,this._dragOverHandler)}_carriesFiles(e){return Array.from(e?.types??[]).includes(`Files`)}_imageFiles(e){return Array.from(e?.files??[]).filter(e=>e.type?.startsWith(`image/`))}_onPaste(e){let t=this._imageFiles(e.clipboardData);if(t.length){if(!this.editor.imageUpload){console.warn(`[MarkdownEditor] An image was pasted but no upload endpoint is configured. Add { image: { fileInput: { uploadUrl: "..." } } } to the toolbar to enable it.`);return}e.preventDefault(),this._uploadAll(t);return}let n=e.clipboardData?.getData(`text/plain`)?.trim(),{selectionStart:r,selectionEnd:i}=this.textarea;if(n&&i>r&&Ar.test(n)){e.preventDefault();let t=`[${this.textarea.value.slice(r,i)}](${n})`;this.editor.insertText(t,t.length,0)}}_onDrop(e){if(!this._carriesFiles(e.dataTransfer))return;e.preventDefault();let t=this._imageFiles(e.dataTransfer);if(t.length){if(!this.editor.imageUpload){console.warn(`[MarkdownEditor] An image was dropped but no upload endpoint is configured. Add { image: { fileInput: { uploadUrl: "..." } } } to the toolbar to enable it.`);return}this._uploadAll(t)}}async _uploadAll(e){for(let t of e){let e=`![${this.editor.label(`Uploading...`)}]()`;this.editor.insertText(e,e.length,0);try{let{path:n,alt:r}=await Rn(t,this.editor.imageUpload);this._replace(e,`![${r}](${n})`)}catch(t){this._replace(e,`![${this.editor.label(`Upload failed`)}]()`),console.error(`[MarkdownEditor] Image upload failed.`,t)}}}_replace(e,t){let n=this.textarea,r=n.value.indexOf(e);if(r===-1)return;n.value=n.value.slice(0,r)+t+n.value.slice(r+e.length);let i=r+t.length;n.setSelectionRange(i,i),this.editor.render(),this.editor.notifyChange()}},Mr=new ot({breaks:!0}),Nr=class{constructor(e,t={}){this.usertextarea=typeof e==`string`?document.querySelector(e):e,this.options=t,this.mode=t.mode||`plain`,this.preview=!this.options.toolbar||this.options.toolbar.includes(`preview`),this.footerOptions=this._parseFooterOptions(t.footer),this.variables=this._parseVariables(t.toolbar),this.imageUpload=this._parseImageUpload(t.toolbar),this.previewTimer=null,this.init(),this.undoRedoManager=new Cr(this),this.listManager=new Tr(this),this.indentManager=new wr(this),this.shortcutManager=new Or(this),this.findReplace=new kr(this),this.pasteManager=new jr(this)}label(e){return this.options.labels?.[e]??e}_parseImageUpload(e){let t=(Array.isArray(e)?e:[]).find(e=>e&&typeof e==`object`&&e.image)?.image?.fileInput;return t?.uploadUrl?t:null}_parseVariables(e){let t=(Array.isArray(e)?e:[]).find(e=>e&&typeof e==`object`&&Array.isArray(e.variables));return t?t.variables:[]}_parseFooterOptions(e){if(e===!1)return null;let t=e??{};return{line:t.line!==!1,col:t.col!==!1,chars:t.chars!==!1,words:t.words===!0}}init(){this.createEditor(),this.addToolbar(),this.addFooter(),this._toolbarH=this.editorContainer.querySelector(`.toolbar`)?.offsetHeight??0,this._footerH=this.editorContainer.querySelector(`.editor-footer`)?.offsetHeight??0,this._autoGrow()}createEditor(){this.isTextareaValid()&&(this.applyDefaultAttributes(),this.buildEditorLayout(),this.addInputListener(),this.render())}isTextareaValid(){return this.usertextarea.tagName===`TEXTAREA`}applyDefaultAttributes(){this.usertextarea.id&&document.querySelector(`label[for="${this.usertextarea.id}"]`)||this.usertextarea.getAttribute(`aria-label`)||this.usertextarea.getAttribute(`aria-labelledby`)||(this.usertextarea.setAttribute(`aria-label`,this.options.label||`Markdown editor`),this._addedAriaLabel=!0),this.usertextarea.classList.add(`editor-textarea`,`fj:focus:ring-0`,`fj:focus:outline-0`,`fj:border-0`,`fj:border-base-soft`,`fj:px-4`,`fj:py-2`,`fj:max-w-full`,`fj:w-full`,`fj:h-full`,`fj:bg-transparent`,`fj:outline-0`,`fj:appearance-none`,`fj:overflow-y-auto`,`fj:resize-none`),this.usertextarea.hasAttribute(`placeholder`)||(this.usertextarea.placeholder=this.options.placeholder||`Write your markdown...`)}buildEditorLayout(){this.editorContainer=document.createElement(`div`),this.editorContainer.className=`
178
177
  markdown-editor-wrapper
179
178
  fj:me-surface
180
179
  fj:me-surface-outline
@@ -217,7 +216,7 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
217
216
  fj:box-border
218
217
  fj:relative
219
218
  fj:z-10
220
- `,e.appendChild(this.displayLayer)),e.appendChild(this.usertextarea),this.markdownEditorDiv.appendChild(e)}addPreviewWrapper(){let e=new er(this.markdownEditorDiv);this.previewContent=e.getPreviewContent()}addInputListener(){this._inputHandler=()=>{this._autoGrow(),this.renderHybrid(),this.debouncedPreview(),this.notifyChange()},this._scrollHandler=()=>{this._scrollRaf||=requestAnimationFrame(()=>{if(this._scrollRaf=null,this.mode===`hybrid`&&(this.displayLayer.scrollTop=this.usertextarea.scrollTop,this.displayLayer.scrollLeft=this.usertextarea.scrollLeft),this.preview&&this.previewContent){let e=this.usertextarea,t=e.scrollTop/(e.scrollHeight-e.clientHeight);this.previewContent.scrollTop=t*(this.previewContent.scrollHeight-this.previewContent.clientHeight)}})},this.usertextarea.addEventListener(`input`,this._inputHandler),this.usertextarea.addEventListener(`scroll`,this._scrollHandler)}debouncedPreview(){this.preview&&(clearTimeout(this.previewTimer),this.previewTimer=setTimeout(()=>{this.previewContent.innerHTML=this._renderMarkdown(this.usertextarea.value),this.wirePreviewCheckboxes();let e=this.usertextarea,t=e.scrollTop/(e.scrollHeight-e.clientHeight);this.previewContent.scrollTop=t*(this.previewContent.scrollHeight-this.previewContent.clientHeight)},150))}renderMarkdown(e){return this._renderMarkdown(e)}createToolbar(e,t=[`bold`,`italic`,`strikethrough`]){let n=Object.create(this);return n.usertextarea=e,n.render=()=>{},n.notifyChange=()=>{},n.insertText=(t,n=0,r=0)=>{let{selectionStart:i,selectionEnd:a,value:o}=e,s=e.scrollTop;e.value=o.slice(0,i)+t+o.slice(a),e.focus(),e.setSelectionRange(i+n,i+t.length-r),e.scrollTop=s},new $n(n,t,{standalone:!0}).toolbar}_renderMarkdown(e){let t=this.options.renderer??(e=>Mr.parse(e)),n=this.options.sanitizer??(e=>On.sanitize(e)),r=Yn(e,this.variables),i=t(r);return this.options.renderer&&!this._taskListWarned&&/^\s*[-*] \[[ xX]\] /m.test(r)&&!/type=["']?checkbox/.test(i)&&(this._taskListWarned=!0,console.warn(`[MarkdownEditor] Task list syntax found, but the custom renderer emitted no checkboxes. Clickable checkboxes in the preview need a task-list plugin, e.g. markdown-it-task-lists.`)),n(i)}wirePreviewCheckboxes(){this.previewContent.querySelectorAll(`input[type="checkbox"]`).forEach((e,t)=>{e.removeAttribute(`disabled`),e.addEventListener(`click`,n=>{n.preventDefault();let r=this.usertextarea.value.split(`
219
+ `,e.appendChild(this.displayLayer)),e.appendChild(this.usertextarea),this.markdownEditorDiv.appendChild(e)}addPreviewWrapper(){let e=new er(this.markdownEditorDiv);this.previewContent=e.getPreviewContent()}addInputListener(){this._inputHandler=()=>{this._autoGrow(),this.renderHybrid(),this.debouncedPreview(),this.notifyChange()},this._scrollHandler=()=>{this._scrollRaf||=requestAnimationFrame(()=>{this._scrollRaf=null,this.mode===`hybrid`&&(this.displayLayer.scrollTop=this.usertextarea.scrollTop,this.displayLayer.scrollLeft=this.usertextarea.scrollLeft),this.preview&&this.previewContent&&this._syncPreviewScroll()})},this.usertextarea.addEventListener(`input`,this._inputHandler),this.usertextarea.addEventListener(`scroll`,this._scrollHandler)}debouncedPreview(){this.preview&&(clearTimeout(this.previewTimer),this.previewTimer=setTimeout(()=>{let e=this.previewContent.scrollTop;this.previewContent.innerHTML=this._renderMarkdown(this.usertextarea.value),this.wirePreviewCheckboxes(),this._syncPreviewScroll()||(this.previewContent.scrollTop=e)},150))}_syncPreviewScroll(){if(!this.preview||!this.previewContent)return!1;let e=this.usertextarea,t=e.scrollHeight-e.clientHeight;if(t<=0)return!1;let n=e.scrollTop/t,r=this.previewContent.scrollHeight-this.previewContent.clientHeight;return this.previewContent.scrollTop=n*r,!0}renderMarkdown(e){return this._renderMarkdown(e)}createToolbar(e,t=[`bold`,`italic`,`strikethrough`]){let n=Object.create(this);return n.usertextarea=e,n.render=()=>{},n.notifyChange=()=>{},n.insertText=(t,n=0,r=0)=>{let{selectionStart:i,selectionEnd:a,value:o}=e,s=e.scrollTop;e.value=o.slice(0,i)+t+o.slice(a),e.focus(),e.setSelectionRange(i+n,i+t.length-r),e.scrollTop=s},new $n(n,t,{standalone:!0}).toolbar}_renderMarkdown(e){let t=this.options.renderer??(e=>Mr.parse(e)),n=this.options.sanitizer??(e=>On.sanitize(e)),r=Yn(e,this.variables),i=t(r);return this.options.renderer&&!this._taskListWarned&&/^\s*[-*] \[[ xX]\] /m.test(r)&&!/type=["']?checkbox/.test(i)&&(this._taskListWarned=!0,console.warn(`[MarkdownEditor] Task list syntax found, but the custom renderer emitted no checkboxes. Clickable checkboxes in the preview need a task-list plugin, e.g. markdown-it-task-lists.`)),n(i)}wirePreviewCheckboxes(){this.previewContent.querySelectorAll(`input[type="checkbox"]`).forEach((e,t)=>{e.removeAttribute(`disabled`),e.addEventListener(`click`,n=>{n.preventDefault();let r=this.usertextarea.value.split(`
221
220
  `),i=0;for(let n=0;n<r.length;n++)if(/^(\s*)([-*] \[[ xX]\] )/.test(r[n])){if(i===t){e.checked?r[n]=r[n].replace(/\[ \]/,`[x]`):r[n]=r[n].replace(/\[[xX]\]/,`[ ]`);break}i++}this.usertextarea.value=r.join(`
222
221
  `),this.render(),this.notifyChange()})})}addFooter(){if(!this.footerOptions)return;let{line:e,col:t,chars:n,words:r}=this.footerOptions;(e||t||n||r)&&(this.footer=new tr(this.editorContainer,this.footerOptions),this.footer.update(this.usertextarea),this._footerUpdate=()=>this.footer.update(this.usertextarea),this.usertextarea.addEventListener(`input`,this._footerUpdate),this.usertextarea.addEventListener(`click`,this._footerUpdate),this.usertextarea.addEventListener(`keyup`,this._footerUpdate),this.usertextarea.addEventListener(`focus`,this._footerUpdate))}addToolbar(){this.toolbarInstance=new $n(this,this.options.toolbar||[`undo`,`redo`,`heading`,`blockquote`,`ul`,`ol`,`checklist`,`outdent`,`indent`,`bold`,`italic`,`strikethrough`,`code`,`codeblock`,`hr`,`table`,`link`,`image`,`preview`])}insertText(e,t=0,n=0){let{selectionStart:r,selectionEnd:i}=this.usertextarea,a=this.usertextarea.value,o=this.usertextarea.scrollTop;this.usertextarea.value=`${a.substring(0,r)}${e}${a.substring(i)}`,this.usertextarea.focus(),this.usertextarea.setSelectionRange(r+t,r+e.length-n),this.render(),this.notifyChange(),this.restoreScroll(o)}restoreScroll(e){this.usertextarea.scrollTop=e}scrollToView(){}_highlight(e){let t=e.replace(/&/g,`&amp;`).replace(/</g,`&lt;`).replace(/>/g,`&gt;`);return t=t.replace(/```(\w+)?\n([\s\S]*?)```/g,'<span class="fj:opacity-30">```$1</span>\n$2<span class="fj:opacity-30">```</span>').replace(/`([^`\n]+)`/g,'<span class="fj:opacity-40">`</span><span class="fj:text-accent">$1</span><span class="fj:opacity-40">`</span>').replace(/^(#+ )(.*)$/gm,`<span class="fj:text-primary"><span class="fj:opacity-40">$1</span><span class="faux-bold">$2</span></span>`).replace(/\*\*(.*?)\*\*/g,`<span class="fj:text-secondary"><span class="fj:opacity-40">**</span><span class="faux-bold">$1</span><span class="fj:opacity-40">**</span></span>`).replace(/^([\s]*)([\-\*] |[\d]+\. |\[[\s xX]\] )(.*)$/gm,`$1<span class="fj:text-primary">$2</span>$3`).replace(/(\*|_)(.*?)\1/g,`<span class="fj:text-accent"><span class="fj:opacity-40">$1</span>$2<span class="fj:opacity-40">$1</span></span>`).replace(/~~(.*?)~~/g,`<span class="fj:line-through fj:opacity-70"><span class="fj:opacity-40">~~</span>$1<span class="fj:opacity-40">~~</span></span>`).replace(/(?<!~)(~)([^~]+)\1(?!~)/g,`<span class="fj:line-through fj:opacity-70"><span class="fj:opacity-40">$1</span>$2<span class="fj:opacity-40">$1</span></span>`).replace(/(!?\[)(.*?)(\]\()(.*?)(\))/g,`<span class="fj:opacity-40">$1</span><span class="fj:text-primary">$2</span><span class="fj:opacity-40">$3</span><span class="fj:underline fj:opacity-50">$4</span><span class="fj:opacity-50">$5</span>`),e.endsWith(`
223
222
  `)&&(t+=` `),t}renderHybrid(){if(this.mode!==`hybrid`)return;let e=this.usertextarea.value;if(e===this._lastRaw)return;this._lastRaw=e;let t=this._highlight(e).split(`