PHPackages                             iliaal/mdparser - 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. iliaal/mdparser

ActivePhp-ext[Parsing &amp; Serialization](/categories/parsing)

iliaal/mdparser
===============

Native C CommonMark + GitHub Flavored Markdown parser for PHP. 100% spec compliance, 15-30x faster than pure-PHP parsers, zero runtime dependencies.

0.3.0(1mo ago)176BSD-3-ClauseCPHP &gt;=8.3CI passing

Since Apr 11Pushed 4d ago1 watchersCompare

[ Source](https://github.com/iliaal/mdparser)[ Packagist](https://packagist.org/packages/iliaal/mdparser)[ Docs](https://github.com/iliaal/mdparser)[ RSS](/packages/iliaal-mdparser/feed)WikiDiscussions master Synced 1w ago

READMEChangelog (4)DependenciesVersions (4)Used By (0)

mdparser
========

[](#mdparser)

[![Tests](https://github.com/iliaal/mdparser/actions/workflows/tests.yml/badge.svg)](https://github.com/iliaal/mdparser/actions/workflows/tests.yml)[![Windows Build](https://github.com/iliaal/mdparser/actions/workflows/windows.yml/badge.svg)](https://github.com/iliaal/mdparser/actions/workflows/windows.yml)[![Version](https://camo.githubusercontent.com/ef0b4ea8e473b20ea4601de5f90665a85f506df28439b79a1e973d40c4fa26c6/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f762f72656c656173652f696c6961616c2f6d64706172736572)](https://github.com/iliaal/mdparser/releases)[![License: BSD-3-Clause](https://camo.githubusercontent.com/5b18cec5d64abf4a1fb017b12bcf376f4f1aa4c91aa28a9669664f8b2666eb62/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c6963656e73652d4253442d2d332d2d436c617573652d677265656e2e737667)](https://opensource.org/licenses/BSD-3-Clause)[![Follow @iliaa](https://camo.githubusercontent.com/a54521c97521f05fbadec4bd9bcba96ff1eeaffe756a6d7338b47a628cdeb39b/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f466f6c6c6f772d40696c6961612d3030303030303f7374796c653d666c6174266c6f676f3d78266c6f676f436f6c6f723d7768697465)](https://x.com/intent/follow?screen_name=iliaa)

[![mdparser: 15-30× faster than pure-PHP](images/mdparser-hero.jpg)](images/mdparser-hero.jpg)

Native C CommonMark + GitHub Flavored Markdown parser for PHP. 15-30× faster than pure-PHP alternatives (Parsedown, cebe, michelf) with full CommonMark 0.31 compliance: 652/652 spec examples pass. GFM extensions: tables, strikethrough, task lists, autolinks, tagfilter. Installable via [PIE](https://github.com/php/pie) (the PHP Foundation's PECL successor); ships as a single `.so`. PHP 8.2 minimum, OO API with `final` classes and `readonly` options.

📦 Install
---------

[](#-install)

```
# PIE (PHP Foundation's extension installer; uses the composer.json
# at the repo root with type: "php-ext")
pie install iliaal/mdparser
```

On a minimal PHP image (e.g. `php:8.x-cli` from Docker Hub), PIE needs a few build tools installed first:

```
# Debian/Ubuntu
sudo apt install -y git bison libtool-bin

# macOS
brew install bison libtool
```

### From source

[](#from-source)

```
git clone https://github.com/iliaal/mdparser.git
cd mdparser
phpize && ./configure --enable-mdparser
make -j
sudo make install
echo 'extension=mdparser.so' | sudo tee /etc/php/conf.d/mdparser.ini
```

### Windows binaries

[](#windows-binaries)

Pre-built DLLs for PHP 8.3, 8.4, and 8.5 (TS/NTS, x86/x64) are attached to each [GitHub release](https://github.com/iliaal/mdparser/releases).

🛠️ Usage
--------

[](#️-usage)

```
use MdParser\Parser;
use MdParser\Options;

// Default parser: safe mode on, GFM extensions on.
$parser = new Parser();
echo $parser->toHtml('# Hello');
// Hello

// Custom options via named arguments. All fields readonly.
$parser = new Parser(new Options(
    smart: true,          // --- -> em dash, -- -> en dash, "..." -> curly
    sourcepos: true,      // add data-sourcepos to every HTML element
    footnotes: true,      // enable [^ref] / [^ref]: syntax
    unsafe: false,        // raw HTML is still stripped (default)
));
echo $parser->toHtml($markdown);

// Three output formats from one parser.
$html = $parser->toHtml($markdown);
$xml  = $parser->toXml($markdown);   // CommonMark XML, DOCTYPE-wrapped
$ast  = $parser->toAst($markdown);   // nested arrays, see below

// AST shape is documented in tests/006_ast.phpt. Brief example:
// [
//   'type' => 'document',
//   'children' => [
//     ['type' => 'heading', 'level' => 1, 'children' => [
//        ['type' => 'text', 'literal' => 'Hello'],
//     ]],
//   ],
// ]
```

📊 Performance
-------------

[](#-performance)

Against the major pure-PHP Markdown libraries, on PHP 8.4 with each parser in its default configuration:

ParserSmall (200 B)Medium (1.8 KB)Large (200 KB)**mdparser****30447 ops/s****5697 ops/s****105 ops/s**Parsedown1651 ops/s (18x slower)325 ops/s (17x)6 ops/s (17x)cebe/markdown (GFM)1350 ops/s (22x)374 ops/s (15x)6 ops/s (16x)michelf (Markdown Extra)1006 ops/s (30x)209 ops/s (27x)5 ops/s (19x)15-30× faster across the board, from small messages to full 200 KB spec documents. See [`bench/README.md`](bench/README.md) for methodology, corpora, caveats, league/commonmark notes, and how to reproduce these numbers yourself.

✨ Feature matrix
----------------

[](#-feature-matrix)

Comparison with the major pure-PHP Markdown libraries. "via ext" means the feature exists but requires opting in to a non-default extension; "Extra" means the feature ships in the library's Markdown Extra dialect, not its base mode; "✗" means the feature is not supported at all.

FeaturemdparserParsedownleague/cm corecebe GFMmichelf ExtraCiconiaCommonMark core✓partial✓partialpartialpartialFenced code blocks✓✓✓✓✓✓GFM tables✓✓via ext✓via Extra✓Strikethrough✓✓via ext✓✗✓Task lists✓✗via ext✗✗✓Autolinks (bare URL)✓✓via ext✓✗✓`` tag filter✓ (tagfilter)✓ (escaped)via extpartial✗✗Smart punctuation✓ (`Options::smart`)✗via ext✗✗✗Footnotes✓ (`Options::footnotes`)Extravia ext✗✓ ExtrapluginHardbreaks/nobreaks✓✗✗✗✗✗Sourcepos✓✗✓✗✗✗Heading anchors✓ (`Options::headingAnchors`)✗via ext✗✗✗`rel="nofollow"`✓ (`Options::nofollowLinks`)✗via ext✗✗✗HTML output✓✓✓✓✓✓XML output✓✗✗✗✗✗AST output✓ (arrays)✗✓ (objects)✗✗✗What we don't cover
-------------------

[](#what-we-dont-cover)

mdparser is deliberately scoped to what cmark-gfm supports: CommonMark core plus the five GFM extensions. It does **not** cover the "Markdown Extra" family of features that Parsedown Extra, michelf Markdown Extra, and league/commonmark's optional extensions offer. If you need any of the following, reach for league/commonmark, the most actively-maintained pure-PHP option for extended Markdown:

- Definition lists (`Term :: definition`)
- Abbreviations (`*[HTML]: ...`)
- Attribute syntax (`{.class #id key="val"}`)
- Permalink anchor markup (we emit heading `id` slugs; we don't inject the inner `` element GitHub uses for permalinks)
- Table of contents
- YAML front matter
- Mentions (`@user`)
- LaTeX math (`$$...$$`)
- Emoji (`:smile:`)
- Custom admonition containers (`::: warning`)

These are real features. They're just not in scope for a CommonMark+GFM core parser, and cmark-gfm doesn't implement them.

A note on `unsafe: true`
------------------------

[](#a-note-on-unsafe-true)

`Options::unsafe = true` tells cmark to pass raw HTML through verbatim instead of escaping or stripping it. The contract for this mode is that you own the input: it is yours, or it comes from a pipeline you trust. Two postprocess interactions are worth knowing if you also turn on `headingAnchors` or `nofollowLinks`:

- **Heading slug positioning under raw ``.** mdparser locates each AST heading in the rendered HTML by rendering it standalone and matching its exact byte sequence. Raw `x` blocks written directly in the markdown source are therefore left untouched and do not consume slugs. The fingerprint search skips over HTML comments, CDATA sections, and raw-text / escapable-raw-text element bodies (`script`, `style`, `title`, `textarea`, `iframe`, `noscript`, `xmp`, `noembed`, `noframes`, `plaintext`), so a heading-shaped byte sequence inside those regions cannot hijack a slug. The narrow remaining exception is when a raw `...` block in the document body produces bytes byte-identical to a later Markdown heading (same level, same inner text), in which case the `id` attribute lands on the first match.
- **`nofollowLinks` is tag-aware.** It rewrites every `` it finds at a real tag-start position. The scan walks tag-by-tag with quote-aware attribute parsing, so anchor-shaped substrings inside another tag's quoted attribute value (e.g. `` written directly in the source) are passed through verbatim rather than rewritten. Raw-text element bodies and comment / CDATA bodies are likewise emitted verbatim. In-document fragment anchors (`href="#..."`) are intentionally skipped, so footnote references and backrefs stay clean.

### `toAst()` is unsanitized

[](#toast-is-unsanitized)

`Parser::toAst()` returns a structural representation of the parsed document. Link / image `url` fields and `html_block` / `html_inline` `literal` fields are preserved byte-for-byte; the `unsafe`, `tagfilter`, and URL-scheme defenses do **not** apply to the AST. If you build HTML out of the AST yourself, you own the sanitization: apply a URL scheme allowlist before emitting `href`, and run HTML through a sanitizer before emitting raw `html_block` / `html_inline` literal text. See `docs/ast.md` for examples.

🔗 PHP Performance Toolkit
-------------------------

[](#-php-performance-toolkit)

Companion native PHP extensions for high-throughput PHP workloads:

- **[php\_excel](https://github.com/iliaal/php_excel)**: native Excel I/O. 7-10× faster than PhpSpreadsheet, full XLS/XLSX with formulas, formatting, and styling. Powered by LibXL.
- **[php\_clickhouse](https://github.com/iliaal/php_clickhouse)**: native ClickHouse client speaking the wire protocol directly. Picks up where SeasClick left off.
- **[fastchart](https://github.com/iliaal/fastchart)**: native chart-rendering extension. 26 chart types behind one fluent OO API, SVG-canonical with PNG/JPG/WebP output (no libgd dependency).

📚 Read more
-----------

[](#-read-more)

Full background, design rationale, and benchmark methodology in the launch post: [mdparser: A Native CommonMark + GFM Parser for PHP](https://ilia.ws/blog/mdparser-a-native-commonmark-gfm-parser-for-php).

License
-------

[](#license)

- Wrapper code (`mdparser*.c`, `php_mdparser.h`) under BSD 3-Clause.
- Embedded cmark-gfm sources under BSD-2-Clause, MIT, and related permissive licenses. See `LICENSE` for aggregated notices.

---

[Follow @iliaa on X](https://x.com/iliaa) • [Blog](https://ilia.ws) • If this sped up your stack, ⭐ star it!

###  Health Score

42

—

FairBetter than 88% of packages

Maintenance96

Actively maintained with recent releases

Popularity13

Limited adoption so far

Community9

Small or concentrated contributor base

Maturity41

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 98.7% 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 ~12 days

Total

3

Last Release

34d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/2838354?v=4)[iliaa](/maintainers/iliaa)[@iliaa](https://github.com/iliaa)

---

Top Contributors

[![iliaal](https://avatars.githubusercontent.com/u/158724?v=4)](https://github.com/iliaal "iliaal (75 commits)")[![dependabot[bot]](https://avatars.githubusercontent.com/in/29110?v=4)](https://github.com/dependabot[bot] "dependabot[bot] (1 commits)")

---

Tags

cmarkcommonmarkgfmmarkdownpeclphpphp-extensionpieparsermarkdowngfmcommonmarkphp-extensionpiecmark

### Embed Badge

![Health badge](/badges/iliaal-mdparser/health.svg)

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

###  Alternatives

[league/commonmark

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

3.0k426.1M927](/packages/league-commonmark)[erusev/parsedown

Parser for Markdown.

15.0k155.2M835](/packages/erusev-parsedown)[cebe/markdown

A super fast, highly extensible markdown parser for PHP

1.0k33.5M146](/packages/cebe-markdown)[erusev/parsedown-extra

An extension of Parsedown that adds support for Markdown Extra.

84315.1M208](/packages/erusev-parsedown-extra)[cebe/markdown-latex

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

51775.4k8](/packages/cebe-markdown-latex)[parsedown/parsedown

Parser for Markdown.

211.1M6](/packages/parsedown-parsedown)

PHPackages © 2026

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