overtype 1.1.6 → 1.1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/overtype.esm.js +79 -5
- package/dist/overtype.esm.js.map +2 -2
- package/dist/overtype.js +79 -5
- package/dist/overtype.js.map +2 -2
- package/dist/overtype.min.js +36 -17
- package/package.json +1 -1
- package/src/icons.js +5 -0
- package/src/overtype.js +29 -1
- package/src/parser.js +41 -1
- package/src/styles.js +18 -1
- package/src/toolbar.js +12 -1
package/dist/overtype.min.js
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* OverType v1.1.
|
|
2
|
+
* OverType v1.1.8
|
|
3
3
|
* A lightweight markdown editor library with perfect WYSIWYG alignment
|
|
4
4
|
* @license MIT
|
|
5
5
|
* @author Demo User
|
|
6
6
|
* https://github.com/demo/overtype
|
|
7
7
|
*/
|
|
8
|
-
var OverType=(()=>{var
|
|
9
|
-
`).map((a,s)=>o&&s===t?`<div class="raw-line">${this.escapeHtml(a)||" "}</div>`:this.parseLine(a)).join("")}}
|
|
8
|
+
var OverType=(()=>{var N=Object.defineProperty;var Be=Object.getOwnPropertyDescriptor;var Pe=Object.getOwnPropertyNames;var je=Object.prototype.hasOwnProperty;var Oe=(n,e,t)=>e in n?N(n,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):n[e]=t;var Ne=(n,e)=>{for(var t in e)N(n,t,{get:e[t],enumerable:!0})},ze=(n,e,t,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of Pe(e))!je.call(n,i)&&i!==t&&N(n,i,{get:()=>e[i],enumerable:!(o=Be(e,i))||o.enumerable});return n};var _e=n=>ze(N({},"__esModule",{value:!0}),n);var $=(n,e,t)=>(Oe(n,typeof e!="symbol"?e+"":e,t),t);var Ye={};Ne(Ye,{OverType:()=>A,default:()=>Xe});var I=class{static resetLinkIndex(){this.linkIndex=0}static escapeHtml(e){let t={"&":"&","<":"<",">":">",'"':""","'":"'"};return e.replace(/[&<>"']/g,o=>t[o])}static preserveIndentation(e,t){let i=t.match(/^(\s*)/)[1].replace(/ /g," ");return e.replace(/^\s*/,i)}static parseHeader(e){return e.replace(/^(#{1,3})\s(.+)$/,(t,o,i)=>{let r=o.length;return`<span class="header ${["h1","h2","h3"][r-1]}"><span class="syntax-marker">${o}</span> ${i}</span>`})}static parseHorizontalRule(e){return e.match(/^(-{3,}|\*{3,}|_{3,})$/)?`<div><span class="hr-marker">${e}</span></div>`:null}static parseBlockquote(e){return e.replace(/^> (.+)$/,(t,o)=>`<span class="blockquote"><span class="syntax-marker">></span> ${o}</span>`)}static parseBulletList(e){return e.replace(/^((?: )*)([-*])\s(.+)$/,(t,o,i,r)=>`${o}<span class="syntax-marker">${i}</span> ${r}`)}static parseNumberedList(e){return e.replace(/^((?: )*)(\d+\.)\s(.+)$/,(t,o,i,r)=>`${o}<span class="syntax-marker">${i}</span> ${r}`)}static parseCodeBlock(e){return/^`{3}[^`]*$/.test(e)?`<div><span class="code-fence">${e}</span></div>`:null}static parseBold(e){return e=e.replace(/\*\*(.+?)\*\*/g,'<strong><span class="syntax-marker">**</span>$1<span class="syntax-marker">**</span></strong>'),e=e.replace(/__(.+?)__/g,'<strong><span class="syntax-marker">__</span>$1<span class="syntax-marker">__</span></strong>'),e}static parseItalic(e){return e=e.replace(new RegExp("(?<!\\*)\\*(?!\\*)(.+?)(?<!\\*)\\*(?!\\*)","g"),'<em><span class="syntax-marker">*</span>$1<span class="syntax-marker">*</span></em>'),e=e.replace(new RegExp("(?<!_)_(?!_)(.+?)(?<!_)_(?!_)","g"),'<em><span class="syntax-marker">_</span>$1<span class="syntax-marker">_</span></em>'),e}static parseInlineCode(e){return e.replace(new RegExp("(?<!`)(`+)(?!`)((?:(?!\\1).)+?)(\\1)(?!`)","g"),'<code><span class="syntax-marker">$1</span>$2<span class="syntax-marker">$3</span></code>')}static sanitizeUrl(e){let t=e.trim(),o=t.toLowerCase(),r=["http://","https://","mailto:","ftp://","ftps://"].some(s=>o.startsWith(s)),a=t.startsWith("/")||t.startsWith("#")||t.startsWith("?")||t.startsWith(".")||!t.includes(":")&&!t.includes("//");return r||a?e:"#"}static parseLinks(e){return e.replace(/\[(.+?)\]\((.+?)\)/g,(t,o,i)=>{let r=`--link-${this.linkIndex++}`;return`<a href="${this.sanitizeUrl(i)}" style="anchor-name: ${r}"><span class="syntax-marker">[</span>${o}<span class="syntax-marker">](</span><span class="syntax-marker link-url">${i}</span><span class="syntax-marker">)</span></a>`})}static parseInlineElements(e){let t=e;t=this.parseInlineCode(t);let o=new Map;return t=t.replace(/(<code>.*?<\/code>)/g,i=>{let r=`\uE000${o.size}\uE001`;return o.set(r,i),r}),t=this.parseLinks(t),t=t.replace(/(<a[^>]*>.*?<\/a>)/g,i=>{let r=`\uE000${o.size}\uE001`;return o.set(r,i),r}),t=this.parseBold(t),t=this.parseItalic(t),o.forEach((i,r)=>{t=t.replace(r,i)}),t}static parseLine(e){let t=this.escapeHtml(e);t=this.preserveIndentation(t,e);let o=this.parseHorizontalRule(t);if(o)return o;let i=this.parseCodeBlock(t);return i||(t=this.parseHeader(t),t=this.parseBlockquote(t),t=this.parseBulletList(t),t=this.parseNumberedList(t),t=this.parseInlineElements(t),t.trim()===""?"<div> </div>":`<div>${t}</div>`)}static parse(e,t=-1,o=!1){return this.resetLinkIndex(),e.split(`
|
|
9
|
+
`).map((a,s)=>o&&s===t?`<div class="raw-line">${this.escapeHtml(a)||" "}</div>`:this.parseLine(a)).join("")}};$(I,"linkIndex",0);var Fe=Object.defineProperty,Y=Object.getOwnPropertySymbols,Re=Object.prototype.hasOwnProperty,Ve=Object.prototype.propertyIsEnumerable,ee=(n,e,t)=>e in n?Fe(n,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):n[e]=t,te=(n,e)=>{for(var t in e||(e={}))Re.call(e,t)&&ee(n,t,e[t]);if(Y)for(var t of Y(e))Ve.call(e,t)&&ee(n,t,e[t]);return n},S={bold:{prefix:"**",suffix:"**",trimFirst:!0},italic:{prefix:"_",suffix:"_",trimFirst:!0},code:{prefix:"`",suffix:"`",blockPrefix:"```",blockSuffix:"```"},link:{prefix:"[",suffix:"](url)",replaceNext:"url",scanFor:"https?://"},bulletList:{prefix:"- ",multiline:!0,unorderedList:!0},numberedList:{prefix:"1. ",multiline:!0,orderedList:!0},quote:{prefix:"> ",multiline:!0,surroundWithNewlines:!0},taskList:{prefix:"- [ ] ",multiline:!0,surroundWithNewlines:!0},header1:{prefix:"# "},header2:{prefix:"## "},header3:{prefix:"### "},header4:{prefix:"#### "},header5:{prefix:"##### "},header6:{prefix:"###### "}};function De(){return{prefix:"",suffix:"",blockPrefix:"",blockSuffix:"",multiline:!1,replaceNext:"",prefixSpace:!1,scanFor:"",surroundWithNewlines:!1,orderedList:!1,unorderedList:!1,trimFirst:!1}}function E(n){return te(te({},De()),n)}var _=!1;function qe(){return _}function g(n,e,t){_&&(console.group(`\u{1F50D} ${n}`),console.log(e),t&&console.log("Data:",t),console.groupEnd())}function z(n,e){if(!_)return;let t=n.value.slice(n.selectionStart,n.selectionEnd);console.group(`\u{1F4CD} Selection: ${e}`),console.log("Position:",`${n.selectionStart}-${n.selectionEnd}`),console.log("Selected text:",JSON.stringify(t)),console.log("Length:",t.length);let o=n.value.slice(Math.max(0,n.selectionStart-10),n.selectionStart),i=n.value.slice(n.selectionEnd,Math.min(n.value.length,n.selectionEnd+10));console.log("Context:",JSON.stringify(o)+"[SELECTION]"+JSON.stringify(i)),console.groupEnd()}function re(n){_&&(console.group("\u{1F4DD} Result"),console.log("Text to insert:",JSON.stringify(n.text)),console.log("New selection:",`${n.selectionStart}-${n.selectionEnd}`),console.groupEnd())}var C=null;function H(n,{text:e,selectionStart:t,selectionEnd:o}){let i=qe();i&&(console.group("\u{1F527} insertText"),console.log("Current selection:",`${n.selectionStart}-${n.selectionEnd}`),console.log("Text to insert:",JSON.stringify(e)),console.log("New selection to set:",t,"-",o)),n.focus();let r=n.selectionStart,a=n.selectionEnd,s=n.value.slice(0,r),l=n.value.slice(a);i&&(console.log("Before text (last 20):",JSON.stringify(s.slice(-20))),console.log("After text (first 20):",JSON.stringify(l.slice(0,20))),console.log("Selected text being replaced:",JSON.stringify(n.value.slice(r,a))));let d=n.value,p=r!==a;if(C===null||C===!0){n.contentEditable="true";try{C=document.execCommand("insertText",!1,e),i&&console.log("execCommand returned:",C,"for text with",e.split(`
|
|
10
10
|
`).length,"lines")}catch(c){C=!1,i&&console.log("execCommand threw error:",c)}n.contentEditable="false"}if(i&&(console.log("canInsertText before:",C),console.log("execCommand result:",C)),C){let c=s+e+l,m=n.value;i&&(console.log("Expected length:",c.length),console.log("Actual length:",m.length)),m!==c&&i&&(console.log("execCommand changed the value but not as expected"),console.log("Expected:",JSON.stringify(c.slice(0,100))),console.log("Actual:",JSON.stringify(m.slice(0,100))))}if(!C)if(i&&console.log("Using manual insertion"),n.value===d){i&&console.log("Value unchanged, doing manual replacement");try{document.execCommand("ms-beginUndoUnit")}catch(c){}n.value=s+e+l;try{document.execCommand("ms-endUndoUnit")}catch(c){}n.dispatchEvent(new CustomEvent("input",{bubbles:!0,cancelable:!0}))}else i&&console.log("Value was changed by execCommand, skipping manual insertion");i&&console.log("Setting selection range:",t,o),t!=null&&o!=null?n.setSelectionRange(t,o):n.setSelectionRange(r,n.selectionEnd),i&&(console.log("Final value length:",n.value.length),console.groupEnd())}function ne(n){return n.trim().split(`
|
|
11
|
-
`).length>1}function
|
|
12
|
-
`),t=0;for(let o=0;o<e.length;o++){let i=e[o].length+1;n.selectionStart>=t&&n.selectionStart<t+i&&(n.selectionStart=t),n.selectionEnd>=t&&n.selectionEnd<t+i&&(o===e.length-1?n.selectionEnd=Math.min(t+e[o].length,n.value.length):n.selectionEnd=t+i-1),t+=i}}function Ke(n,e,t,o=!1){if(n.selectionStart===n.selectionEnd)n.selectionStart=
|
|
11
|
+
`).length>1}function We(n,e){let t=e;for(;n[t]&&n[t-1]!=null&&!n[t-1].match(/\s/);)t--;return t}function Ue(n,e,t){let o=e,i=t?/\n/:/\s/;for(;n[o]&&!n[o].match(i);)o++;return o}function se(n){let e=n.value.split(`
|
|
12
|
+
`),t=0;for(let o=0;o<e.length;o++){let i=e[o].length+1;n.selectionStart>=t&&n.selectionStart<t+i&&(n.selectionStart=t),n.selectionEnd>=t&&n.selectionEnd<t+i&&(o===e.length-1?n.selectionEnd=Math.min(t+e[o].length,n.value.length):n.selectionEnd=t+i-1),t+=i}}function Ke(n,e,t,o=!1){if(n.selectionStart===n.selectionEnd)n.selectionStart=We(n.value,n.selectionStart),n.selectionEnd=Ue(n.value,n.selectionEnd,o);else{let i=n.selectionStart-e.length,r=n.selectionEnd+t.length,a=n.value.slice(i,n.selectionStart)===e,s=n.value.slice(n.selectionEnd,r)===t;a&&s&&(n.selectionStart=i,n.selectionEnd=r)}return n.value.slice(n.selectionStart,n.selectionEnd)}function J(n){let e=n.value.slice(0,n.selectionStart),t=n.value.slice(n.selectionEnd),o=e.match(/\n*$/),i=t.match(/^\n*/),r=o?o[0].length:0,a=i?i[0].length:0,s="",l="";return e.match(/\S/)&&r<2&&(s=`
|
|
13
13
|
`.repeat(2-r)),t.match(/\S/)&&a<2&&(l=`
|
|
14
14
|
`.repeat(2-a)),{newlinesToAppend:s,newlinesToPrepend:l}}function F(n,e,t={}){let o=n.selectionStart,i=n.selectionEnd,r=o===i,a=n.value,s=o;for(;s>0&&a[s-1]!==`
|
|
15
15
|
`;)s--;if(r){let d=o;for(;d<a.length&&a[d]!==`
|
|
@@ -22,12 +22,12 @@ ${s}`:r;if(d){let x=n.value[n.selectionStart-1];n.selectionStart!==0&&x!=null&&!
|
|
|
22
22
|
`),t=/^\d+\.\s+/,o=e.every(r=>t.test(r)),i=e;return o&&(i=e.map(r=>r.replace(t,""))),{text:i.join(`
|
|
23
23
|
`),processed:o}}function ie(n){let e=n.split(`
|
|
24
24
|
`),t="- ",o=e.every(r=>r.startsWith(t)),i=e;return o&&(i=e.map(r=>r.slice(t.length))),{text:i.join(`
|
|
25
|
-
`),processed:o}}function
|
|
26
|
-
`).map((f,u)=>`${
|
|
27
|
-
`)+h;return t?(o=Math.max(o+
|
|
28
|
-
`),a=0,s="";for(let c of r){if(t>=a&&t<=a+c.length){s=c;break}a+=c.length+1}s.startsWith("- ")&&(s.startsWith("- [ ] ")||s.startsWith("- [x] ")?e.push("task-list"):e.push("bullet-list")),/^\d+\.\s/.test(s)&&e.push("numbered-list"),s.startsWith("> ")&&e.push("quote"),s.startsWith("# ")&&e.push("header"),s.startsWith("## ")&&e.push("header-2"),s.startsWith("### ")&&e.push("header-3");let l=Math.max(0,t-10),d=Math.min(i.length,o+10),p=i.slice(l,d);if(p.includes("**")){let c=i.slice(Math.max(0,t-100),t),m=i.slice(o,Math.min(i.length,o+100)),h=c.lastIndexOf("**"),v=m.indexOf("**");h!==-1&&v!==-1&&e.push("bold")}if(p.includes("_")){let c=i.slice(Math.max(0,t-100),t),m=i.slice(o,Math.min(i.length,o+100)),h=c.lastIndexOf("_"),v=m.indexOf("_");h!==-1&&v!==-1&&e.push("italic")}if(p.includes("`")){let c=i.slice(Math.max(0,t-100),t),m=i.slice(o,Math.min(i.length,o+100));c.includes("`")&&m.includes("`")&&e.push("code")}if(p.includes("[")&&p.includes("]")){let c=i.slice(Math.max(0,t-100),t),m=i.slice(o,Math.min(i.length,o+100)),h=c.lastIndexOf("["),v=m.indexOf("]");h!==-1&&v!==-1&&i.slice(o+v+1,o+v+10).startsWith("(")&&e.push("link")}return e}function V(n){if(!n||n.disabled||n.readOnly)return;g("toggleBold","Starting"),z(n,"Before");let e=E(S.bold),t=R(n,e);re(t),H(n,t),z(n,"After")}function D(n){if(!n||n.disabled||n.readOnly)return;let e=E(S.italic),t=R(n,e);H(n,t)}function ce(n){if(!n||n.disabled||n.readOnly)return;let e=E(S.code),t=R(n,e);H(n,t)}function q(n,e={}){if(!n||n.disabled||n.readOnly)return;let t=n.value.slice(n.selectionStart,n.selectionEnd),o=E(S.link);if(t&&t.match(/^https?:\/\//)&&!e.url?(o.suffix=`](${t})`,o.replaceNext=""):e.url&&(o.suffix=`](${e.url})`,o.replaceNext=""),e.text&&!t){let a=n.selectionStart;n.value=n.value.slice(0,a)+e.text+n.value.slice(a),n.selectionStart=a,n.selectionEnd=a+e.text.length}let r=R(n,o);H(n,r)}function W(n){if(!n||n.disabled||n.readOnly)return;let e=E(S.bulletList);le(n,e)}function
|
|
25
|
+
`),processed:o}}function P(n,e){return e?"- ":`${n+1}. `}function Ze(n,e){let t,o,i;return n.orderedList?(t=oe(e),o=ie(t.text),i=o.text):(t=ie(e),o=oe(t.text),i=o.text),[t,o,i]}function Je(n,e){let t=n.selectionStart===n.selectionEnd,o=n.selectionStart,i=n.selectionEnd;se(n);let r=n.value.slice(n.selectionStart,n.selectionEnd),[a,s,l]=Ze(e,r),d=l.split(`
|
|
26
|
+
`).map((f,u)=>`${P(u,e.unorderedList)}${f}`),p=d.reduce((f,u,b)=>f+P(b,e.unorderedList).length,0),c=d.reduce((f,u,b)=>f+P(b,!e.unorderedList).length,0);if(a.processed)return t?(o=Math.max(o-P(0,e.unorderedList).length,0),i=o):(o=n.selectionStart,i=n.selectionEnd-p),{text:l,selectionStart:o,selectionEnd:i};let{newlinesToAppend:m,newlinesToPrepend:h}=J(n),v=m+d.join(`
|
|
27
|
+
`)+h;return t?(o=Math.max(o+P(0,e.unorderedList).length+m.length,0),i=o):s.processed?(o=Math.max(n.selectionStart+m.length,0),i=n.selectionEnd+m.length+p-c):(o=Math.max(n.selectionStart+m.length,0),i=n.selectionEnd+m.length+p),{text:v,selectionStart:o,selectionEnd:i}}function le(n,e){let t=F(n,o=>Je(o,e),{adjustSelection:(o,i,r,a)=>{let s=n.value.slice(a,n.selectionEnd),l=/^\d+\.\s+/,d=/^- /,p=l.test(s),c=d.test(s),m=e.orderedList&&p||e.unorderedList&&c;if(i===r)if(m){let h=s.match(e.orderedList?l:d),v=h?h[0].length:0;return{start:Math.max(i-v,a),end:Math.max(i-v,a)}}else if(p||c){let h=s.match(p?l:d),v=h?h[0].length:0,u=(e.unorderedList?2:3)-v;return{start:i+u,end:i+u}}else{let h=e.unorderedList?2:3;return{start:i+h,end:i+h}}else if(m){let h=s.match(e.orderedList?l:d),v=h?h[0].length:0;return{start:Math.max(i-v,a),end:Math.max(r-v,a)}}else if(p||c){let h=s.match(p?l:d),v=h?h[0].length:0,u=(e.unorderedList?2:3)-v;return{start:i+u,end:r+u}}else{let h=e.unorderedList?2:3;return{start:i+h,end:r+h}}}});H(n,t)}function Qe(n){if(!n)return[];let e=[],{selectionStart:t,selectionEnd:o,value:i}=n,r=i.split(`
|
|
28
|
+
`),a=0,s="";for(let c of r){if(t>=a&&t<=a+c.length){s=c;break}a+=c.length+1}s.startsWith("- ")&&(s.startsWith("- [ ] ")||s.startsWith("- [x] ")?e.push("task-list"):e.push("bullet-list")),/^\d+\.\s/.test(s)&&e.push("numbered-list"),s.startsWith("> ")&&e.push("quote"),s.startsWith("# ")&&e.push("header"),s.startsWith("## ")&&e.push("header-2"),s.startsWith("### ")&&e.push("header-3");let l=Math.max(0,t-10),d=Math.min(i.length,o+10),p=i.slice(l,d);if(p.includes("**")){let c=i.slice(Math.max(0,t-100),t),m=i.slice(o,Math.min(i.length,o+100)),h=c.lastIndexOf("**"),v=m.indexOf("**");h!==-1&&v!==-1&&e.push("bold")}if(p.includes("_")){let c=i.slice(Math.max(0,t-100),t),m=i.slice(o,Math.min(i.length,o+100)),h=c.lastIndexOf("_"),v=m.indexOf("_");h!==-1&&v!==-1&&e.push("italic")}if(p.includes("`")){let c=i.slice(Math.max(0,t-100),t),m=i.slice(o,Math.min(i.length,o+100));c.includes("`")&&m.includes("`")&&e.push("code")}if(p.includes("[")&&p.includes("]")){let c=i.slice(Math.max(0,t-100),t),m=i.slice(o,Math.min(i.length,o+100)),h=c.lastIndexOf("["),v=m.indexOf("]");h!==-1&&v!==-1&&i.slice(o+v+1,o+v+10).startsWith("(")&&e.push("link")}return e}function V(n){if(!n||n.disabled||n.readOnly)return;g("toggleBold","Starting"),z(n,"Before");let e=E(S.bold),t=R(n,e);re(t),H(n,t),z(n,"After")}function D(n){if(!n||n.disabled||n.readOnly)return;let e=E(S.italic),t=R(n,e);H(n,t)}function ce(n){if(!n||n.disabled||n.readOnly)return;let e=E(S.code),t=R(n,e);H(n,t)}function q(n,e={}){if(!n||n.disabled||n.readOnly)return;let t=n.value.slice(n.selectionStart,n.selectionEnd),o=E(S.link);if(t&&t.match(/^https?:\/\//)&&!e.url?(o.suffix=`](${t})`,o.replaceNext=""):e.url&&(o.suffix=`](${e.url})`,o.replaceNext=""),e.text&&!t){let a=n.selectionStart;n.value=n.value.slice(0,a)+e.text+n.value.slice(a),n.selectionStart=a,n.selectionEnd=a+e.text.length}let r=R(n,o);H(n,r)}function W(n){if(!n||n.disabled||n.readOnly)return;let e=E(S.bulletList);le(n,e)}function U(n){if(!n||n.disabled||n.readOnly)return;let e=E(S.numberedList);le(n,e)}function pe(n){if(!n||n.disabled||n.readOnly)return;g("toggleQuote","Starting"),z(n,"Initial");let e=E(S.quote),t=F(n,o=>ae(o,e),{prefix:e.prefix});re(t),H(n,t),z(n,"Final")}function de(n){if(!n||n.disabled||n.readOnly)return;let e=E(S.taskList),t=F(n,o=>ae(o,e),{prefix:e.prefix});H(n,t)}function Q(n,e=1,t=!1){if(!n||n.disabled||n.readOnly)return;(e<1||e>6)&&(e=1),g("insertHeader","============ START ============"),g("insertHeader",`Level: ${e}, Toggle: ${t}`),g("insertHeader",`Initial cursor: ${n.selectionStart}-${n.selectionEnd}`);let o=`header${e===1?"1":e}`,i=E(S[o]||S.header1);g("insertHeader",`Style prefix: "${i.prefix}"`);let r=n.value,a=n.selectionStart,s=n.selectionEnd,l=a;for(;l>0&&r[l-1]!==`
|
|
29
29
|
`;)l--;let d=s;for(;d<r.length&&r[d]!==`
|
|
30
|
-
`;)d++;let p=r.slice(l,d);g("insertHeader",`Current line (before): "${p}"`);let c=p.match(/^(#{1,6})\s*/),m=c?c[1].length:0,h=c?c[0].length:0;g("insertHeader","Existing header check:"),g("insertHeader",` - Match: ${c?`"${c[0]}"`:"none"}`),g("insertHeader",` - Existing level: ${m}`),g("insertHeader",` - Existing prefix length: ${h}`),g("insertHeader",` - Target level: ${e}`);let v=t&&m===e;g("insertHeader",`Should toggle OFF: ${v} (toggle=${t}, existingLevel=${m}, level=${e})`);let f=F(n,u=>{let b=u.value.slice(u.selectionStart,u.selectionEnd);g("insertHeader",`Line in operation: "${b}"`);let y=b.replace(/^#{1,6}\s*/,"");g("insertHeader",`Cleaned line: "${y}"`);let w;return v?(g("insertHeader","ACTION: Toggling OFF - removing header"),w=y):m>0?(g("insertHeader",`ACTION: Replacing H${m} with H${e}`),w=i.prefix+y):(g("insertHeader","ACTION: Adding new header"),w=i.prefix+y),g("insertHeader",`New line: "${w}"`),{text:w,selectionStart:u.selectionStart,selectionEnd:u.selectionEnd}},{prefix:i.prefix,adjustSelection:(u,b,y,w)=>{if(g("insertHeader","Adjusting selection:"),g("insertHeader",` - isRemoving param: ${u}`),g("insertHeader",` - shouldToggleOff: ${v}`),g("insertHeader",` - selStart: ${b}, selEnd: ${y}`),g("insertHeader",` - lineStartPos: ${w}`),v){let T=Math.max(b-h,w);return g("insertHeader",` - Removing header, adjusting by -${h}`),{start:T,end:b===y?T:Math.max(y-h,w)}}else if(h>0){let T=i.prefix.length-h;return g("insertHeader",` - Replacing header, adjusting by ${T}`),{start:b+T,end:y+T}}else return g("insertHeader",` - Adding header, adjusting by +${i.prefix.length}`),{start:b+i.prefix.length,end:y+i.prefix.length}}});g("insertHeader",`Final result: text="${f.text}", cursor=${f.selectionStart}-${f.selectionEnd}`),g("insertHeader","============ END ============"),H(n,f)}function he(n){Q(n,1,!0)}function ue(n){Q(n,2,!0)}function me(n){Q(n,3,!0)}function fe(n){return
|
|
30
|
+
`;)d++;let p=r.slice(l,d);g("insertHeader",`Current line (before): "${p}"`);let c=p.match(/^(#{1,6})\s*/),m=c?c[1].length:0,h=c?c[0].length:0;g("insertHeader","Existing header check:"),g("insertHeader",` - Match: ${c?`"${c[0]}"`:"none"}`),g("insertHeader",` - Existing level: ${m}`),g("insertHeader",` - Existing prefix length: ${h}`),g("insertHeader",` - Target level: ${e}`);let v=t&&m===e;g("insertHeader",`Should toggle OFF: ${v} (toggle=${t}, existingLevel=${m}, level=${e})`);let f=F(n,u=>{let b=u.value.slice(u.selectionStart,u.selectionEnd);g("insertHeader",`Line in operation: "${b}"`);let y=b.replace(/^#{1,6}\s*/,"");g("insertHeader",`Cleaned line: "${y}"`);let w;return v?(g("insertHeader","ACTION: Toggling OFF - removing header"),w=y):m>0?(g("insertHeader",`ACTION: Replacing H${m} with H${e}`),w=i.prefix+y):(g("insertHeader","ACTION: Adding new header"),w=i.prefix+y),g("insertHeader",`New line: "${w}"`),{text:w,selectionStart:u.selectionStart,selectionEnd:u.selectionEnd}},{prefix:i.prefix,adjustSelection:(u,b,y,w)=>{if(g("insertHeader","Adjusting selection:"),g("insertHeader",` - isRemoving param: ${u}`),g("insertHeader",` - shouldToggleOff: ${v}`),g("insertHeader",` - selStart: ${b}, selEnd: ${y}`),g("insertHeader",` - lineStartPos: ${w}`),v){let T=Math.max(b-h,w);return g("insertHeader",` - Removing header, adjusting by -${h}`),{start:T,end:b===y?T:Math.max(y-h,w)}}else if(h>0){let T=i.prefix.length-h;return g("insertHeader",` - Replacing header, adjusting by ${T}`),{start:b+T,end:y+T}}else return g("insertHeader",` - Adding header, adjusting by +${i.prefix.length}`),{start:b+i.prefix.length,end:y+i.prefix.length}}});g("insertHeader",`Final result: text="${f.text}", cursor=${f.selectionStart}-${f.selectionEnd}`),g("insertHeader","============ END ============"),H(n,f)}function he(n){Q(n,1,!0)}function ue(n){Q(n,2,!0)}function me(n){Q(n,3,!0)}function fe(n){return Qe(n)}var j=class{constructor(e){this.editor=e,this.textarea=e.textarea}handleKeydown(e){if(!(navigator.platform.toLowerCase().includes("mac")?e.metaKey:e.ctrlKey))return!1;let i=null;switch(e.key.toLowerCase()){case"b":e.shiftKey||(i="toggleBold");break;case"i":e.shiftKey||(i="toggleItalic");break;case"k":e.shiftKey||(i="insertLink");break;case"7":e.shiftKey&&(i="toggleNumberedList");break;case"8":e.shiftKey&&(i="toggleBulletList");break}return i?(e.preventDefault(),this.editor.toolbar?this.editor.toolbar.handleAction(i):this.handleAction(i),!0):!1}async handleAction(e){let t=this.textarea;if(t){t.focus();try{switch(e){case"toggleBold":V(t);break;case"toggleItalic":D(t);break;case"insertLink":q(t);break;case"toggleBulletList":W(t);break;case"toggleNumberedList":U(t);break}t.dispatchEvent(new Event("input",{bubbles:!0}))}catch(o){console.error("Error in markdown action:",o)}}}destroy(){}};var M={name:"solar",colors:{bgPrimary:"#faf0ca",bgSecondary:"#ffffff",text:"#0d3b66",h1:"#f95738",h2:"#ee964b",h3:"#3d8a51",strong:"#ee964b",em:"#f95738",link:"#0d3b66",code:"#0d3b66",codeBg:"rgba(244, 211, 94, 0.4)",blockquote:"#5a7a9b",hr:"#5a7a9b",syntaxMarker:"rgba(13, 59, 102, 0.52)",cursor:"#f95738",selection:"rgba(244, 211, 94, 0.4)",listMarker:"#ee964b",toolbarBg:"#ffffff",toolbarBorder:"rgba(13, 59, 102, 0.15)",toolbarIcon:"#0d3b66",toolbarHover:"#f5f5f5",toolbarActive:"#faf0ca"}},ve={name:"cave",colors:{bgPrimary:"#141E26",bgSecondary:"#1D2D3E",text:"#c5dde8",h1:"#d4a5ff",h2:"#f6ae2d",h3:"#9fcfec",strong:"#f6ae2d",em:"#9fcfec",link:"#9fcfec",code:"#c5dde8",codeBg:"#1a232b",blockquote:"#9fcfec",hr:"#c5dde8",syntaxMarker:"rgba(159, 207, 236, 0.73)",cursor:"#f26419",selection:"rgba(51, 101, 138, 0.4)",listMarker:"#f6ae2d",toolbarBg:"#1D2D3E",toolbarBorder:"rgba(197, 221, 232, 0.1)",toolbarIcon:"#c5dde8",toolbarHover:"#243546",toolbarActive:"#2a3f52"}},ye={solar:M,cave:ve,light:M,dark:ve};function B(n){return typeof n=="string"?{...ye[n]||ye.solar,name:n}:n}function O(n){let e=[];for(let[t,o]of Object.entries(n)){let i=t.replace(/([A-Z])/g,"-$1").toLowerCase();e.push(`--${i}: ${o};`)}return e.join(`
|
|
31
31
|
`)}function be(n,e={}){return{...n,colors:{...n.colors,...e}}}function ke(n={}){let{fontSize:e="14px",lineHeight:t=1.6,fontFamily:o='"SF Mono", SFMono-Regular, Menlo, Monaco, "Cascadia Code", Consolas, "Roboto Mono", "Noto Sans Mono", "Droid Sans Mono", "Ubuntu Mono", "DejaVu Sans Mono", "Liberation Mono", "Courier New", Courier, monospace',padding:i="20px",theme:r=null,mobile:a={}}=n,s=Object.keys(a).length>0?`
|
|
32
32
|
@media (max-width: 640px) {
|
|
33
33
|
.overtype-wrapper .overtype-input,
|
|
@@ -36,7 +36,7 @@ ${s}`:r;if(d){let x=n.value[n.selectionStart-1];n.selectionStart!==0&&x!=null&&!
|
|
|
36
36
|
`)}
|
|
37
37
|
}
|
|
38
38
|
}
|
|
39
|
-
`:"",l=r&&r.colors?
|
|
39
|
+
`:"",l=r&&r.colors?O(r.colors):"";return`
|
|
40
40
|
/* OverType Editor Styles */
|
|
41
41
|
.overtype-container {
|
|
42
42
|
display: grid !important;
|
|
@@ -82,7 +82,6 @@ ${s}`:r;if(d){let x=n.value[n.selectionStart-1];n.selectionStart!==0&&x!=null&&!
|
|
|
82
82
|
|
|
83
83
|
/* Font properties - any difference breaks alignment */
|
|
84
84
|
font-family: ${o} !important;
|
|
85
|
-
font-synthesis: none !important; /* no faux bold/italic width drift */
|
|
86
85
|
font-variant-ligatures: none !important; /* keep metrics stable for code */
|
|
87
86
|
font-size: var(--instance-font-size, ${e}) !important;
|
|
88
87
|
line-height: var(--instance-line-height, ${t}) !important;
|
|
@@ -478,6 +477,23 @@ ${s}`:r;if(d){let x=n.value[n.selectionStart-1];n.selectionStart!==0&&x!=null&&!
|
|
|
478
477
|
margin: 0 2px;
|
|
479
478
|
}
|
|
480
479
|
}
|
|
480
|
+
|
|
481
|
+
/* Plain mode - hide preview and show textarea text */
|
|
482
|
+
.overtype-container.plain-mode .overtype-preview {
|
|
483
|
+
display: none !important;
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
.overtype-container.plain-mode .overtype-input {
|
|
487
|
+
color: var(--text, #0d3b66) !important;
|
|
488
|
+
/* Use system font stack for better plain text readability */
|
|
489
|
+
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
|
|
490
|
+
"Helvetica Neue", Arial, sans-serif !important;
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
/* Ensure textarea remains transparent in overlay mode */
|
|
494
|
+
.overtype-container:not(.plain-mode) .overtype-input {
|
|
495
|
+
color: transparent !important;
|
|
496
|
+
}
|
|
481
497
|
|
|
482
498
|
${s}
|
|
483
499
|
`}var we=`<svg viewBox="0 0 18 18">
|
|
@@ -516,17 +532,20 @@ ${s}`:r;if(d){let x=n.value[n.selectionStart-1];n.selectionStart!==0&&x!=null&&!
|
|
|
516
532
|
<path fill="currentColor" d="M3.5,6A0.5,0.5,0,0,1,3,5.5V3.085l-0.276.138A0.5,0.5,0,0,1,2.053,3c-0.124-.247-0.023-0.324.224-0.447l1-.5A0.5,0.5,0,0,1,4,2.5v3A0.5,0.5,0,0,1,3.5,6Z"></path>
|
|
517
533
|
<path stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="1" d="M4.5,10.5h-2c0-.234,1.85-1.076,1.85-2.234A0.959,0.959,0,0,0,2.5,8.156"></path>
|
|
518
534
|
<path stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="1" d="M2.5,14.846a0.959,0.959,0,0,0,1.85-.109A0.7,0.7,0,0,0,3.75,14a0.688,0.688,0,0,0,.6-0.736,0.959,0.959,0,0,0-1.85-.109"></path>
|
|
519
|
-
</svg
|
|
535
|
+
</svg>`,Me=`<svg viewBox="2 2 20 20">
|
|
520
536
|
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 10.8182L9 10.8182C8.80222 10.8182 8.60888 10.7649 8.44443 10.665C8.27998 10.5651 8.15181 10.4231 8.07612 10.257C8.00043 10.0909 7.98063 9.90808 8.01922 9.73174C8.0578 9.55539 8.15304 9.39341 8.29289 9.26627C8.43275 9.13913 8.61093 9.05255 8.80491 9.01747C8.99889 8.98239 9.19996 9.00039 9.38268 9.0692C9.56541 9.13801 9.72159 9.25453 9.83147 9.40403C9.94135 9.55353 10 9.72929 10 9.90909L10 12.1818C10 12.664 9.78929 13.1265 9.41421 13.4675C9.03914 13.8084 8.53043 14 8 14"></path>
|
|
521
537
|
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16 10.8182L15 10.8182C14.8022 10.8182 14.6089 10.7649 14.4444 10.665C14.28 10.5651 14.1518 10.4231 14.0761 10.257C14.0004 10.0909 13.9806 9.90808 14.0192 9.73174C14.0578 9.55539 14.153 9.39341 14.2929 9.26627C14.4327 9.13913 14.6109 9.05255 14.8049 9.01747C14.9989 8.98239 15.2 9.00039 15.3827 9.0692C15.5654 9.13801 15.7216 9.25453 15.8315 9.40403C15.9414 9.55353 16 9.72929 16 9.90909L16 12.1818C16 12.664 15.7893 13.1265 15.4142 13.4675C15.0391 13.8084 14.5304 14 14 14"></path>
|
|
522
|
-
</svg
|
|
538
|
+
</svg>`,$e=`<svg viewBox="0 0 18 18">
|
|
523
539
|
<line stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" x1="8" x2="16" y1="4" y2="4"></line>
|
|
524
540
|
<line stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" x1="8" x2="16" y1="9" y2="9"></line>
|
|
525
541
|
<line stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" x1="8" x2="16" y1="14" y2="14"></line>
|
|
526
542
|
<rect stroke="currentColor" fill="none" stroke-width="1.5" x="2" y="3" width="3" height="3" rx="0.5"></rect>
|
|
527
543
|
<rect stroke="currentColor" fill="none" stroke-width="1.5" x="2" y="13" width="3" height="3" rx="0.5"></rect>
|
|
528
544
|
<polyline stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" points="2.65 9.5 3.5 10.5 5 8.5"></polyline>
|
|
529
|
-
</svg
|
|
545
|
+
</svg>`,Ie=`<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
546
|
+
<path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z" fill="none"></path>
|
|
547
|
+
<circle cx="12" cy="12" r="3" fill="none"></circle>
|
|
548
|
+
</svg>`;var K=class{constructor(e){this.editor=e,this.container=null,this.buttons={}}create(){this.container=document.createElement("div"),this.container.className="overtype-toolbar",this.container.setAttribute("role","toolbar"),this.container.setAttribute("aria-label","Text formatting"),[{name:"bold",icon:we,title:"Bold (Ctrl+B)",action:"toggleBold"},{name:"italic",icon:xe,title:"Italic (Ctrl+I)",action:"toggleItalic"},{separator:!0},{name:"h1",icon:Se,title:"Heading 1",action:"insertH1"},{name:"h2",icon:Le,title:"Heading 2",action:"insertH2"},{name:"h3",icon:Ce,title:"Heading 3",action:"insertH3"},{separator:!0},{name:"link",icon:Ee,title:"Insert Link (Ctrl+K)",action:"insertLink"},{name:"code",icon:Ae,title:"Code (Ctrl+`)",action:"toggleCode"},{separator:!0},{name:"quote",icon:Me,title:"Quote",action:"toggleQuote"},{separator:!0},{name:"bulletList",icon:Te,title:"Bullet List",action:"toggleBulletList"},{name:"orderedList",icon:He,title:"Numbered List",action:"toggleNumberedList"},{name:"taskList",icon:$e,title:"Task List",action:"toggleTaskList"},{separator:!0},{name:"togglePlain",icon:Ie,title:"Show plain textarea",action:"toggle-plain"}].forEach(i=>{if(i.separator){let r=document.createElement("div");r.className="overtype-toolbar-separator",r.setAttribute("role","separator"),this.container.appendChild(r)}else{let r=this.createButton(i);this.buttons[i.name]=r,this.container.appendChild(r)}});let t=this.editor.element.querySelector(".overtype-container"),o=this.editor.element.querySelector(".overtype-wrapper");return t&&o&&t.insertBefore(this.container,o),this.container}createButton(e){let t=document.createElement("button");return t.className="overtype-toolbar-button",t.type="button",t.title=e.title,t.setAttribute("aria-label",e.title),t.setAttribute("data-action",e.action),t.innerHTML=e.icon,t.addEventListener("click",o=>{o.preventDefault(),this.handleAction(e.action)}),t}async handleAction(e){let t=this.editor.textarea;if(t){t.focus();try{switch(e){case"toggleBold":V(t);break;case"toggleItalic":D(t);break;case"insertH1":he(t);break;case"insertH2":ue(t);break;case"insertH3":me(t);break;case"insertLink":q(t);break;case"toggleCode":ce(t);break;case"toggleBulletList":W(t);break;case"toggleNumberedList":U(t);break;case"toggleQuote":pe(t);break;case"toggleTaskList":de(t);break;case"toggle-plain":let o=this.editor.container.classList.contains("plain-mode");this.editor.showPlainTextarea(!o);break}t.dispatchEvent(new Event("input",{bubbles:!0}))}catch(o){console.error("Error loading markdown-actions:",o)}}}async updateButtonStates(){let e=this.editor.textarea;if(e)try{let t=fe(e);Object.entries(this.buttons).forEach(([o,i])=>{let r=!1;switch(o){case"bold":r=t.includes("bold");break;case"italic":r=t.includes("italic");break;case"code":r=!1;break;case"bulletList":r=t.includes("bullet-list");break;case"orderedList":r=t.includes("numbered-list");break;case"quote":r=t.includes("quote");break;case"taskList":r=t.includes("task-list");break;case"h1":r=t.includes("header");break;case"h2":r=t.includes("header-2");break;case"h3":r=t.includes("header-3");break;case"togglePlain":r=!this.editor.container.classList.contains("plain-mode");break}i.classList.toggle("active",r),i.setAttribute("aria-pressed",r.toString())})}catch(t){}}destroy(){this.container&&(this.container.remove(),this.container=null,this.buttons={})}};var Z=class{constructor(e){this.editor=e,this.tooltip=null,this.currentLink=null,this.hideTimeout=null,this.init()}init(){CSS.supports("position-anchor: --x")&&CSS.supports("position-area: center")&&(this.createTooltip(),this.editor.textarea.addEventListener("selectionchange",()=>this.checkCursorPosition()),this.editor.textarea.addEventListener("keyup",t=>{(t.key.includes("Arrow")||t.key==="Home"||t.key==="End")&&this.checkCursorPosition()}),this.editor.textarea.addEventListener("input",()=>this.hide()),this.editor.textarea.addEventListener("scroll",()=>this.hide()),this.tooltip.addEventListener("mouseenter",()=>this.cancelHide()),this.tooltip.addEventListener("mouseleave",()=>this.scheduleHide()))}createTooltip(){this.tooltip=document.createElement("div"),this.tooltip.className="overtype-link-tooltip";let e=document.createElement("style");e.textContent=`
|
|
530
549
|
@supports (position-anchor: --x) and (position-area: center) {
|
|
531
550
|
.overtype-link-tooltip {
|
|
532
551
|
position: absolute;
|
|
@@ -565,7 +584,7 @@ ${s}`:r;if(d){let x=n.value[n.selectionStart-1];n.selectionStart!==0&&x!=null&&!
|
|
|
565
584
|
</svg>
|
|
566
585
|
<span class="overtype-link-tooltip-url"></span>
|
|
567
586
|
</span>
|
|
568
|
-
`,this.tooltip.addEventListener("click",t=>{t.preventDefault(),t.stopPropagation(),this.currentLink&&(window.open(this.currentLink.url,"_blank"),this.hide())}),this.editor.container.appendChild(this.tooltip)}checkCursorPosition(){let e=this.editor.textarea.selectionStart,t=this.editor.textarea.value,o=this.findLinkAtPosition(t,e);o?(!this.currentLink||this.currentLink.url!==o.url||this.currentLink.index!==o.index)&&this.show(o):this.scheduleHide()}findLinkAtPosition(e,t){let o=/\[([^\]]+)\]\(([^)]+)\)/g,i,r=0;for(;(i=o.exec(e))!==null;){let a=i.index,s=i.index+i[0].length;if(t>=a&&t<=s)return{text:i[1],url:i[2],index:r,start:a,end:s};r++}return null}show(e){this.currentLink=e,this.cancelHide();let t=this.tooltip.querySelector(".overtype-link-tooltip-url");t.textContent=e.url,this.tooltip.style.setProperty("--target-anchor",`--link-${e.index}`),this.tooltip.classList.add("visible")}hide(){this.tooltip.classList.remove("visible"),this.currentLink=null}scheduleHide(){this.cancelHide(),this.hideTimeout=setTimeout(()=>this.hide(),300)}cancelHide(){this.hideTimeout&&(clearTimeout(this.hideTimeout),this.hideTimeout=null)}destroy(){this.cancelHide(),this.tooltip&&this.tooltip.parentNode&&this.tooltip.parentNode.removeChild(this.tooltip),this.tooltip=null,this.currentLink=null}};var k=class k{constructor(e,t={}){let o;if(typeof e=="string"){if(o=document.querySelectorAll(e),o.length===0)throw new Error(`No elements found for selector: ${e}`);o=Array.from(o)}else if(e instanceof Element)o=[e];else if(e instanceof NodeList)o=Array.from(e);else if(Array.isArray(e))o=e;else throw new Error("Invalid target: must be selector string, Element, NodeList, or Array");return o.map(r=>{if(r.overTypeInstance)return r.overTypeInstance.reinit(t),r.overTypeInstance;let a=Object.create(k.prototype);return a._init(r,t),r.overTypeInstance=a,k.instances.set(r,a),a})}_init(e,t={}){this.element=e,this.instanceTheme=t.theme||null,this.options=this._mergeOptions(t),this.instanceId=++k.instanceCount,this.initialized=!1,k.injectStyles(),k.initGlobalListeners();let o=e.querySelector(".overtype-container"),i=e.querySelector(".overtype-wrapper");o||i?this._recoverFromDOM(o,i):this._buildFromScratch(),this.shortcuts=new
|
|
587
|
+
`,this.tooltip.addEventListener("click",t=>{t.preventDefault(),t.stopPropagation(),this.currentLink&&(window.open(this.currentLink.url,"_blank"),this.hide())}),this.editor.container.appendChild(this.tooltip)}checkCursorPosition(){let e=this.editor.textarea.selectionStart,t=this.editor.textarea.value,o=this.findLinkAtPosition(t,e);o?(!this.currentLink||this.currentLink.url!==o.url||this.currentLink.index!==o.index)&&this.show(o):this.scheduleHide()}findLinkAtPosition(e,t){let o=/\[([^\]]+)\]\(([^)]+)\)/g,i,r=0;for(;(i=o.exec(e))!==null;){let a=i.index,s=i.index+i[0].length;if(t>=a&&t<=s)return{text:i[1],url:i[2],index:r,start:a,end:s};r++}return null}show(e){this.currentLink=e,this.cancelHide();let t=this.tooltip.querySelector(".overtype-link-tooltip-url");t.textContent=e.url,this.tooltip.style.setProperty("--target-anchor",`--link-${e.index}`),this.tooltip.classList.add("visible")}hide(){this.tooltip.classList.remove("visible"),this.currentLink=null}scheduleHide(){this.cancelHide(),this.hideTimeout=setTimeout(()=>this.hide(),300)}cancelHide(){this.hideTimeout&&(clearTimeout(this.hideTimeout),this.hideTimeout=null)}destroy(){this.cancelHide(),this.tooltip&&this.tooltip.parentNode&&this.tooltip.parentNode.removeChild(this.tooltip),this.tooltip=null,this.currentLink=null}};var k=class k{constructor(e,t={}){let o;if(typeof e=="string"){if(o=document.querySelectorAll(e),o.length===0)throw new Error(`No elements found for selector: ${e}`);o=Array.from(o)}else if(e instanceof Element)o=[e];else if(e instanceof NodeList)o=Array.from(e);else if(Array.isArray(e))o=e;else throw new Error("Invalid target: must be selector string, Element, NodeList, or Array");return o.map(r=>{if(r.overTypeInstance)return r.overTypeInstance.reinit(t),r.overTypeInstance;let a=Object.create(k.prototype);return a._init(r,t),r.overTypeInstance=a,k.instances.set(r,a),a})}_init(e,t={}){this.element=e,this.instanceTheme=t.theme||null,this.options=this._mergeOptions(t),this.instanceId=++k.instanceCount,this.initialized=!1,k.injectStyles(),k.initGlobalListeners();let o=e.querySelector(".overtype-container"),i=e.querySelector(".overtype-wrapper");o||i?this._recoverFromDOM(o,i):this._buildFromScratch(),this.shortcuts=new j(this),this.linkTooltip=new Z(this),this.options.toolbar&&(this.toolbar=new K(this),this.toolbar.create(),this.textarea.addEventListener("selectionchange",()=>{this.toolbar.updateButtonStates()}),this.textarea.addEventListener("input",()=>{this.toolbar.updateButtonStates()})),this.initialized=!0,this.options.onChange&&this.options.onChange(this.getValue(),this)}_mergeOptions(e){let t={fontSize:"14px",lineHeight:1.6,fontFamily:'"SF Mono", SFMono-Regular, Menlo, Monaco, "Cascadia Code", Consolas, "Roboto Mono", "Noto Sans Mono", "Droid Sans Mono", "Ubuntu Mono", "DejaVu Sans Mono", "Liberation Mono", "Courier New", Courier, monospace',padding:"16px",mobile:{fontSize:"16px",padding:"12px",lineHeight:1.5},textareaProps:{},autofocus:!1,autoResize:!1,minHeight:"100px",maxHeight:null,placeholder:"Start typing...",value:"",onChange:null,onKeydown:null,showActiveLineRaw:!1,showStats:!1,toolbar:!1,statsFormatter:null},{theme:o,colors:i,...r}=e;return{...t,...r}}_recoverFromDOM(e,t){if(e&&e.classList.contains("overtype-container"))this.container=e,this.wrapper=e.querySelector(".overtype-wrapper");else if(t){this.wrapper=t,this.container=document.createElement("div"),this.container.className="overtype-container";let o=this.instanceTheme||k.currentTheme||M,i=typeof o=="string"?o:o.name;if(i&&this.container.setAttribute("data-theme",i),this.instanceTheme){let r=typeof this.instanceTheme=="string"?B(this.instanceTheme):this.instanceTheme;if(r&&r.colors){let a=O(r.colors);this.container.style.cssText+=a}}t.parentNode.insertBefore(this.container,t),this.container.appendChild(t)}if(!this.wrapper){e&&e.remove(),t&&t.remove(),this._buildFromScratch();return}if(this.textarea=this.wrapper.querySelector(".overtype-input"),this.preview=this.wrapper.querySelector(".overtype-preview"),!this.textarea||!this.preview){this.container.remove(),this._buildFromScratch();return}this.wrapper._instance=this,this.options.fontSize&&this.wrapper.style.setProperty("--instance-font-size",this.options.fontSize),this.options.lineHeight&&this.wrapper.style.setProperty("--instance-line-height",String(this.options.lineHeight)),this.options.padding&&this.wrapper.style.setProperty("--instance-padding",this.options.padding),this._configureTextarea(),this._applyOptions()}_buildFromScratch(){let e=this._extractContent();this.element.innerHTML="",this._createDOM(),(e||this.options.value)&&this.setValue(e||this.options.value),this._applyOptions()}_extractContent(){let e=this.element.querySelector(".overtype-input");return e?e.value:this.element.textContent||""}_createDOM(){this.container=document.createElement("div"),this.container.className="overtype-container";let e=this.instanceTheme||k.currentTheme||M,t=typeof e=="string"?e:e.name;if(t&&this.container.setAttribute("data-theme",t),this.instanceTheme){let o=typeof this.instanceTheme=="string"?B(this.instanceTheme):this.instanceTheme;if(o&&o.colors){let i=O(o.colors);this.container.style.cssText+=i}}this.wrapper=document.createElement("div"),this.wrapper.className="overtype-wrapper",this.options.fontSize&&this.wrapper.style.setProperty("--instance-font-size",this.options.fontSize),this.options.lineHeight&&this.wrapper.style.setProperty("--instance-line-height",String(this.options.lineHeight)),this.options.padding&&this.wrapper.style.setProperty("--instance-padding",this.options.padding),this.wrapper._instance=this,this.textarea=document.createElement("textarea"),this.textarea.className="overtype-input",this.textarea.placeholder=this.options.placeholder,this._configureTextarea(),this.options.textareaProps&&Object.entries(this.options.textareaProps).forEach(([o,i])=>{o==="className"||o==="class"?this.textarea.className+=" "+i:o==="style"&&typeof i=="object"?Object.assign(this.textarea.style,i):this.textarea.setAttribute(o,i)}),this.preview=document.createElement("div"),this.preview.className="overtype-preview",this.preview.setAttribute("aria-hidden","true"),this.wrapper.appendChild(this.textarea),this.wrapper.appendChild(this.preview),this.container.appendChild(this.wrapper),this.options.showStats&&(this.statsBar=document.createElement("div"),this.statsBar.className="overtype-stats",this.container.appendChild(this.statsBar),this._updateStats()),this.element.appendChild(this.container),window.location.pathname.includes("demo.html")&&console.log("_createDOM completed:",{elementId:this.element.id,autoResize:this.options.autoResize,containerClasses:this.container.className,hasStats:!!this.statsBar,hasToolbar:this.options.toolbar}),this.options.autoResize?this._setupAutoResize():(this.container.classList.remove("overtype-auto-resize"),window.location.pathname.includes("demo.html")&&console.log("Removed auto-resize class from:",this.element.id))}_configureTextarea(){this.textarea.setAttribute("autocomplete","off"),this.textarea.setAttribute("autocorrect","off"),this.textarea.setAttribute("autocapitalize","off"),this.textarea.setAttribute("spellcheck","false"),this.textarea.setAttribute("data-gramm","false"),this.textarea.setAttribute("data-gramm_editor","false"),this.textarea.setAttribute("data-enable-grammarly","false")}_applyOptions(){this.options.autofocus&&this.textarea.focus(),this.options.autoResize?this.container.classList.contains("overtype-auto-resize")||this._setupAutoResize():this.container.classList.remove("overtype-auto-resize"),this.updatePreview()}updatePreview(){let e=this.textarea.value,t=this.textarea.selectionStart,o=this._getCurrentLine(e,t),i=I.parse(e,o,this.options.showActiveLineRaw);this.preview.innerHTML=i||'<span style="color: #808080;">Start typing...</span>',this._applyCodeBlockBackgrounds(),this.options.showStats&&this.statsBar&&this._updateStats(),this.options.onChange&&this.initialized&&this.options.onChange(e,this)}_applyCodeBlockBackgrounds(){let e=this.preview.querySelectorAll(".code-fence");for(let t=0;t<e.length-1;t+=2){let o=e[t],i=e[t+1],r=o.parentElement,a=i.parentElement;if(!r||!a)continue;o.style.display="block",i.style.display="block",r.classList.add("code-block-line"),a.classList.add("code-block-line");let s=r.nextElementSibling;for(;s&&s!==a;){if(s.tagName==="DIV"){s.classList.add("code-block-line");let l=s.textContent;s.textContent=l}if(s=s.nextElementSibling,!s)break}}}_getCurrentLine(e,t){return e.substring(0,t).split(`
|
|
569
588
|
`).length-1}handleInput(e){this.updatePreview()}handleKeydown(e){if(e.key==="Tab"){e.preventDefault();let o=this.textarea.selectionStart,i=this.textarea.selectionEnd,r=this.textarea.value;if(o!==i&&e.shiftKey){let a=r.substring(0,o),s=r.substring(o,i),l=r.substring(i),p=s.split(`
|
|
570
589
|
`).map(c=>c.replace(/^ /,"")).join(`
|
|
571
590
|
`);this.textarea.value=a+p+l,this.textarea.selectionStart=o,this.textarea.selectionEnd=o+p.length}else if(o!==i){let a=r.substring(0,o),s=r.substring(o,i),l=r.substring(i),p=s.split(`
|
|
@@ -578,7 +597,7 @@ ${s}`:r;if(d){let x=n.value[n.selectionStart-1];n.selectionStart!==0&&x!=null&&!
|
|
|
578
597
|
<span>${o} chars, ${i} words, ${t.length} lines</span>
|
|
579
598
|
</div>
|
|
580
599
|
<div class="overtype-stat">Line ${l}, Col ${d}</div>
|
|
581
|
-
`}_setupAutoResize(){this.container.classList.add("overtype-auto-resize"),this.previousHeight=null,this._updateAutoHeight(),this.textarea.addEventListener("input",()=>this._updateAutoHeight()),window.addEventListener("resize",()=>this._updateAutoHeight())}_updateAutoHeight(){if(!this.options.autoResize)return;let e=this.textarea,t=this.preview,o=this.wrapper,i=window.getComputedStyle(e),r=parseFloat(i.paddingTop),a=parseFloat(i.paddingBottom),s=e.scrollTop;e.style.setProperty("height","auto","important");let l=e.scrollHeight;if(this.options.minHeight){let c=parseInt(this.options.minHeight);l=Math.max(l,c)}let d="hidden";if(this.options.maxHeight){let c=parseInt(this.options.maxHeight);l>c&&(l=c,d="auto")}let p=l+"px";e.style.setProperty("height",p,"important"),e.style.setProperty("overflow-y",d,"important"),t.style.setProperty("height",p,"important"),t.style.setProperty("overflow-y",d,"important"),o.style.setProperty("height",p,"important"),e.scrollTop=s,t.scrollTop=s,this.previousHeight!==l&&(this.previousHeight=l)}showStats(e){this.options.showStats=e,e&&!this.statsBar?(this.statsBar=document.createElement("div"),this.statsBar.className="overtype-stats",this.container.appendChild(this.statsBar),this._updateStats()):!e&&this.statsBar&&(this.statsBar.remove(),this.statsBar=null)}destroy(){if(this.element.overTypeInstance=null,k.instances.delete(this.element),this.shortcuts&&this.shortcuts.destroy(),this.wrapper){let e=this.getValue();this.wrapper.remove(),this.element.textContent=e}this.initialized=!1}static init(e,t={}){return new k(e,t)}static getInstance(e){return e.overTypeInstance||k.instances.get(e)||null}static destroyAll(){document.querySelectorAll("[data-overtype-instance]").forEach(t=>{let o=k.getInstance(t);o&&o.destroy()})}static injectStyles(e=!1){if(k.stylesInjected&&!e)return;let t=document.querySelector("style.overtype-styles");t&&t.remove();let o=k.currentTheme
|
|
600
|
+
`}_setupAutoResize(){this.container.classList.add("overtype-auto-resize"),this.previousHeight=null,this._updateAutoHeight(),this.textarea.addEventListener("input",()=>this._updateAutoHeight()),window.addEventListener("resize",()=>this._updateAutoHeight())}_updateAutoHeight(){if(!this.options.autoResize)return;let e=this.textarea,t=this.preview,o=this.wrapper,i=window.getComputedStyle(e),r=parseFloat(i.paddingTop),a=parseFloat(i.paddingBottom),s=e.scrollTop;e.style.setProperty("height","auto","important");let l=e.scrollHeight;if(this.options.minHeight){let c=parseInt(this.options.minHeight);l=Math.max(l,c)}let d="hidden";if(this.options.maxHeight){let c=parseInt(this.options.maxHeight);l>c&&(l=c,d="auto")}let p=l+"px";e.style.setProperty("height",p,"important"),e.style.setProperty("overflow-y",d,"important"),t.style.setProperty("height",p,"important"),t.style.setProperty("overflow-y",d,"important"),o.style.setProperty("height",p,"important"),e.scrollTop=s,t.scrollTop=s,this.previousHeight!==l&&(this.previousHeight=l)}showStats(e){this.options.showStats=e,e&&!this.statsBar?(this.statsBar=document.createElement("div"),this.statsBar.className="overtype-stats",this.container.appendChild(this.statsBar),this._updateStats()):!e&&this.statsBar&&(this.statsBar.remove(),this.statsBar=null)}showPlainTextarea(e){if(e?this.container.classList.add("plain-mode"):this.container.classList.remove("plain-mode"),this.toolbar){let t=this.container.querySelector('[data-action="toggle-plain"]');t&&(t.classList.toggle("active",!e),t.title=e?"Show markdown preview":"Show plain textarea")}return e}destroy(){if(this.element.overTypeInstance=null,k.instances.delete(this.element),this.shortcuts&&this.shortcuts.destroy(),this.wrapper){let e=this.getValue();this.wrapper.remove(),this.element.textContent=e}this.initialized=!1}static init(e,t={}){return new k(e,t)}static getInstance(e){return e.overTypeInstance||k.instances.get(e)||null}static destroyAll(){document.querySelectorAll("[data-overtype-instance]").forEach(t=>{let o=k.getInstance(t);o&&o.destroy()})}static injectStyles(e=!1){if(k.stylesInjected&&!e)return;let t=document.querySelector("style.overtype-styles");t&&t.remove();let o=k.currentTheme||M,i=ke({theme:o}),r=document.createElement("style");r.className="overtype-styles",r.textContent=i,document.head.appendChild(r),k.stylesInjected=!0}static setTheme(e,t=null){let o=typeof e=="string"?B(e):e;t&&(o=be(o,t)),k.currentTheme=o,k.injectStyles(!0),document.querySelectorAll(".overtype-container").forEach(i=>{let r=typeof o=="string"?o:o.name;r&&i.setAttribute("data-theme",r)}),document.querySelectorAll(".overtype-wrapper").forEach(i=>{if(!i.closest(".overtype-container")){let a=typeof o=="string"?o:o.name;a&&i.setAttribute("data-theme",a)}let r=i._instance;r&&r.updatePreview()})}static initGlobalListeners(){k.globalListenersInitialized||(document.addEventListener("input",e=>{if(e.target&&e.target.classList&&e.target.classList.contains("overtype-input")){let t=e.target.closest(".overtype-wrapper"),o=t==null?void 0:t._instance;o&&o.handleInput(e)}}),document.addEventListener("keydown",e=>{if(e.target&&e.target.classList&&e.target.classList.contains("overtype-input")){let t=e.target.closest(".overtype-wrapper"),o=t==null?void 0:t._instance;o&&o.handleKeydown(e)}}),document.addEventListener("scroll",e=>{if(e.target&&e.target.classList&&e.target.classList.contains("overtype-input")){let t=e.target.closest(".overtype-wrapper"),o=t==null?void 0:t._instance;o&&o.handleScroll(e)}},!0),document.addEventListener("selectionchange",e=>{let t=document.activeElement;if(t&&t.classList.contains("overtype-input")){let o=t.closest(".overtype-wrapper"),i=o==null?void 0:o._instance;i&&(i.options.showStats&&i.statsBar&&i._updateStats(),clearTimeout(i._selectionTimeout),i._selectionTimeout=setTimeout(()=>{i.updatePreview()},50))}}),k.globalListenersInitialized=!0)}};$(k,"instances",new WeakMap),$(k,"stylesInjected",!1),$(k,"globalListenersInitialized",!1),$(k,"instanceCount",0);var A=k;A.MarkdownParser=I;A.ShortcutsManager=j;A.themes={solar:M,cave:B("cave")};A.getTheme=B;A.currentTheme=M;var Xe=A;return _e(Ye);})();
|
|
582
601
|
/**
|
|
583
602
|
* OverType - A lightweight markdown editor library with perfect WYSIWYG alignment
|
|
584
603
|
* @version 1.0.0
|
package/package.json
CHANGED
package/src/icons.js
CHANGED
|
@@ -70,4 +70,9 @@ export const taskListIcon = `<svg viewBox="0 0 18 18">
|
|
|
70
70
|
<rect stroke="currentColor" fill="none" stroke-width="1.5" x="2" y="3" width="3" height="3" rx="0.5"></rect>
|
|
71
71
|
<rect stroke="currentColor" fill="none" stroke-width="1.5" x="2" y="13" width="3" height="3" rx="0.5"></rect>
|
|
72
72
|
<polyline stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" points="2.65 9.5 3.5 10.5 5 8.5"></polyline>
|
|
73
|
+
</svg>`;
|
|
74
|
+
|
|
75
|
+
export const eyeIcon = `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
76
|
+
<path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z" fill="none"></path>
|
|
77
|
+
<circle cx="12" cy="12" r="3" fill="none"></circle>
|
|
73
78
|
</svg>`;
|
package/src/overtype.js
CHANGED
|
@@ -134,7 +134,8 @@ class OverType {
|
|
|
134
134
|
// Typography
|
|
135
135
|
fontSize: '14px',
|
|
136
136
|
lineHeight: 1.6,
|
|
137
|
-
|
|
137
|
+
/* System-first, guaranteed monospaced; avoids Android 'ui-monospace' pitfalls */
|
|
138
|
+
fontFamily: '"SF Mono", SFMono-Regular, Menlo, Monaco, "Cascadia Code", Consolas, "Roboto Mono", "Noto Sans Mono", "Droid Sans Mono", "Ubuntu Mono", "DejaVu Sans Mono", "Liberation Mono", "Courier New", Courier, monospace',
|
|
138
139
|
padding: '16px',
|
|
139
140
|
|
|
140
141
|
// Mobile styles
|
|
@@ -789,6 +790,33 @@ class OverType {
|
|
|
789
790
|
this.statsBar = null;
|
|
790
791
|
}
|
|
791
792
|
}
|
|
793
|
+
|
|
794
|
+
/**
|
|
795
|
+
* Show or hide the plain textarea (toggle overlay visibility)
|
|
796
|
+
* @param {boolean} show - true to show plain textarea (hide overlay), false to show overlay
|
|
797
|
+
* @returns {boolean} Current plain textarea state
|
|
798
|
+
*/
|
|
799
|
+
showPlainTextarea(show) {
|
|
800
|
+
if (show) {
|
|
801
|
+
// Show plain textarea mode (hide overlay)
|
|
802
|
+
this.container.classList.add('plain-mode');
|
|
803
|
+
} else {
|
|
804
|
+
// Show overlay mode (hide plain textarea text)
|
|
805
|
+
this.container.classList.remove('plain-mode');
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
// Update toolbar button if exists
|
|
809
|
+
if (this.toolbar) {
|
|
810
|
+
const toggleBtn = this.container.querySelector('[data-action="toggle-plain"]');
|
|
811
|
+
if (toggleBtn) {
|
|
812
|
+
// Button is active when showing overlay (not plain mode)
|
|
813
|
+
toggleBtn.classList.toggle('active', !show);
|
|
814
|
+
toggleBtn.title = show ? 'Show markdown preview' : 'Show plain textarea';
|
|
815
|
+
}
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
return show;
|
|
819
|
+
}
|
|
792
820
|
|
|
793
821
|
/**
|
|
794
822
|
* Destroy the editor instance
|
package/src/parser.js
CHANGED
|
@@ -157,6 +157,44 @@ export class MarkdownParser {
|
|
|
157
157
|
return html.replace(/(?<!`)(`+)(?!`)((?:(?!\1).)+?)(\1)(?!`)/g, '<code><span class="syntax-marker">$1</span>$2<span class="syntax-marker">$3</span></code>');
|
|
158
158
|
}
|
|
159
159
|
|
|
160
|
+
/**
|
|
161
|
+
* Sanitize URL to prevent XSS attacks
|
|
162
|
+
* @param {string} url - URL to sanitize
|
|
163
|
+
* @returns {string} Safe URL or '#' if dangerous
|
|
164
|
+
*/
|
|
165
|
+
static sanitizeUrl(url) {
|
|
166
|
+
// Trim whitespace and convert to lowercase for protocol check
|
|
167
|
+
const trimmed = url.trim();
|
|
168
|
+
const lower = trimmed.toLowerCase();
|
|
169
|
+
|
|
170
|
+
// Allow safe protocols
|
|
171
|
+
const safeProtocols = [
|
|
172
|
+
'http://',
|
|
173
|
+
'https://',
|
|
174
|
+
'mailto:',
|
|
175
|
+
'ftp://',
|
|
176
|
+
'ftps://'
|
|
177
|
+
];
|
|
178
|
+
|
|
179
|
+
// Check if URL starts with a safe protocol
|
|
180
|
+
const hasSafeProtocol = safeProtocols.some(protocol => lower.startsWith(protocol));
|
|
181
|
+
|
|
182
|
+
// Allow relative URLs (starting with / or # or no protocol)
|
|
183
|
+
const isRelative = trimmed.startsWith('/') ||
|
|
184
|
+
trimmed.startsWith('#') ||
|
|
185
|
+
trimmed.startsWith('?') ||
|
|
186
|
+
trimmed.startsWith('.') ||
|
|
187
|
+
(!trimmed.includes(':') && !trimmed.includes('//'));
|
|
188
|
+
|
|
189
|
+
// If safe protocol or relative URL, return as-is
|
|
190
|
+
if (hasSafeProtocol || isRelative) {
|
|
191
|
+
return url;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// Block dangerous protocols (javascript:, data:, vbscript:, etc.)
|
|
195
|
+
return '#';
|
|
196
|
+
}
|
|
197
|
+
|
|
160
198
|
/**
|
|
161
199
|
* Parse links
|
|
162
200
|
* @param {string} html - HTML with potential link markdown
|
|
@@ -165,8 +203,10 @@ export class MarkdownParser {
|
|
|
165
203
|
static parseLinks(html) {
|
|
166
204
|
return html.replace(/\[(.+?)\]\((.+?)\)/g, (match, text, url) => {
|
|
167
205
|
const anchorName = `--link-${this.linkIndex++}`;
|
|
206
|
+
// Sanitize URL to prevent XSS attacks
|
|
207
|
+
const safeUrl = this.sanitizeUrl(url);
|
|
168
208
|
// Don't double-escape - url is already escaped from parseLine
|
|
169
|
-
return `<a href="${
|
|
209
|
+
return `<a href="${safeUrl}" style="anchor-name: ${anchorName}"><span class="syntax-marker">[</span>${text}<span class="syntax-marker">](</span><span class="syntax-marker link-url">${url}</span><span class="syntax-marker">)</span></a>`;
|
|
170
210
|
});
|
|
171
211
|
}
|
|
172
212
|
|
package/src/styles.js
CHANGED
|
@@ -14,6 +14,7 @@ export function generateStyles(options = {}) {
|
|
|
14
14
|
const {
|
|
15
15
|
fontSize = '14px',
|
|
16
16
|
lineHeight = 1.6,
|
|
17
|
+
/* System-first, guaranteed monospaced; avoids Android 'ui-monospace' pitfalls */
|
|
17
18
|
fontFamily = '"SF Mono", SFMono-Regular, Menlo, Monaco, "Cascadia Code", Consolas, "Roboto Mono", "Noto Sans Mono", "Droid Sans Mono", "Ubuntu Mono", "DejaVu Sans Mono", "Liberation Mono", "Courier New", Courier, monospace',
|
|
18
19
|
padding = '20px',
|
|
19
20
|
theme = null,
|
|
@@ -84,7 +85,6 @@ export function generateStyles(options = {}) {
|
|
|
84
85
|
|
|
85
86
|
/* Font properties - any difference breaks alignment */
|
|
86
87
|
font-family: ${fontFamily} !important;
|
|
87
|
-
font-synthesis: none !important; /* no faux bold/italic width drift */
|
|
88
88
|
font-variant-ligatures: none !important; /* keep metrics stable for code */
|
|
89
89
|
font-size: var(--instance-font-size, ${fontSize}) !important;
|
|
90
90
|
line-height: var(--instance-line-height, ${lineHeight}) !important;
|
|
@@ -480,6 +480,23 @@ export function generateStyles(options = {}) {
|
|
|
480
480
|
margin: 0 2px;
|
|
481
481
|
}
|
|
482
482
|
}
|
|
483
|
+
|
|
484
|
+
/* Plain mode - hide preview and show textarea text */
|
|
485
|
+
.overtype-container.plain-mode .overtype-preview {
|
|
486
|
+
display: none !important;
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
.overtype-container.plain-mode .overtype-input {
|
|
490
|
+
color: var(--text, #0d3b66) !important;
|
|
491
|
+
/* Use system font stack for better plain text readability */
|
|
492
|
+
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
|
|
493
|
+
"Helvetica Neue", Arial, sans-serif !important;
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
/* Ensure textarea remains transparent in overlay mode */
|
|
497
|
+
.overtype-container:not(.plain-mode) .overtype-input {
|
|
498
|
+
color: transparent !important;
|
|
499
|
+
}
|
|
483
500
|
|
|
484
501
|
${mobileStyles}
|
|
485
502
|
`;
|
package/src/toolbar.js
CHANGED
|
@@ -39,7 +39,9 @@ export class Toolbar {
|
|
|
39
39
|
{ separator: true },
|
|
40
40
|
{ name: 'bulletList', icon: icons.bulletListIcon, title: 'Bullet List', action: 'toggleBulletList' },
|
|
41
41
|
{ name: 'orderedList', icon: icons.orderedListIcon, title: 'Numbered List', action: 'toggleNumberedList' },
|
|
42
|
-
{ name: 'taskList', icon: icons.taskListIcon, title: 'Task List', action: 'toggleTaskList' }
|
|
42
|
+
{ name: 'taskList', icon: icons.taskListIcon, title: 'Task List', action: 'toggleTaskList' },
|
|
43
|
+
{ separator: true },
|
|
44
|
+
{ name: 'togglePlain', icon: icons.eyeIcon, title: 'Show plain textarea', action: 'toggle-plain' }
|
|
43
45
|
];
|
|
44
46
|
|
|
45
47
|
// Create buttons
|
|
@@ -133,6 +135,11 @@ export class Toolbar {
|
|
|
133
135
|
case 'toggleTaskList':
|
|
134
136
|
markdownActions.toggleTaskList(textarea);
|
|
135
137
|
break;
|
|
138
|
+
case 'toggle-plain':
|
|
139
|
+
// Toggle between plain textarea and overlay mode
|
|
140
|
+
const isPlain = this.editor.container.classList.contains('plain-mode');
|
|
141
|
+
this.editor.showPlainTextarea(!isPlain);
|
|
142
|
+
break;
|
|
136
143
|
}
|
|
137
144
|
|
|
138
145
|
// Trigger input event to update preview
|
|
@@ -189,6 +196,10 @@ export class Toolbar {
|
|
|
189
196
|
case 'h3':
|
|
190
197
|
isActive = activeFormats.includes('header-3');
|
|
191
198
|
break;
|
|
199
|
+
case 'togglePlain':
|
|
200
|
+
// Button is active when in overlay mode (not plain mode)
|
|
201
|
+
isActive = !this.editor.container.classList.contains('plain-mode');
|
|
202
|
+
break;
|
|
192
203
|
}
|
|
193
204
|
|
|
194
205
|
button.classList.toggle('active', isActive);
|