/** * Markdown & Branded HTML Formatting Utilities for PostFundManagement (PFM) */ export function isHtmlContent(content: string): boolean { if (!content) return false; const trimmed = content.trim(); return ( trimmed.startsWith('')) || /<(strong|b|em|i|u|h[1-6]|ul|ol|li|table|blockquote|div|p|img|hr|br)\b/i.test(trimmed) ); } export function stripMarkdown(text: string): string { if (!text) return ''; return text .replace(/<[^>]*>/g, ' ') .replace(/!\[.*?\]\(.*?\)/g, '') .replace(/\[(.*?)\]\(.*?\)/g, '$1') .replace(/#{1,6}\s+/g, '') .replace(/(\*\*|__)(.*?)\1/g, '$2') .replace(/(\*|_)(.*?)\1/g, '$2') .replace(/~~(.*?)~~/g, '$1') .replace(/`{1,3}.*?`{1,3}/gs, '') .replace(/^>\s+/gm, '') .replace(/^[-*+]\s+/gm, '') .replace(/^\d+\.\s+/gm, '') .replace(/\|/g, ' ') .replace(/\s+/g, ' ') .trim(); } export function parseMarkdownToHtml(markdown: string): string { if (!markdown) return ''; let html = markdown .replace(/)<[^<]*)*<\/script>/gi, '') .replace(/\r\n/g, '\n'); html = html.replace(/```([a-zA-Z0-9_-]*)\n([\s\S]*?)```/g, (_match, _lang, code) => { const escaped = code .replace(/&/g, '&') .replace(//g, '>'); return `
${escaped}
`; }); html = html.replace(/`([^`]+)`/g, (_match, code) => { const escaped = code .replace(/&/g, '&') .replace(//g, '>'); return `${escaped}`; }); html = html.replace(/^#### (.*?)$/gm, '

$1

'); html = html.replace(/^### (.*?)$/gm, '

$1

'); html = html.replace(/^## (.*?)$/gm, '

$1

'); html = html.replace(/^# (.*?)$/gm, '

$1

'); html = html.replace(/\*\*\*(.*?)\*\*\*/g, '$1'); html = html.replace(/\*\*(.*?)\*\*/g, '$1'); html = html.replace(/__(.*?)__/g, '$1'); html = html.replace(/\*(.*?)\*/g, '$1'); html = html.replace(/\[(.*?)\]\((.*?)\)/g, '$1'); html = html.replace(/^[-*+]\s+(.*?)$/gm, '
  • $1
  • '); html = html.replace(/^\d+\.\s+(.*?)$/gm, '
  • $1
  • '); const paragraphs = html.split(/\n{2,}/); html = paragraphs .map((p) => { const trimmed = p.trim(); if (!trimmed) return ''; if ( trimmed.startsWith('${trimmed.replace(/\n/g, '
    ')}

    `; }) .join('\n'); return html; }