LogIn
I don't have account.

Convert Markdown to HTML and HTML to Markdown

Janhavi Rajput

51 Views

Whether you're building a blog, content management system (CMS) or a documentation site, converting between Markdown and HTML is a common task in modern web development.

In this guide, we'll show you how to easily convert Markdown to HTML and HTML back to Markdown using JavaScript libraries like unified, remark, rehype, and turndown.

Why Convert Between Markdown and HTML?

  • Markdown to HTML: Needed for rendering Markdown content in browsers.

  • HTML to Markdown: Useful when editing previously rendered content or importing HTML from external sources.

Required Libraries

To perform these conversions, we'll use the following packages

Task Package
Parse Markdown remark-parse
Convert Markdown AST → HTML AST remark-rehype
Serialize HTML AST → HTML rehype-stringify
Convert HTML → Markdown turndown, turndown-plugin-gfm

Installation

Install all necessary dependencies using npm or yarn:

npm install unified remark-parse remark-rehype rehype-stringify turndown turndown-plugin-gfm

Or using yarn

yarn add unified remark-parse remark-rehype rehype-stringify turndown turndown-plugin-gfm

Setting Up the Markdown ↔ HTML Utility

Now let’s implement a simple yet powerful utility to convert Markdown to HTML and vice versa.


import { unified } from "unified";
import remarkParse from "remark-parse";
import remarkRehype from "remark-rehype";
import rehypeStringify from "rehype-stringify";
import TurndownService from "turndown";
import { gfm } from "turndown-plugin-gfm";

/**
 * Convert Markdown → HTML (synchronous)
 */
const markdownToHtml = (markdown) => {
  const file = unified()
    .use(remarkParse)
    .use(remarkRehype)
    .use(rehypeStringify)
    .processSync(markdown);
  return String(file);
};
/**
 * Convert HTML → Markdown
 */
const htmlToMarkdown = (html) => {
  const turndown = new TurndownService({
    headingStyle: "atx", // # Heading
    hr: "---", // Horizontal rule style
    codeBlockStyle: "fenced", // Use ```
    bulletListMarker: "-", // Bullet style
  });
  // Enable GitHub Flavored Markdown (tables, strikethrough, etc.)
  turndown.use(gfm);
  // Handle <pre><code class="language-xxx"> blocks
  turndown.addRule("fencedCodeBlock", {
    filter: (node) =>
      node.nodeName === "PRE" &&
      node.firstChild &&
      node.firstChild.nodeName === "CODE",
    replacement: (content, node) => {
      const className = node.firstChild.getAttribute("class") || "";
      const language = (className.match(/language-(\w+)/) || [])[1] || "";
      return `\n\n\`\`\`${language}\n${node.firstChild.textContent}\n\`\`\`\n\n`;
    },
  });
  return turndown.turndown(html);
};
export const MarkdownUtils = { markdownToHtml, htmlToMarkdown };

How It Works

1. Markdown → HTML

We use the Unified processor to create a pipeline:

  • remarkParse parses Markdown into an abstract syntax tree (AST).

  • remarkRehype converts the Markdown AST to a HTML AST.

  • rehypeStringify serializes the HTML AST to a string of HTML.

const html = markdownToHtml("# Hello World");
// Output: <h1>Hello World</h1>

2. HTML → Markdown

We use TurndownService, a powerful HTML-to-Markdown converter. To make it even better, we:

  • Enable GitHub Flavored Markdown via the gfm plugin.
  • Customize code block handling to preserve language syntax highlighting (like language-js).
const markdown = htmlToMarkdown("<h1>Hello</h1>");
// Output: "# Hello"

Example Usage


import { MarkdownUtils } from "./MarkdownUtils";

const md = `
# Sample Title
- List item
- Another item
\`\`\`js
console.log("Hello World");
\`\`\`
`;

const html = MarkdownUtils.markdownToHtml(md);
console.log("HTML Output:\n", html);

const markdownBack = MarkdownUtils.htmlToMarkdown(html);
console.log("Markdown Output:\n", markdownBack);

Use Cases

  • Markdown editors
  • Static site generators
  • Content migration tools
  • Developer blogs
  • Comment systems (e.g., GitHub-style)

Tips

  • Avoid XSS vulnerabilities: Sanitize HTML if you're converting user-generated Markdown.
  • Handle edge cases: Some complex HTML might not convert back to perfect Markdown test thoroughly.
  • Internationalization: Consider encoding and character set issues if working with multilingual content.