overtype 1.1.5 → 1.1.6

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.
@@ -1,11 +1,11 @@
1
1
  /**
2
- * OverType v1.1.4
2
+ * OverType v1.1.6
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 P=Object.defineProperty;var Ie=Object.getOwnPropertyDescriptor;var Be=Object.getOwnPropertyNames;var je=Object.prototype.hasOwnProperty;var Oe=(n,e,t)=>e in n?P(n,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):n[e]=t;var Ne=(n,e)=>{for(var t in e)P(n,t,{get:e[t],enumerable:!0})},Pe=(n,e,t,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of Be(e))!je.call(n,i)&&i!==t&&P(n,i,{get:()=>e[i],enumerable:!(o=Ie(e,i))||o.enumerable});return n};var ze=n=>Pe(P({},"__esModule",{value:!0}),n);var M=(n,e,t)=>(Oe(n,typeof e!="symbol"?e+"":e,t),t);var Xe={};Ne(Xe,{OverType:()=>A,default:()=>Ge});var I=class{static resetLinkIndex(){this.linkIndex=0}static escapeHtml(e){let t={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"};return e.replace(/[&<>"']/g,o=>t[o])}static preserveIndentation(e,t){let i=t.match(/^(\s*)/)[1].replace(/ /g,"&nbsp;");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(/^&gt; (.+)$/,(t,o)=>`<span class="blockquote"><span class="syntax-marker">&gt;</span> ${o}</span>`)}static parseBulletList(e){return e.replace(/^((?:&nbsp;)*)([-*])\s(.+)$/,(t,o,i,r)=>`${o}<span class="syntax-marker">${i}</span> ${r}`)}static parseNumberedList(e){return e.replace(/^((?:&nbsp;)*)(\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 parseLinks(e){return e.replace(/\[(.+?)\]\((.+?)\)/g,(t,o,i)=>{let r=`--link-${this.linkIndex++}`;return`<a href="${i}" style="anchor-name: ${r}"><span class="syntax-marker">[</span>${o}<span class="syntax-marker">](</span><span class="syntax-marker">${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=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>&nbsp;</div>":`<div>${t}</div>`)}static parse(e,t=-1,o=!1){return this.resetLinkIndex(),e.split(`
8
+ var OverType=(()=>{var P=Object.defineProperty;var Ie=Object.getOwnPropertyDescriptor;var Be=Object.getOwnPropertyNames;var je=Object.prototype.hasOwnProperty;var Oe=(n,e,t)=>e in n?P(n,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):n[e]=t;var Ne=(n,e)=>{for(var t in e)P(n,t,{get:e[t],enumerable:!0})},Pe=(n,e,t,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of Be(e))!je.call(n,i)&&i!==t&&P(n,i,{get:()=>e[i],enumerable:!(o=Ie(e,i))||o.enumerable});return n};var ze=n=>Pe(P({},"__esModule",{value:!0}),n);var M=(n,e,t)=>(Oe(n,typeof e!="symbol"?e+"":e,t),t);var Xe={};Ne(Xe,{OverType:()=>A,default:()=>Ge});var I=class{static resetLinkIndex(){this.linkIndex=0}static escapeHtml(e){let t={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"};return e.replace(/[&<>"']/g,o=>t[o])}static preserveIndentation(e,t){let i=t.match(/^(\s*)/)[1].replace(/ /g,"&nbsp;");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(/^&gt; (.+)$/,(t,o)=>`<span class="blockquote"><span class="syntax-marker">&gt;</span> ${o}</span>`)}static parseBulletList(e){return e.replace(/^((?:&nbsp;)*)([-*])\s(.+)$/,(t,o,i,r)=>`${o}<span class="syntax-marker">${i}</span> ${r}`)}static parseNumberedList(e){return e.replace(/^((?:&nbsp;)*)(\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 parseLinks(e){return e.replace(/\[(.+?)\]\((.+?)\)/g,(t,o,i)=>{let r=`--link-${this.linkIndex++}`;return`<a href="${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>&nbsp;</div>":`<div>${t}</div>`)}static parse(e,t=-1,o=!1){return this.resetLinkIndex(),e.split(`
9
9
  `).map((a,s)=>o&&s===t?`<div class="raw-line">${this.escapeHtml(a)||"&nbsp;"}</div>`:this.parseLine(a)).join("")}};M(I,"linkIndex",0);var _e=Object.defineProperty,Y=Object.getOwnPropertySymbols,Fe=Object.prototype.hasOwnProperty,Re=Object.prototype.propertyIsEnumerable,ee=(n,e,t)=>e in n?_e(n,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):n[e]=t,te=(n,e)=>{for(var t in e||(e={}))Fe.call(e,t)&&ee(n,t,e[t]);if(Y)for(var t of Y(e))Re.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 Ve(){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({},Ve()),n)}var _=!1;function De(){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=De();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
11
  `).length>1}function qe(n,e){let t=e;for(;n[t]&&n[t-1]!=null&&!n[t-1].match(/\s/);)t--;return t}function We(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(`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "overtype",
3
- "version": "1.1.5",
3
+ "version": "1.1.6",
4
4
  "description": "A lightweight markdown editor library with perfect WYSIWYG alignment using an invisible textarea overlay",
5
5
  "main": "dist/overtype.js",
6
6
  "module": "dist/overtype.esm.js",
package/src/parser.js CHANGED
@@ -165,7 +165,8 @@ export class MarkdownParser {
165
165
  static parseLinks(html) {
166
166
  return html.replace(/\[(.+?)\]\((.+?)\)/g, (match, text, url) => {
167
167
  const anchorName = `--link-${this.linkIndex++}`;
168
- return `<a href="${url}" style="anchor-name: ${anchorName}"><span class="syntax-marker">[</span>${text}<span class="syntax-marker">](</span><span class="syntax-marker">${url}</span><span class="syntax-marker">)</span></a>`;
168
+ // Don't double-escape - url is already escaped from parseLine
169
+ return `<a href="${url}" 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>`;
169
170
  });
170
171
  }
171
172
 
@@ -176,30 +177,44 @@ export class MarkdownParser {
176
177
  */
177
178
  static parseInlineElements(text) {
178
179
  let html = text;
179
- // Order matters: parse code first to avoid conflicts
180
+ // Order matters: parse code first
180
181
  html = this.parseInlineCode(html);
182
+
181
183
  // Use placeholders to protect inline code while preserving formatting spans
182
184
  // We use Unicode Private Use Area (U+E000-U+F8FF) as placeholders because:
183
185
  // 1. These characters are reserved for application-specific use
184
186
  // 2. They'll never appear in user text
185
187
  // 3. They maintain single-character width (important for alignment)
186
188
  // 4. They're invisible if accidentally rendered
187
- // This allows formatting like *text `code` text* to span across code blocks
188
- // while preventing formatting inside code like `__init__` from being bolded
189
- const codeBlocks = new Map();
189
+ const sanctuaries = new Map();
190
+
191
+ // Protect code blocks
190
192
  html = html.replace(/(<code>.*?<\/code>)/g, (match) => {
191
- const placeholder = `\uE000${codeBlocks.size}\uE001`;
192
- codeBlocks.set(placeholder, match);
193
+ const placeholder = `\uE000${sanctuaries.size}\uE001`;
194
+ sanctuaries.set(placeholder, match);
193
195
  return placeholder;
194
196
  });
195
- // Process other inline elements on text with placeholders
197
+
198
+ // Parse links AFTER protecting code but BEFORE bold/italic
199
+ // This ensures link URLs don't get processed as markdown
196
200
  html = this.parseLinks(html);
201
+
202
+ // Protect entire link elements (not just the URL part)
203
+ html = html.replace(/(<a[^>]*>.*?<\/a>)/g, (match) => {
204
+ const placeholder = `\uE000${sanctuaries.size}\uE001`;
205
+ sanctuaries.set(placeholder, match);
206
+ return placeholder;
207
+ });
208
+
209
+ // Process other inline elements on text with placeholders
197
210
  html = this.parseBold(html);
198
211
  html = this.parseItalic(html);
199
- // Restore code blocks
200
- codeBlocks.forEach((codeBlock, placeholder) => {
201
- html = html.replace(placeholder, codeBlock);
212
+
213
+ // Restore all sanctuaries
214
+ sanctuaries.forEach((content, placeholder) => {
215
+ html = html.replace(placeholder, content);
202
216
  });
217
+
203
218
  return html;
204
219
  }
205
220