* Simple markdown to HTML converter * Supports: headers, bold, italic, code, links, lists, and paragraphs * @param {string} markdown - Markdown text to convert * @returns {string} HTML string with converted markdown
(markdown)
| 60 | * @returns {string} HTML string with converted markdown |
| 61 | */ |
| 62 | function markdownToHtml(markdown) { |
| 63 | if (!markdown) return ''; |
| 64 | |
| 65 | let html = markdown; |
| 66 | |
| 67 | // Convert headers (# ## ### etc.) |
| 68 | html = html.replace(/^### (.+)$/gm, '<h3>$1</h3>'); |
| 69 | html = html.replace(/^## (.+)$/gm, '<h2>$1</h2>'); |
| 70 | html = html.replace(/^# (.+)$/gm, '<h1>$1</h1>'); |
| 71 | |
| 72 | // Convert bold **text** and __text__ |
| 73 | html = html.replace(/\*\*(.+?)\*\*/g, '<strong>$1</strong>'); |
| 74 | html = html.replace(/__(.+?)__/g, '<strong>$1</strong>'); |
| 75 | |
| 76 | // Convert italic *text* and _text_ |
| 77 | html = html.replace(/\*(.+?)\*/g, '<em>$1</em>'); |
| 78 | html = html.replace(/_(.+?)_/g, '<em>$1</em>'); |
| 79 | |
| 80 | // Convert inline code `code` |
| 81 | html = html.replace(/`([^`]+)`/g, '<code>$1</code>'); |
| 82 | |
| 83 | // Convert code blocks ```code``` |
| 84 | html = html.replace(/```([^`]+)```/g, '<pre><code>$1</code></pre>'); |
| 85 | |
| 86 | // Convert links [text](url) |
| 87 | html = html.replace(/\[([^\]]+)\]\(([^)]+)\)/g, '<a href="$2" target="_blank">$1</a>'); |
| 88 | |
| 89 | // Convert unordered lists (- item or * item) |
| 90 | html = html.replace(/^[\-\*] (.+)$/gm, '<li>$1</li>'); |
| 91 | |
| 92 | // Convert ordered lists (1. item, 2. item, etc.) |
| 93 | html = html.replace(/^\d+\. (.+)$/gm, '<li class="ordered">$1</li>'); |
| 94 | |
| 95 | // Wrap consecutive <li> elements properly |
| 96 | html = html.replace( |
| 97 | /(<li(?:\s+class="ordered")?>.*?<\/li>(?:\s*<li(?:\s+class="ordered")?>.*?<\/li>)*)/gs, |
| 98 | (match) => { |
| 99 | if (match.includes('class="ordered"')) { |
| 100 | return `<ol>${match.replace(/\s+class="ordered"/g, '')}</ol>`; |
| 101 | } |
| 102 | return `<ul>${match}</ul>`; |
| 103 | }, |
| 104 | ); |
| 105 | |
| 106 | // Convert line breaks to paragraphs (double newlines become paragraph breaks) |
| 107 | const paragraphs = html.split(/\n\s*\n/); |
| 108 | html = paragraphs.map((p) => { |
| 109 | const trimmed = p.trim(); |
| 110 | if ( |
| 111 | trimmed && !trimmed.startsWith('<h') && !trimmed.startsWith('<ul') |
| 112 | && !trimmed.startsWith('<ol') && !trimmed.startsWith('<pre') |
| 113 | ) { |
| 114 | return `<p>${trimmed.replace(/\n/g, '<br>')}</p>`; |
| 115 | } |
| 116 | return trimmed; |
| 117 | }).join('\n'); |
| 118 | |
| 119 | return html; |
no test coverage detected