| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| |
|
|
| export function escapeHtml(str) { |
| return String(str) |
| .replace(/&/g, '&') |
| .replace(/</g, '<') |
| .replace(/>/g, '>') |
| .replace(/"/g, '"'); |
| } |
|
|
| |
|
|
| |
| export function renderEmailInline(text) { |
| let out = text; |
| |
| out = out.replace(/\*\*(.+?)\*\*/g, '<strong style="color:#fff;">$1</strong>'); |
| out = out.replace(/__(.+?)__/g, '<strong style="color:#fff;">$1</strong>'); |
| |
| out = out.replace(/(?<!\*)\*([^*\n]+?)\*(?!\*)/g, '<em>$1</em>'); |
| |
| out = out.replace( |
| /^([A-Z][A-Za-z ]+): */, |
| '<strong style="color:#4ade80;font-size:12px;text-transform:uppercase;letter-spacing:0.5px;">$1:</strong> ', |
| ); |
| return out; |
| } |
|
|
| |
| |
| |
| export function markdownToEmailHtml(md) { |
| const escaped = escapeHtml(md); |
| const lines = escaped.split('\n'); |
|
|
| |
| const blocks = []; |
| let current = null; |
| const flush = () => { if (current) { blocks.push(current); current = null; } }; |
|
|
| for (const line of lines) { |
| const trimmed = line.trim(); |
| if (!trimmed) { flush(); continue; } |
|
|
| const bullet = line.match(/^\s*[*-]\s+(.+)$/); |
| if (bullet) { |
| if (!current || current.type !== 'ul') { flush(); current = { type: 'ul', items: [] }; } |
| current.items.push(bullet[1]); |
| } else { |
| if (!current || current.type !== 'p') { flush(); current = { type: 'p', items: [] }; } |
| current.items.push(trimmed); |
| } |
| } |
| flush(); |
|
|
| return blocks.map((block) => { |
| if (block.type === 'ul') { |
| const items = block.items |
| .map((item) => `<li style="margin-bottom:6px;">${renderEmailInline(item)}</li>`) |
| .join(''); |
| return `<ul style="margin:12px 0;padding-left:20px;list-style:disc;">${items}</ul>`; |
| } |
| const joined = block.items.map(renderEmailInline).join('<br/>'); |
| return `<p style="margin:0 0 12px;">${joined}</p>`; |
| }).join(''); |
| } |
|
|
| |
| |
| |
|
|
| export function escapeTelegramHtml(str) { |
| return String(str) |
| .replace(/&/g, '&') |
| .replace(/</g, '<') |
| .replace(/>/g, '>'); |
| } |
|
|
| export function markdownToTelegramHtml(md) { |
| let html = escapeTelegramHtml(md); |
| |
| html = html.replace(/^[*-]\s+/gm, 'β’ '); |
| |
| html = html.replace(/\*\*(.+?)\*\*/g, '<b>$1</b>'); |
| html = html.replace(/__(.+?)__/g, '<b>$1</b>'); |
| |
| html = html.replace(/(?<!\*)\*([^*\n]+?)\*(?!\*)/g, '<i>$1</i>'); |
| |
| html = html.replace(/^([A-Z][A-Za-z ]+): */gm, '<b>$1:</b> '); |
| return html; |
| } |
|
|
| |
| |
|
|
| export function escapeSlackMrkdwn(str) { |
| return String(str) |
| .replace(/&/g, '&') |
| .replace(/</g, '<') |
| .replace(/>/g, '>'); |
| } |
|
|
| export function markdownToSlackMrkdwn(md) { |
| let txt = escapeSlackMrkdwn(md); |
| |
| txt = txt.replace(/^[*-]\s+/gm, 'β’ '); |
| |
| |
| txt = txt.replace(/\*\*(.+?)\*\*/g, '\u0001$1\u0001'); |
| txt = txt.replace(/__(.+?)__/g, '\u0001$1\u0001'); |
| |
| txt = txt.replace(/(?<!\*)\*([^*\n]+?)\*(?!\*)/g, '_$1_'); |
| |
| txt = txt.replace(/\u0001/g, '*'); |
| |
| txt = txt.replace(/^([A-Z][A-Za-z ]+): */gm, '*$1:* '); |
| return txt; |
| } |
|
|
| |
| |
| |
|
|
| export function markdownToDiscord(md) { |
| let txt = String(md); |
| txt = txt.replace(/^\*\s+/gm, '- '); |
| txt = txt.replace(/^([A-Z][A-Za-z ]+): */gm, '**$1:** '); |
| return txt; |
| } |
|
|