PHPackages                             facebook/fbmarkdown - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Parsing &amp; Serialization](/categories/parsing)
4. /
5. facebook/fbmarkdown

AbandonedArchivedLibrary[Parsing &amp; Serialization](/categories/parsing)

facebook/fbmarkdown
===================

Markdown parser and renderer for Hack

v1.6.6(4y ago)2923.2k↓50%12[4 issues](https://github.com/hhvm/fbmarkdown/issues)[2 PRs](https://github.com/hhvm/fbmarkdown/pulls)2MITHack

Since Jan 16Pushed 2y ago19 watchersCompare

[ Source](https://github.com/hhvm/fbmarkdown)[ Packagist](https://packagist.org/packages/facebook/fbmarkdown)[ RSS](/packages/facebook-fbmarkdown/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (10)Dependencies (6)Versions (18)Used By (2)

FBMarkdown
==========

[](#fbmarkdown)

FBMarkdown is an extensible parser and renderer for [GitHub Flavored Markdown](https://github.github.com/gfm/), written in [Hack](http://hacklang.org).

It is used to render [the Hack and HHVM documentation](https://docs.hhvm.com).

Why another Markdown library?
-----------------------------

[](#why-another-markdown-library)

For docs.hhvm.com, we wanted:

- GitHub Flavored Markdown for familiarity
- support for custom extensions

Originally, the Ruby GFM pipeline was the best fit; over time, we started to want to:

- make it easier and faster to contribute to docs.hhvm.com
- remove the Ruby dependencies to make it easy to render markdown in other Hack projects
- produce and mutate an AST before rendering
- support multiple renders

FBMarkdown exists to address all of these goals.

Requirements
------------

[](#requirements)

- HHVM 3.24 or above.
- [hhvm-autoload](https://github.com/hhvm/hhvm-autoload)

Installing FBMarkdown
---------------------

[](#installing-fbmarkdown)

```
hhvm composer.phar require facebook/fbmarkdown

```

Using FBMarkdown
----------------

[](#using-fbmarkdown)

```
use namespace Facebook\Markdown;

function render(string $markdown): string {
  $ast = Markdown\parse(new Markdown\ParserContext(), $markdown);

  $html = (new Markdown\HTMLRenderer(
    new Markdown\RenderContext()
  ))->render($ast);

  return $html;
}
```

FBMarkdown currently supports three types of Markdown sources, with plans to expand: trusted, sponsored, and user-generated content.

- **Trusted content mode**: Embedded HTML is enabled, and all URI schemes are enabled and will be parsed as links. In addition, all images are processed normally.
- **Sponsored mode**: HTML rendering is enabled, but limited to allowed tags only (defined in `TagFilterExtension`, based on the GFM spec). Additionally, URIs are limited to the {`http`, `https`, `irc`, and `mailto`} schemes, and `rel="nofollow ugc"` is added to all links.
- **User-generated content**: All HTML is disabled, as are links and images regardless of schemes. If links are re-enabled, `rel="nofollow ugc"` will be added to all links.

To make changes to these default settings:

- You may alter the keyset of allowed URI schemes by calling the Parser function `setAllowedURISchemes()`.
- You may enable embedded HTML by calling the Parser function `enableHTML_UNSAFE()`. **N.B.: For complete compatibility with GitHub Flavored Markdown, support for embedded HTML must be enabled.**
- You may disable image filtering by calling the Renderer function `disableImageFiltering()`.
- You may add `rel="nofollow ugc"` to all links by calling the Renderer function `addNoFollowUGCAllLinks()`.

If you are re-using contexts to render multiple independent snippets, you will need to call `->resetFileData()` on the context.

How FBMarkdown works
--------------------

[](#how-fbmarkdown-works)

### Parsing

[](#parsing)

1. The classes in the `Facebook\Markdown\UnparsedBlocks` namespace convert markdown text to a tree of nodes representing the block structure of the document, however the content of the blocks is unparsed.
2. The contents of the blocks ('inlines') are parsed using the classes in the `Facebook\Markdown\Inlines` namespace.
3. Finally, the classes of the `Facebook\Markdown\Blocks` namespace are used to represent the fully parsed AST - blocks and Inlines.

### Rendering

[](#rendering)

The AST is recursively walked, emitting output for each note - e.g. the HTML renderer produces strings.

Extending FBMarkdown
--------------------

[](#extending-fbmarkdown)

There are 2 main ways to extend FBMarkdown: extending the parser, and transforming the AST.

### Extending The Parser

[](#extending-the-parser)

#### Inlines

[](#inlines)

Extend `Facebook\Markdown\Inlines\Inline` or a subclass, and pass your classname to `$render_ctx->getInlineContext()->prependInlineTypes(...)`.

There are then several approaches to rendering:

- instantiate your subclass, and add support for it to a custom renderer
- instantiate your subclass, and make it implement the `Facebook\Markdown\RenderableAsHTML` interface
- if it could be replaced with several existing inlines, return a `Facebook\Markdown\Inlines\InlineSequence`, then you won't need to extend the renderer.

#### Blocks

[](#blocks)

You will need to implement the `Facebook\Markdown\UnparsedBlocks\BlockProducer` interface, and pass your classname to `$render_ctx->getBlockContext()->prependBlockTypes(...)`.

There are then several approaches to rendering:

- create a subclass of `Block`, and add support for it to a custom renderer
- create a subclass of `Block`, and make it implement the `Facebook\Markdown\RenderableAsHTML` interface
- if it could be replaced with several existing blocks, return a `Facebook\Markdown\Blocks\BlockSequence`
- if it could be replaced with a paragraph of inlines, return a `Facebook\Markdown\Blocks\InlineSequenceBlock`

### Transforming The AST

[](#transforming-the-ast)

Extend `Facebook\Markdown\RenderFilter`, and pass it to `$render_ctx->appendFilters(...)`.

### Examples

[](#examples)

The Hack and HHVM documentation uses most of these approaches; see:

- [context setup](https://github.com/hhvm/user-documentation/blob/master/src/build/MarkdownRenderer.php)
- [implementations](https://github.com/hhvm/user-documentation/tree/master/src/markdown-extensions)

License
-------

[](#license)

FBMarkdown is MIT-licensed.

FBMarkdown may contain third-party software; see [third\_party\_notices.txt](third_party_notices.txt) for details.

###  Health Score

41

—

FairBetter than 89% of packages

Maintenance17

Infrequent updates — may be unmaintained

Popularity38

Limited adoption so far

Community27

Small or concentrated contributor base

Maturity72

Established project with proven stability

 Bus Factor1

Top contributor holds 81.3% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~98 days

Recently: every ~217 days

Total

17

Last Release

1473d ago

Major Versions

v0.2 → v1.02018-03-29

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/3757713?v=4)[Joel Marcey](/maintainers/JoelMarcey)[@JoelMarcey](https://github.com/JoelMarcey)

![](https://avatars.githubusercontent.com/u/601530?v=4)[Yang, Bo](/maintainers/Atry)[@Atry](https://github.com/Atry)

![](https://avatars.githubusercontent.com/u/727402?v=4)[Alexey Toptygin](/maintainers/alexeyt)[@alexeyt](https://github.com/alexeyt)

---

Top Contributors

[![fredemmott](https://avatars.githubusercontent.com/u/360927?v=4)](https://github.com/fredemmott "fredemmott (91 commits)")[![jjergus](https://avatars.githubusercontent.com/u/2483917?v=4)](https://github.com/jjergus "jjergus (11 commits)")[![lexidor](https://avatars.githubusercontent.com/u/31805625?v=4)](https://github.com/lexidor "lexidor (6 commits)")[![alexeyt](https://avatars.githubusercontent.com/u/727402?v=4)](https://github.com/alexeyt "alexeyt (2 commits)")[![aloiret](https://avatars.githubusercontent.com/u/1227963?v=4)](https://github.com/aloiret "aloiret (1 commits)")[![kmeht](https://avatars.githubusercontent.com/u/1120478?v=4)](https://github.com/kmeht "kmeht (1 commits)")

---

Tags

facebookmarkdowngfmhack

### Embed Badge

![Health badge](/badges/facebook-fbmarkdown/health.svg)

```
[![Health](https://phpackages.com/badges/facebook-fbmarkdown/health.svg)](https://phpackages.com/packages/facebook-fbmarkdown)
```

###  Alternatives

[league/commonmark

Highly-extensible PHP Markdown parser which fully supports the CommonMark spec and GitHub-Flavored Markdown (GFM)

2.9k404.0M702](/packages/league-commonmark)[erusev/parsedown

Parser for Markdown.

15.0k151.8M732](/packages/erusev-parsedown)[cebe/markdown

A super fast, highly extensible markdown parser for PHP

1.0k32.5M136](/packages/cebe-markdown)[michelf/php-markdown

PHP Markdown

3.5k52.4M345](/packages/michelf-php-markdown)[league/html-to-markdown

An HTML-to-markdown conversion helper for PHP

1.9k28.6M199](/packages/league-html-to-markdown)[cebe/markdown-latex

A super fast, highly extensible markdown parser for PHP, that converts markdown files into latex

51766.1k7](/packages/cebe-markdown-latex)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
