Skip to main content

toHtml(md, options?): string

Converts a Markdown string to an HTML string.

Import​

import { toHtml } from 'md-to-rich'
// or sub-path:
import { toHtml } from 'md-to-rich/html'

Signature​

function toHtml(md: string, options?: HtmlOptions): string

Options​

OptionTypeDefaultDescription
headingIdsbooleantrueInject slug-based id attributes on headings (collision-safe)
classNamesPartial<Record<HtmlElement, string>>{}Map of element name → CSS class string
renderImagesbooleantrueRender <img> tags; set to false to suppress all images
allowRawHtmlbooleanfalsePass raw HTML nodes from Markdown through to output
gfmbooleantrueEnable GitHub Flavored Markdown
remarkPluginsPlugin[][]Additional remark plugins applied before serialization

Examples​

Basic​

toHtml('# Hello\n\n**Bold** and *italic*.')
// → '<h1 id="hello">Hello</h1><p><strong>Bold</strong> and <em>italic</em>.</p>'

Custom class names​

toHtml('# Title\n\nParagraph.', {
classNames: {
h1: 'heading-xl',
p: 'prose text-base',
},
})
// → '<h1 id="title" class="heading-xl">Title</h1>
// <p class="prose text-base">Paragraph.</p>'

Disable heading IDs​

toHtml('# Title', { headingIds: false })
// → '<h1>Title</h1>'

Suppress images​

toHtml('![alt](https://example.com/img.png)', { renderImages: false })
// → '' (image element omitted)

GFM Features​

When gfm: true (the default), the following GitHub Flavored Markdown extensions are enabled:

FeatureMarkdownOutput
Tables| a | b |<table> with style="text-align:..." per column
Task lists- [x] done<input type="checkbox" disabled checked>
Strikethrough~~text~~<del>text</del>
Autolinkshttps://example.com<a href="...">
Footnotes (2.1.0+)text[^1] … [^1]: note<sup><a href="#fn-1">1</a></sup> and a closing <section class="footnotes"> with back-links

Reference-style links and images ([text][ref] with [ref]: url) resolve to normal links and images. Ordered lists keep their start number (<ol start="3">). Both need 2.1.0 or later.

URL Sanitisation​

URL sanitisation is always on regardless of options. Any href or src attribute containing a dangerous protocol is replaced with #.

See the Security page for the full list of blocked and allowed protocols.

allowRawHtml

Setting allowRawHtml: true passes raw HTML nodes from the Markdown source through to the output unchanged. This opens an XSS risk if the output is injected into a browser DOM.

Only enable this option when the Markdown source is fully trusted (e.g., stored in your own database, never user-supplied).

FAQ​

Is toHtml() safe for user-submitted Markdown?​

Yes, with the default options. toHtml() escapes all text, strips raw HTML such as <script> or <img onerror>, and replaces link and image URLs that use javascript:, data: or any scheme other than http, https and mailto with #. Keep allowRawHtml off for untrusted input; see Security.

How do I add syntax highlighting to code blocks?​

md-to-rich doesn't highlight code. toHtml() emits fenced code as <pre><code class="language-ts">…</code></pre> with the code HTML-escaped, which is the class convention Prism and highlight.js look for, so run one of them over the output in the browser or at build time.

Can I turn off GitHub Flavored Markdown in toHtml()?​

Yes: pass gfm: false and remark-gfm isn't loaded. Tables then render as plain paragraphs, - [x] stays literal text, ~~text~~ isn't struck through, and bare URLs aren't linked.

toHtml('~~old~~ https://example.com', { gfm: false })
// → '<p>~~old~~ https://example.com</p>'

How do I get heading IDs for a table of contents?​

toHtml() adds an id to every heading by default (headingIds: true): the heading text is lowercased, characters other than ASCII letters, digits, spaces, hyphens and underscores are removed, spaces and underscores become hyphens, and repeats get -1, -2 suffixes. Read them back from the output to build a table of contents:

const html = toHtml('# Guide\n\n## Install\n\n## Usage')
const toc = [...html.matchAll(/<h([1-6]) id="([^"]*)"[^>]*>(.*?)<\/h\1>/g)].map(
([, depth, id, inner]) => ({ depth: Number(depth), id, text: inner.replace(/<[^>]+>/g, '') }),
)
// → [{ depth: 1, id: 'guide', text: 'Guide' }, { depth: 2, id: 'install', ... }, ...]