iliaal/mdparser 问题修复 & 功能扩展

解决BUG、新增功能、兼容多环境部署,快速响应你的开发需求

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

iliaal/mdparser

Composer 安装命令:

pie install iliaal/mdparser

包简介

Native C CommonMark + GitHub Flavored Markdown parser for PHP, targeting CommonMark 0.31 + GFM. ~10-20x faster than pure-PHP parsers, zero runtime dependencies.

README 文档

README

Tests Windows Build Version License: BSD-3-Clause Follow @iliaa

mdparser: ~10-20× faster than pure-PHP

Native C CommonMark + GitHub Flavored Markdown parser for PHP. ~10-20× faster than pure-PHP alternatives (Parsedown, cebe, michelf) on a clean optimized build, targeting CommonMark 0.31 (652/652 spec examples pass; see docs/spec-coverage.md). GFM extensions: tables, strikethrough, task lists, autolinks, tagfilter. Installable via 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

# 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

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

Pre-built DLLs for PHP 8.3, 8.4, and 8.5 (TS/NTS, x86/x64) are attached to each GitHub release.

🛠️ Usage

use MdParser\Parser;
use MdParser\Options;

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

// Custom options via named arguments. All fields readonly.
$parser = new Parser(new Options(
    smart: true,          // --- -> em dash, -- -> en dash, "..." -> curly
    footnotes: true,      // enable [^ref] / [^ref]: syntax
    unsafe: false,        // raw HTML is escaped (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

Against the major pure-PHP Markdown libraries, on PHP 8.4 (clean optimized build, each parser in its default configuration):

Corpus mdparser ops/sec Best pure-PHP ops/sec Speedup
200 B ~530,000 ~26,000 (Parsedown) ~20×
1.8 KB ~110,000 ~6,000 (cebe/GitHub) ~19×
200 KB ~980 ~95 (cebe/GitHub) ~10×

~10-20× faster across the corpora (up to ~45× vs the slowest), from small messages to full 200 KB spec documents. bench/README.md is the source of truth: methodology, all parsers, caveats, league/commonmark notes, and how to reproduce. (Always benchmark a clean optimized PHP build; a debug/ASan build inflates these numbers.)

✨ 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.

Feature mdparser Parsedown league/cm core cebe GFM michelf Extra Ciconia
CommonMark core partial partial partial partial
Fenced code blocks
GFM tables via ext via Extra
Strikethrough via ext
Task lists via ext
Autolinks (bare URL) via ext
<script> tag filter ✓ (tagfilter) ✓ (escaped) via ext partial
Smart punctuation ✓ (Options::smart) via ext
Footnotes ✓ (Options::footnotes) Extra via ext ✓ Extra plugin
Hardbreaks/nobreaks
Sourcepos
Heading anchors ✓ (Options::headingAnchors) via ext
rel="nofollow" ✓ (Options::nofollowLinks) via ext
HTML output
XML output
AST output ✓ (arrays) ✓ (objects)

Opt-in dialect extensions

Beyond CommonMark + GFM, md4c ships several dialect extensions, each exposed as an opt-in Options flag (all default off, so the standard CommonMark + GFM parse is unaffected): latexMath ($inline$, $$block$$), wikiLinks ([[target]]), spoilers (||text||), underline, highlight (==text==), superscript (^text^), subscript (~text~), and admonitions (GitHub-style > [!NOTE] alert blocks). Plus parser-behavior toggles (noIndentedCodeBlocks, permissiveAtxHeadings, collapseWhitespace). See docs/options.md for behavior and edge cases.

What we don't cover

mdparser is deliberately scoped to CommonMark core plus the 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 <a class="anchor"> element GitHub uses for permalinks)
  • Table of contents
  • YAML front matter
  • Mentions (@user)
  • Emoji (:smile:)
  • Fenced admonition containers (::: warning); GitHub-style > [!NOTE] alert blocks are supported via Options::admonitions

These are real features. They're just out of scope for a CommonMark+GFM core parser.

A note on unsafe: true

Options::unsafe = true tells the renderer 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. headingAnchors and nofollowLinks are applied in-stream as md4c parses the source, so they touch only Markdown-derived nodes; raw HTML you write directly is emitted verbatim and is never rewritten:

  • Heading anchors apply to Markdown headings only. A # heading gets an id slug. A raw <h1>x</h1> block written directly in the source (possible under unsafe: true, tagfilter: false) is raw HTML, not a parsed heading node, so it is emitted untouched and gets no id. A raw heading and a later Markdown heading with the same text do not collide.
  • nofollowLinks applies to Markdown links only. Inline links, reference links, and autolinks get rel="nofollow noopener noreferrer"; in-document fragment anchors (href="#...", including footnote references and backrefs) are skipped. A raw <a href="..."> written directly in the source is passed through verbatim rather than rewritten. Sanitize raw HTML yourself if you allow it.

Structural outputs are unsanitized

Parser::toXml() and Parser::toAst() return structural representations of the parsed document. Link / image url fields and html_block / html_inline literal text are preserved; XML output escapes those bytes as XML text, while AST output returns them byte-for-byte. The unsafe, tagfilter, and URL-scheme defenses do not make these structural outputs safe to transform back into HTML. If you build HTML out of XML or AST data 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.

🔗 Native PHP extensions

Companion native PHP extensions:

  • php_excel: native Excel I/O via LibXL. 7-10× faster than PhpSpreadsheet, full XLS/XLSX with formulas, formatting, and styling.
  • php_clickhouse: native ClickHouse client speaking the wire protocol directly. Picks up where SeasClick left off.
  • pdo_duckdb: PDO driver for DuckDB, analytical SQL in your PHP stack.
  • fastjson: drop-in faster ext/json, backed by yyjson. 6× encode, 2.7× decode, 5× validate.
  • phpser: decoder-optimized binary serializer for cache workloads. Faster than igbinary on packed numerics and DTO batches.
  • fast_uuid: high-throughput UUID generation (v1/v4/v7), batched CSPRNG and SIMD hex formatter, ramsey-compatible API.
  • fastchart: native chart-rendering extension. 38 chart types behind one fluent OO API, SVG-canonical with PNG/JPG/WebP and optional PDF output.
  • statgrab: system statistics (CPU, memory, disk, network) via libstatgrab, no parsing /proc by hand.
  • phonetic: native phonetic name matching (Double Metaphone, Beider-Morse, Daitch-Mokotoff, NYSIIS, Match Rating), the encoders PHP core lacks.

📚 Read more

Full background, design rationale, and benchmark methodology in the launch post: mdparser: A Native CommonMark + GFM Parser for PHP.

License

  • Wrapper code (mdparser*.c, php_mdparser.h) under BSD 3-Clause.
  • Embedded md4c sources under the MIT license. See LICENSE for aggregated notices.

Follow @iliaa on XBlog • If this sped up your stack, ⭐ star it!

iliaal/mdparser 适用场景与选型建议

iliaal/mdparser 是一款 基于 C 开发的 Composer 扩展包,目前已累计 367 次下载、GitHub Stars 达 20, 最近一次更新时间为 2026 年 04 月 11 日, 在 PHP 生态内属于活跃度较高的组件。

它主要适用于以下技术方向: 「parser」 「markdown」 「pie」 「gfm」 「commonmark」 「php-extension」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。

我们在过去多个企业项目中使用过 iliaal/mdparser 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 iliaal/mdparser 我们能提供哪些服务?
定制开发 / 二次开发

基于 iliaal/mdparser 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 367
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 20
  • 点击次数: 38
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 20
  • Watchers: 1
  • Forks: 1
  • 开发语言: C

其他信息

  • 授权协议: BSD-3-Clause
  • 更新时间: 2026-04-11