apps/web/src/lib/agendaEmail.ts
1/** Convert the server-built agenda's small Markdown subset to email-safe HTML. */
2const escapeHtml = (text: string) =>
3 text.replace(
4 /[&<>"']/g,
5 (char) =>
6 ({ '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' })[
7 char
8 ] || char,
9 )
10
11export function agendaEmailHtml(markdown: string): string {
12 const inline = (line: string) => {
13 let html = '',
14 end = 0
15 for (const match of line.matchAll(/\[([^\]]+)\]\(([^)]+)\)/g)) {
16 html += escapeHtml(line.slice(end, match.index))
17 let url: URL | undefined
18 try {
19 url = new URL(match[2], 'https://www.unleash.ai')
20 } catch {
21 /* Invalid links remain plain text. */
22 }
23 html +=
24 url && (url.protocol === 'https:' || url.protocol === 'http:')
25 ? `<a href="${escapeHtml(url.href)}">${escapeHtml(match[1])}</a>`
26 : escapeHtml(match[1])
27 end = match.index + match[0].length
28 }
29 return html + escapeHtml(line.slice(end))
30 }
31 return markdown
32 .split(/\n+/)
33 .filter((line) => line.trim())
34 .map((line) => `<p>${inline(line.replace(/^[-*] /, ''))}</p>`)
35 .join('\n')
36}
37