Advertisement
Markdown Editor
1
0 words, 0 characters
Preview
HTML Input
Markdown Output
Markdown Input
HTML Output

How to Use

  1. Type or paste Markdown in the editor. The preview updates in real time.
  2. Use the toolbar buttons to insert common Markdown syntax (bold, links, tables, etc.).
  3. Switch to "HTML to Markdown" tab to convert HTML code into Markdown format.
  4. Switch to "Markdown to HTML" tab to get the raw HTML output of your Markdown.
  5. Copy results to clipboard or export as an HTML file.

Frequently Asked Questions

What Markdown syntax is supported?
We support standard Markdown plus GFM extensions: headings, bold, italic, strikethrough, links, images, lists, task lists, blockquotes, code blocks, tables, and horizontal rules.
Is my data safe?
Yes. All processing happens entirely in your browser. No data is uploaded to any server. Your content stays on your device.
Can I export the preview as HTML?
Yes. Click the "Export" button to download a complete HTML file with your rendered Markdown content. You can also copy the raw HTML from the "Markdown to HTML" tab.
Does it support tables and task lists?
Yes. GFM (GitHub Flavored Markdown) tables and task lists with checkboxes are fully supported in the editor and preview.
How does HTML to Markdown conversion work?
The converter parses your HTML and maps common elements (headings, paragraphs, lists, links, images, tables, code blocks) to their Markdown equivalents. It handles most standard HTML structures.
Advertisement
Copied!
\n\n\nMarkdown Export\n\n\n\n' + content + '\n\n'; const blob = new Blob([fullHtml], { type: 'text/html' }); const a = document.createElement('a'); a.href = URL.createObjectURL(blob); a.download = 'markdown-export.html'; a.click(); URL.revokeObjectURL(a.href); showToast(i18n[currentLang].toastExported); } // ============ Tab 2: HTML to Markdown ============ function convertHtmlToMd() { const html = document.getElementById('htmlInput').value.trim(); if (!html) { showToast(i18n[currentLang].errorEmpty); return; } const md = htmlToMd(html); document.getElementById('mdOutput').value = md; showToast(i18n[currentLang].toastConverted); } function htmlToMd(html) { const div = document.createElement('div'); div.innerHTML = html; return nodeToMd(div).trim(); } function nodeToMd(node) { let result = ''; node.childNodes.forEach(child => { if (child.nodeType === 3) { result += child.textContent; return; } if (child.nodeType !== 1) return; const tag = child.tagName.toLowerCase(); const inner = nodeToMd(child); switch (tag) { case 'h1': result += '# ' + inner.trim() + '\n\n'; break; case 'h2': result += '## ' + inner.trim() + '\n\n'; break; case 'h3': result += '### ' + inner.trim() + '\n\n'; break; case 'h4': result += '#### ' + inner.trim() + '\n\n'; break; case 'h5': result += '##### ' + inner.trim() + '\n\n'; break; case 'h6': result += '###### ' + inner.trim() + '\n\n'; break; case 'p': result += inner.trim() + '\n\n'; break; case 'strong': case 'b': result += '**' + inner + '**'; break; case 'em': case 'i': result += '*' + inner + '*'; break; case 'del': case 's': result += '~~' + inner + '~~'; break; case 'a': { const href = child.getAttribute('href') || ''; result += '[' + inner + '](' + href + ')'; break; } case 'img': { const src = child.getAttribute('src') || ''; const alt = child.getAttribute('alt') || ''; result += '![' + alt + '](' + src + ')'; break; } case 'ul': { child.querySelectorAll(':scope > li').forEach(li => { result += '- ' + nodeToMd(li).trim() + '\n'; }); result += '\n'; break; } case 'ol': { let idx = 1; child.querySelectorAll(':scope > li').forEach(li => { result += idx + '. ' + nodeToMd(li).trim() + '\n'; idx++; }); result += '\n'; break; } case 'li': result += inner; break; case 'blockquote': { const bqLines = inner.trim().split('\n'); result += bqLines.map(l => '> ' + l).join('\n') + '\n\n'; break; } case 'code': { if (child.parentElement && child.parentElement.tagName.toLowerCase() === 'pre') { result += inner; } else { result += '`' + inner + '`'; } break; } case 'pre': { result += '```\n' + inner.trim() + '\n```\n\n'; break; } case 'hr': result += '---\n\n'; break; case 'br': result += '\n'; break; case 'table': { const thead = child.querySelector('thead'); const tbody = child.querySelector('tbody') || child; let headerRow = null; if (thead) { const tr = thead.querySelector('tr'); if (tr) headerRow = Array.from(tr.querySelectorAll('th,td')).map(c => nodeToMd(c).trim()); } const bodyRows = Array.from((tbody.tagName.toLowerCase() === 'tbody' ? tbody : child).querySelectorAll('tbody > tr, :scope > tr')).filter(tr => !thead || !thead.contains(tr)); if (!headerRow && bodyRows.length > 0) { const firstRow = bodyRows.shift(); headerRow = Array.from(firstRow.querySelectorAll('th,td')).map(c => nodeToMd(c).trim()); } if (headerRow) { result += '| ' + headerRow.join(' | ') + ' |\n'; result += '| ' + headerRow.map(() => '---').join(' | ') + ' |\n'; bodyRows.forEach(tr => { const cells = Array.from(tr.querySelectorAll('td,th')).map(c => nodeToMd(c).trim()); result += '| ' + cells.join(' | ') + ' |\n'; }); result += '\n'; } break; } case 'div': case 'span': case 'section': case 'article': result += inner; break; default: result += inner; } }); return result; } // ============ Tab 3: Markdown to HTML ============ function convertMdToHtml() { const md = document.getElementById('mdConvertInput').value.trim(); if (!md) { showToast(i18n[currentLang].errorEmpty); return; } const html = parseMd(md); document.getElementById('htmlOutput').value = formatHtmlOutput(html); showToast(i18n[currentLang].toastConverted); } function formatHtmlOutput(html) { // Simple indentation for readability let formatted = html; let indent = 0; const lines = formatted.split('\n').filter(l => l.trim()); const result = []; lines.forEach(line => { const trimmed = line.trim(); if (/^<\/(h[1-6]|p|ul|ol|li|blockquote|pre|table|thead|tbody|tr|div)>/.test(trimmed)) indent = Math.max(0, indent - 1); result.push(' '.repeat(indent) + trimmed); if (/^<(ul|ol|blockquote|table|thead|tbody|tr)(\s|>)/.test(trimmed) && !/\/>$/.test(trimmed) && !/<\//.test(trimmed)) indent++; }); return result.join('\n'); } // ============ Init ============ updateLineNumbers(); updateWordCount();