Open-source project
davidfstr/rdiscount avatar
davidfstr/rdiscount

RDiscount, a C implementation of Markdown with a Ruby extension

Discount (For Ruby) Implementation of John Gruber's Markdown

750 stars67 forksCNOASSERTION

At a glance

What is it?
davidfstr/rdiscount wraps Discount, David Loren Parsons' C implementation of John Gruber's Markdown, as a Ruby gem that passes the Markdown 1.0 test suite. It supports the same options as the classic RedCloth and BlueCloth libraries, and can stand in for BlueCloth in existing code via the aliasing pattern shown in the README.
Who is it for?
Adopt RDiscount if you are in Ruby and need Markdown rendering that is fast, has no runtime dependencies beyond the C extension, and keeps the RedCloth-era option names your existing code already uses. Skip it if you need the extended Markdown dialects that kramdown and commonmarker provide, since Discount implements the original syntax document.
Can I use it commercially?
Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
Is it still maintained?
Activity is slowing. The repository last received commits 6 months ago.
What is it written in?
Mainly C, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 25, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What the package actually contains

RDiscount is a Ruby extension around Discount, which is an implementation of John Gruber's Markdown markup language written in C. The README states that Discount implements all of the language described in the Markdown syntax document and passes the Markdown 1.0 test suite.

That last claim is the one that matters, and it is worth being precise about what it means. The Markdown 1.0 test suite is a fixed set of documents with expected output, so passing it says the renderer handles the documented syntax correctly. It does not say anything about the extended dialects that later libraries added, and Discount is a strict implementation of the original language rather than a superset.

The provenance is split in a way the README is upfront about. Discount was developed by David Loren Parsons, and the Ruby extension is maintained by the author of the rdiscount repository. The homepage is at dafoster.net/projects/rdiscount, the documentation is on rdoc.info, and the bug tracker is the GitHub issues page.

The repository layout matches that split. There is a discount/ directory holding the C implementation, an ext/ directory for the Ruby extension bindings, a lib/ directory for the Ruby side, a man/ directory for the manual pages, a bin/ directory, a Rakefile, the rdiscount.gemspec, a BUILDING file for hacking instructions, a COPYING file for the licence, and a test/ directory. There is also an ext.diff file, which is presumably the patch that keeps the extension working against the C sources, and a discount submodule, which is why there is a .gitmodules file.

The primary language recorded for the repository is C, the licence field reports it as a custom licence GitHub cannot classify, and the last push was on 2026-04-27 with a GitHub Actions build workflow.

Installing and rendering

Releases are published to RubyGems and the install is the standard gem command:

bash
$ [sudo] gem install rdiscount

The sources are also available through git, and the Rakefile lists the available tasks:

bash
$ git clone git://github.com/davidfstr/rdiscount.git
$ cd rdiscount
$ rake --tasks

The README points at the BUILDING file for hacking instructions, which is where you would look for how the C extension is compiled against your Ruby version.

The usage is the classic Markdown library shape. You require the library, construct an object with the Markdown source, and ask for the HTML:

ruby
require 'rdiscount'
markdown = RDiscount.new("Hello World!")
puts markdown.to_html

Additional processing options are turned on when the object is created, and the example shows two of them:

ruby
markdown = RDiscount.new("Hello World!", :smart, :filter_html)

:smart enables the smart punctuation substitutions, and :filter_html filters the HTML in the source. The option names are the ones popularized by RedCloth and adopted by BlueCloth, and that is not an accident.

The BlueCloth compatibility path is the feature that makes this drop-in usable in an existing codebase. The README shows how to inject RDiscount into code that expects BlueCloth:

ruby
begin
  require 'rdiscount'
  BlueCloth = RDiscount
rescue LoadError
  require 'bluecloth'
end

The order matters. RDiscount is tried first and the alias is assigned, and if requiring it raises a LoadError the original BlueCloth is loaded instead. So a project can move to RDiscount for its speed and fall back to BlueCloth if the extension is not available in the environment, which is a sensible arrangement for a gem that compiles C code.

The C extension and the build

The reason a Ruby gem wrapping a C parser is worth the compilation is speed, and the repository shows the shape of that commitment.

The ext/ directory holds the Ruby extension and ext.diff is the patch file that adapts it to the C sources, and the discount/ directory holds the upstream implementation as a submodule rather than as a copy, given the .gitmodules file in the repository root. That arrangement means the C code is tracked as its own project, which is the right call for something with its own upstream and its own release history, and it also means a change to the C side arrives by updating the submodule rather than by a merge.

The Rakefile is the entry point for development, and the README points at rake --tasks to list what is available. The BUILDING file is where the compilation of the extension against your Ruby is described, which is the file to read first if the gem fails to install because of a missing compiler or a header.

For a deployment, the practical consequence is that the target needs a build toolchain. That is a real cost compared with a pure Ruby gem, which installs anywhere Ruby does. It shows up in three places: a Docker image that needs build tools in a first stage, a platform that does not ship a compiler for the target architecture, and a host where the gem is installed from a binary distribution.

The test/ directory is where the behaviour is pinned, and for a Markdown renderer the test suite is the Markdown 1.0 suite plus whatever the extension adds on top. The CHANGELOG.md is the version record, and the repository has no GitHub releases, so the gem versions on RubyGems are the releases.

There is also a man/ directory, which is a slightly unusual thing to find in a gem. Discount is a command line tool in its own right, and the manual pages are for that, so the same C code is usable without Ruby at all if you want a standalone markdown processor. The bin/ directory and the discount/ sources make that possible, and it is a reminder that the Ruby extension is one front end onto a general purpose tool.

The options and what they change in the output

The option names are the interface people actually depend on, so it is worth knowing what they do.

The README demonstrates two of them in the constructor call, and they are representative of the set.:smart turns on the smart punctuation substitutions, which replace straight quotes with typographic ones, and dashes with en and em dashes, following the original Markdown conventions.:filter_html filters the HTML found in the source, which matters when the Markdown comes from users rather than from your own content, because raw HTML in Markdown is a route to script injection.

The options come from the RedCloth lineage, and they are not all about typography. The README only demonstrates:smart and:filter_html; the rest of the option set is not documented here, so check what your version of Discount supports before relying on any others.

Two practical notes about using the options. First, they are set at construction and not at render time, so an object created with:smart will produce smart punctuation on every call to to_html, and a document that needs different options needs a different object. Second, the option set is the RedCloth one, so code written for RedCloth mostly works unchanged, which is the point of the naming, but code written for a CommonMark-oriented library will not transfer because the underlying dialect differs.

The most common mistake when switching a renderer is forgetting that Markdown output is not a fixed string. Discount will produce different HTML for the same input than a CommonMark renderer does in the details, even where the rendered result looks the same. If your application stores rendered HTML, that difference becomes a data migration rather than a code change.

How it compares with the other Ruby Markdown libraries

The Ruby Markdown world has a few well known options, and the differences are mostly about dialect and dependencies.

kramdown is the closest in popularity for new work. It is pure Ruby, it defaults to a kramdown-specific dialect with its own extensions for footnotes, definition lists, math and inline attributes, and it has a parser option to restrict it to a subset. Its advantage is that it needs no compilation; its disadvantage is speed on large documents and the fact that its default output is not the original Markdown.

commonmarker is the modern Rust-based one, exposed to Ruby through a native extension. It is fast, it follows the CommonMark specification closely, and it is what many projects have moved to for that reason. The difference from Discount is the dialect again: CommonMark is a specification with extensions, and Discount is the original 2004 syntax document.

RedCloth is where the option names come from: the README says RDiscount implements the basic protocol popularized by RedCloth and adopted by BlueCloth, so code written against that protocol mostly works unchanged.

So the choice is between a renderer that implements the original Markdown and one that implements a modern dialect. If your content is written in plain Markdown and you want the output to be stable and the dependency tree to be small, Discount is a reasonable answer. If you want tables, fenced code with language hints, footnotes, strikethrough, task lists or autolinks that work as you expect, you want a CommonMark implementation instead, because the original Markdown has no such features and Discount does not invent them.

The performance argument is the one Discount still makes well. A C extension that passes the 1.0 test suite renders a large document faster than a pure Ruby parser, and for a service that renders Markdown on every request, that difference is real.

One thing to check before switching is the licence. Discount is free software under a BSD-style licence that allows you to do as you wish with it as long as you do not attempt to claim it as your own work, and RDiscount adopts that licence verbatim, with the terms in the COPYING file.

Editorial conclusion

Adopt RDiscount if you are in Ruby and need Markdown rendering that is fast, has no runtime dependencies beyond the C extension, and keeps the RedCloth-era option names your existing code already uses. Skip it if you need the extended Markdown dialects that kramdown and commonmarker provide, since Discount implements the original syntax document. Verify first by requiring it in a console, rendering a document with your actual features enabled, and diffing the output against your current renderer before switching.

Frequently asked questions

What is RDiscount?

It is a Ruby extension that wraps Discount, David Loren Parsons' C implementation of John Gruber's Markdown. The README states that Discount implements all of the language in the Markdown syntax document and passes the Markdown 1.0 test suite, and the Ruby extension is maintained by the current maintainer of the gem.

How do I install and use RDiscount?

Install the gem with gem install rdiscount, then require it and render: require 'rdiscount', then RDiscount.new("Hello World!").to_html. Extra processing options are passed at construction, for example RDiscount.new("Hello World!", :smart, :filter_html).

Can RDiscount replace BlueCloth in existing code?

Yes. The README shows a pattern that requires rdiscount and assigns BlueCloth = RDiscount, with a rescue LoadError that falls back to requiring bluecloth, so a project can prefer RDiscount and still work where the extension is unavailable.

Which Markdown dialects does Discount implement?

The original Markdown language as described in John Gruber's syntax document, for which it passes the Markdown 1.0 test suite. It does not implement the later dialects, so features such as tables, footnotes and CommonMark autolinks are not part of it.

What licence is RDiscount under?

RDiscount adopts Discount's licence verbatim, a BSD-style licence that allows you to do as you wish with it as long as you do not attempt to claim it as your own work. The terms are in the COPYING file in the repository.

Official sources

  1. davidfstr/rdiscount on GitHub
  2. Issues
  3. Project website
  4. README
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/davidfstr-rdiscount.svg)](https://hysenlabs.com/projects/davidfstr-rdiscount)

Was this useful?