diff --git a/static/ui.js b/static/ui.js index 33cc417..00926b2 100644 --- a/static/ui.js +++ b/static/ui.js @@ -477,9 +477,14 @@ function renderMd(raw){ t=t.replace(/<\/?[a-z][^>]*>/gi,tag=>SAFE_INLINE.test(tag)?tag:esc(tag)); return t; } + // Stash tags from the backtick pass above so the outer bold/italic + // regexes don't esc() their content (e.g. **`code`** → code) + const _ob_stash=[]; + s=s.replace(/([^<]*<\/code>)/g,m=>{_ob_stash.push(m);return `\x00O${_ob_stash.length-1}\x00`;}); s=s.replace(/\*\*\*(.+?)\*\*\*/g,(_,t)=>`${esc(t)}`); s=s.replace(/\*\*(.+?)\*\*/g,(_,t)=>`${esc(t)}`); s=s.replace(/\*([^*\n]+)\*/g,(_,t)=>`${esc(t)}`); + s=s.replace(/\x00O(\d+)\x00/g,(_,i)=>_ob_stash[+i]); s=s.replace(/^### (.+)$/gm,(_,t)=>`

${inlineMd(t)}

`).replace(/^## (.+)$/gm,(_,t)=>`

${inlineMd(t)}

`).replace(/^# (.+)$/gm,(_,t)=>`

${inlineMd(t)}

`); s=s.replace(/^---+$/gm,'
'); s=s.replace(/^> (.+)$/gm,(_,t)=>`
${inlineMd(t)}
`); @@ -504,12 +509,9 @@ function renderMd(raw){ } return html+''; }); - // Stash existing tags so the autolink pass below does not re-link their href= URLs - const _a_stash=[]; - s=s.replace(/(]*>[\s\S]*?<\/a>)/g,m=>{_a_stash.push(m);return `\x00A${_a_stash.length-1}\x00`;}); - s=s.replace(/\[([^\]]+)\]\((https?:\/\/[^\)]+)\)/g,(_,label,url)=>`${esc(label)}`); - s=s.replace(/\x00A(\d+)\x00/g,(_,i)=>_a_stash[+i]); // Tables: | col | col | header row followed by | --- | --- | separator then data rows + // NOTE: table pass runs BEFORE outer link pass so [label](url) in table cells + // is handled by inlineMd() only — prevents double-linking. s=s.replace(/((?:^\|.+\|\n?)+)/gm,block=>{ const rows=block.trim().split('\n').filter(r=>r.trim()); if(rows.length<2)return block; @@ -521,6 +523,13 @@ function renderMd(raw){ const body=rows.slice(2).map(r=>`${parseRow(r)}`).join(''); return `${header}${body}
`; }); + // Outer link pass for labeled links in plain paragraphs (outside table cells). + // Runs AFTER the table pass so table cells are processed by inlineMd() only. + // Stash existing tags first to avoid re-linking already-linked URLs. + const _a_stash=[]; + s=s.replace(/(]*>[\s\S]*?<\/a>)/g,m=>{_a_stash.push(m);return `\x00A${_a_stash.length-1}\x00`;}); + s=s.replace(/\[([^\]]+)\]\((https?:\/\/[^\)]+)\)/g,(_,label,url)=>`${esc(label)}`); + s=s.replace(/\x00A(\d+)\x00/g,(_,i)=>_a_stash[+i]); // Escape any remaining HTML tags that are NOT from our own markdown output. // Our pipeline only emits: ,,,
,,
    ,
      ,
    1. , // ,,,,
      ,,
      ,
      ,

      ,
      ,,