# github/markup: the Ruby gem that picks the renderer for your README

> github/markup is the first step in GitHub's rendering pipeline: it maps a filename to the library that converts raw markup to HTML. It is a dispatcher, not a renderer, and the documentation is explicit that sanitization happens elsewhere.

**github/markup** — Determines which markup library to use to render a content file (e.g. README) on GitHub

- Repository: https://github.com/github/markup
- Stars: 6,041 · Forks: 3,373
- Language: Ruby
- License: MIT
- Published: 2026-09-22 · Updated: 2026-09-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/github-markup

## The problem github/markup solves: one filename, many markup languages

A repository can contain a README.md, a README.rst, a README.asciidoc and a README.org, and each one needs a different parser. github/markup exists to make that choice automatically. The README describes the library as "the first step" of the journey a markup file takes before it is rendered on GitHub.com, and the job of that step is to select an underlying library that converts raw markup to HTML. The gem is for people building a rendering pipeline of their own: a documentation site, a self-hosted forge, a CI job that converts mixed-format docs, or a tool that wants GitHub-compatible output. It is not for someone who just wants to turn a Markdown string into HTML; for that, a single parser is a smaller dependency. The gem covers the dispatch problem, and the README is direct about the boundary: "only the first step is covered by this gem."

## How the dispatch works, and what the gem deliberately leaves out

The mechanism is a lookup from file extension to a renderer. The README lists the supported formats with the dependency each one needs: .markdown, .mdown, .mkdn and .md map to commonmarker; .textile to RedCloth; .rdoc to rdoc; .org to org-ruby; .creole to creole; .mediawiki and .wiki to wikicloth; .rst to docutils, which is a Python package installed with pip; .asciidoc, .adoc and .asc to asciidoctor; and .pod to Pod::Simple::XHTML, which ships with Perl 5.10 and later. The entry point is GitHub::Markup.render, which takes a filename and the file contents. Because the extension drives the choice, the same call site can serve every format in the list. What the gem does not do is stated plainly: it performs no sanitization of the resulting HTML, because it expects whatever pipeline consumes the HTML to handle that. On GitHub.com the remaining steps are sanitization, syntax highlighting via github/linguist, and further filters for emoji, task lists, named anchors, image CDN caching and autolinking. If you run the gem alone, none of those run. That is a design boundary rather than a defect, but it means the gem's output should never be handed to a browser unprocessed.

## Installing github-markup and rendering a README

The README gives a single install command for the gem itself. Run it, then install the parser for whichever formats you intend to render, since the gem only dispatches to them.

```bash
gem install github-markup
```

The basic usage form takes a filename and a string. The filename matters even though the content is passed separately, because its extension selects the parser.

```ruby
require 'github/markup'

GitHub::Markup.render('README.markdown', "* One\n* Two")
```

A more realistic form reads the file from disk, so the extension and the content come from the same source. This is the shape most pipelines use.

```ruby
require 'github/markup'

GitHub::Markup.render(file, File.read(file))
```

There is also a convenience form that skips filename detection and names the markup constant directly, which is useful when the format is known ahead of time.

```ruby
require 'github/markup'

GitHub::Markup.render_s(GitHub::Markups::MARKUP_MARKDOWN, "* One\n* Two")
```

For local development, the README points at a bootstrap script that fetches the dependencies, run from a Python virtual environment.

```sh
python3 -m venv .venv
source .venv/bin/activate
cd script
./bootstrap
```

The README also notes that running `script/bootstrap` fetches all the listed dependencies, which is the fastest way to get every format working rather than installing them one by one.

## The dependency surface is the real cost of admission

The gem is small, but the formats it dispatches to are not. Each entry in the supported list carries its own install command and its own runtime, and a few of them are not Ruby at all. The .rst renderer is docutils, installed with pip, so a Ruby application that wants to render reStructuredText needs a Python environment present. The .pod renderer is Pod::Simple::XHTML, which comes with Perl 5.10 or later; the README says lower versions should install Pod::Simple from CPAN. The .rdoc entry pins a specific version, `gem install rdoc -v 3.6.1`, which is a signal that the dispatch target is version-sensitive rather than tracking whatever rdoc is current. In practice this means a deployment that supports the full format list carries Ruby gems, a Python package and a Perl module. A pipeline that only ever renders Markdown can install commonmarker alone and ignore the rest, but the gem's supported-format table is the checklist you have to work through. There is no documented lazy loading here: the README presents the dependencies as required if you wish to run the library.

## Where github/markup is the wrong tool

Two cases stand out. The first is a project that renders one format. If every file you process is .md, github/markup adds a dispatch layer over commonmarker without changing the output, and you take on the gem's maintenance cycle for no gain. Call commonmarker directly. The second case is anything that puts rendered HTML in front of users without a sanitizer. The README is unambiguous that markup itself does no sanitization and expects that to be covered by whatever pipeline consumes the HTML. If you are building a comments feature, a user-profile field, or anything where the input is untrusted, the gem is one step in a longer chain and the sanitizer is your responsibility. A related limitation is that the gem's output will not match GitHub.com exactly, because the steps after dispatch (highlighting, emoji, task lists, named anchors, image CDN caching, autolinking) happen on GitHub.com and not in the gem. If pixel-level parity with GitHub is the requirement, the gem gets you the parser choice and nothing past it.

## Alternatives and how their approach differs

The closest structural alternative is calling the target parser yourself. For Markdown that means commonmarker, the same library github/markup dispatches to for .md files, so the rendered output is identical and the difference is purely the extension-to-library mapping you give up. For a multi-format site, the alternative is a documentation toolchain that owns the whole pipeline rather than just the first step: a static site generator with its own Markdown and AsciiDoc support, for instance. That approach inverts the trade-off. You get sanitization, highlighting and link handling from one project, but you are bound to its format list and its rendering choices instead of GitHub's. There is also the option of shelling out to each format's native CLI, which is what docutils and Pod::Simple effectively are. That avoids Ruby entirely but leaves you writing the extension dispatch logic that github/markup already implements. The gem's value is precisely that mapping table, so an alternative only wins if you do not need GitHub-compatible parser selection.

## Maintenance, licence and upgrade considerations

The repository is not archived, and the last push was on 2026-07-29. The most recent release is v6.0.0 on 2026-05-05, following v5.0.1 and v5.0.0 on 2024-06-17. That release history shows a long gap between the 5.x line and 6.0.0, so a major-version bump is worth reading through before upgrading rather than assuming a drop-in change. The gem is MIT licensed, which is permissive and imposes no copyleft obligation on your application; the dependencies it dispatches to carry their own licences, and those are separate from github/markup's. Since the gem's job is selecting other libraries, an upgrade to github-markup can change which parser version you end up running for a given extension, so the practical check before upgrading is the supported-format list and the pinned versions in it. The README does not document a rollback procedure or a deprecation policy for the format list, so treat the release notes as the source for what changed.

## Conclusion

Adopt github/markup when you need the same filename-to-renderer mapping GitHub uses, for example in a docs preview service or a CI step that converts many formats. Do not adopt it as a Markdown library: it delegates to commonmarker for .md files, and it performs no sanitization, so any HTML it returns must pass through your own filter before it reaches a browser. Before committing, verify which optional gems and system packages your chosen format needs, whether the gem's default renderer for that extension matches the library you already run, and how your pipeline will handle a missing dependency.

## FAQ

### Does github/markup sanitize the HTML it produces?

No. The README states that markup itself does no sanitization of the resulting HTML and expects that to be covered by whatever pipeline consumes the HTML. On GitHub.com, sanitization is a separate step after the gem runs.

### Which Markdown library does github/markup use for .md files?

The supported-format list maps .markdown, .mdown, .mkdn and .md to commonmarker, installed with gem install commonmarker. The gem dispatches to it rather than implementing Markdown parsing itself.

### How do I install github/markup?

The README gives gem install github-markup, or bundle install from the repository directory. Rendering a specific format also requires that format's dependency, such as commonmarker for Markdown.

### Does github/markup render reStructuredText without Python?

No. The .rst entry lists docutils, which the README says is installed with pip install docutils, so a Python environment is required for that format.

## Sources

- [github/markup on GitHub](https://github.com/github/markup)
- [Issues](https://github.com/github/markup/issues)
- [License: MIT](https://github.com/github/markup/blob/master/LICENSE)
- [README](https://github.com/github/markup/blob/master/README.md)
- [Releases](https://github.com/github/markup/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/github-markup
