DEV Community

Dev Nestio
Dev Nestio

Posted on

Build a Markdown to HTML Converter with Syntax Highlighting

A browser-only Markdown-to-HTML converter with live preview, syntax highlighting, and HTML sanitization.

Try it: https://devnestio.pages.dev/markdown-to-html/

Core parser

The key trick: protect code blocks before any inline processing.

function parseMarkdown(md) {
  const codeBlocks = [];
  // Protect fenced code blocks
  md = md.replace(/```
{% endraw %}
([\w]*)\n([\s\S]*?)
{% raw %}
```/gm, (_, lang, code) => {
    codeBlocks.push(`<pre><code class="language-${lang}">${esc(code)}</code></pre>`);
    return `\x00CODE${codeBlocks.length - 1}\x00`;
  });
  // ... process headings, tables, blockquotes, lists ...
  // Restore code blocks
  return html.replace(/\x00CODE(\d+)\x00/g, (_, i) => codeBlocks[+i]);
}
Enter fullscreen mode Exit fullscreen mode

Table support

const TABLE_RE = /^\|(.+)\|\s*\n\|[-| :]+\|\s*\n((?:\|.+\|\s*\n?)*)/gm;
Enter fullscreen mode Exit fullscreen mode

Inline formatting

function inlineFormat(text, esc) {
  if (esc) text = text.replace(/&/g,'&amp;').replace(/</g,'&lt;');
  text = text.replace(/\*\*\*(.+?)\*\*\*/g, '<strong><em>$1</em></strong>');
  text = text.replace(/\*\*(.+?)\*\*/g, '<strong>$1</strong>');
  text = text.replace(/\*(.+?)\*/g, '<em>$1</em>');
  text = text.replace(/~~(.+?)~~/g, '<del>$1</del>');
  return text;
}
Enter fullscreen mode Exit fullscreen mode

Features

  • Live preview and HTML source tabs
  • Fenced code blocks with language class
  • Tables, blockquotes, ordered/unordered lists
  • Bold, italic, strikethrough, links, images
  • HTML sanitize option
  • Download as full HTML document

DevNestio — browser-only developer tools.

Top comments (0)