Redcarpet
| Language | Ruby (C extension) |
|---|---|
| License | MIT |
| Repository | github.com/vmg/redcarpet |
| Documentation | README |
| Depends on | a C compiler to build the gem |
| Read / write | parses Markdown (Sundown dialect) with optional extensions; renders HTML, TOC, plain text or custom output |
Redcarpet is a Ruby binding to a C Markdown parser derived from Sundown. It’s fast and its rendering is done by renderer classes you can subclass: override header, link, block_code and other callbacks to produce custom HTML or another format. Extensions are opt-in flags: tables, fenced code blocks, autolinks, strikethrough, superscript, underline, highlight, footnotes, quote and no-intra-emphasis.
It predates CommonMark and doesn’t follow it; edge cases render differently from GitHub. Releases are infrequent (3.6.1 in 2025), but it’s stable and widely deployed.
Installation#
gem install redcarpet
Basic usage: render Markdown to HTML#
require "redcarpet"
renderer = Redcarpet::Render::HTML.new(with_toc_data: true)
markdown = Redcarpet::Markdown.new(renderer,
tables: true,
fenced_code_blocks: true,
autolink: true,
strikethrough: true,
footnotes: true)
html = markdown.render(File.read("README.md", encoding: "UTF-8"))
File.write("README.html", html)
Create the Redcarpet::Markdown object once and reuse it.
How to render untrusted input#
renderer = Redcarpet::Render::HTML.new(
filter_html: true, # strip raw HTML
safe_links_only: true,
no_images: false,
link_attributes: { rel: "nofollow" })
html = Redcarpet::Markdown.new(renderer).render(user_input)
escape_html: true escapes raw HTML instead of removing it.
How to build a table of contents#
toc = Redcarpet::Markdown.new(Redcarpet::Render::HTML_TOC.new(nesting_level: 3))
puts toc.render(text) # nested <ul> with links to the heading ids
Render the document with Redcarpet::Render::HTML.new(with_toc_data: true) so headings get matching ids.
How to write a custom renderer#
class MyRenderer < Redcarpet::Render::HTML
def header(text, level)
%(<h#{level} class="title">#{text}</h#{level}>\n)
end
def block_code(code, language)
%(<pre data-lang="#{language}"><code>#{CGI.escapeHTML(code)}</code></pre>\n)
end
end
require "cgi"
html = Redcarpet::Markdown.new(MyRenderer, fenced_code_blocks: true).render(text)
How to strip Markdown to plain text#
require "redcarpet/render_strip"
plain = Redcarpet::Markdown.new(Redcarpet::Render::StripDown).render(text)
Tips#
hard_wrap: trueon the HTML renderer turns single newlines into<br>.no_intra_emphasis: truestopssnake_case_wordsfrom becoming italic.- For CommonMark or GFM compliance use commonmarker.