alto / markdown
Markdown document engine: parse, query, lint, build, render, and safely edit Markdown with minimal diffs
Requires
- php: >=8.4
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.94
- phpstan/phpstan: ^2.1
- phpstan/phpstan-strict-rules: ^2.0
- phpunit/phpunit: ^12.5
Suggests
- ext-dom: Required for HtmlPolicy::curated() HTML sanitization
README
Alto Markdown parses Markdown into a document model you can lint, format, edit, and convert to HTML, preserving everything you don't touch.
The core has no runtime Composer dependencies. It supports CommonMark, GitHub Flavored Markdown, and GitHub-oriented documents. Trusted extensions can add custom blocks, leaf inlines, native HTML decorators, render-only document projections, lint rules, formatter passes, and document metrics. Alto includes configurable leaf delimiter pairs, smart punctuation, highlights, description lists, footnotes, configurable mentions, nested Markdown tabs, constrained source attributes, escaped code imports, recursive Markdown includes, semantic heading sections, source excerpt displays, and a bounded resource resolver for trusted custom extensions and rich embeds. Front matter stays opaque until the application explicitly passes a decoder.
The full guide set lives under docs/.
| Need | Start with |
|---|---|
| Convert a string to HTML | Markdown::github()->toHtml($source) |
| Convert inline Markdown without a wrapper | Markdown::github()->toInlineHtml($source) |
| Inspect or reuse a document | Markdown::github()->fromString($source) |
| Edit and save a file | Markdown::github()->open($path) |
| Generate Markdown | Markdown::github()->builder() |
| Add trusted syntax or analysis | Markdown::github()->with($extension) |
Installation
composer require alto/markdown
Requires PHP 8.4 or newer. ext-dom is optional, used only by the curated HTML
sanitizer.
Convert to HTML
use Alto\Markdown\Markdown; $markdown = "# Installation\n\nRun `composer install`.\n"; $html = Markdown::github()->toHtml($markdown);
The result is:
<h1>Installation</h1> <p>Run <code>composer install</code>.</p>
Direct conversion is the shortest and fastest path when HTML is the only result you need. Output is safe by default: raw HTML is escaped and unsafe URL schemes are filtered.
Use toInlineHtml() for a title, label, comment, or other fragment where block
syntax and a paragraph wrapper are unwanted:
$label = Markdown::github()->toInlineHtml('Install **Alto**');
See Installation, Conversion, Profiles, and Security to choose the right language and HTML policy.
Open a document when you need more
A document keeps the parsed structure and the original source bytes. Query and edit it without rewriting unrelated content:
use Alto\Markdown\Markdown; $document = Markdown::github()->fromString( "# Guide\n\nRead the [documentation](https://example.com).\n\n" ."## Install\n\nOld instructions.\n", ); $title = $document->title()?->text(); $linkCount = $document->links()->count(); $document->section('Install')->replaceBody("Run Composer.\n"); $markdown = $document->toMarkdown(); $html = $document->toHtml();
Use open() for a file. It adds atomic saving, unified diffs, formatting, and
safe lint fixes:
use Alto\Markdown\Lint\LintConfig; use Alto\Markdown\Markdown; use Alto\Markdown\Operation\SaveOptions; $file = Markdown::github()->open('README.md'); $config = LintConfig::recommended(); $report = $file->lint($config); $file->fix($config); $file->format(); if ($file->hasChanges()) { echo $file->diff()->toUnifiedString(); $file->save(new SaveOptions(compareBeforeWrite: true)); }
Source ranges use original byte offsets. toMarkdown() preserves unchanged
bytes, line endings, and a UTF-8 BOM. Alto rejects an edit when it cannot apply
it safely under the documented V1 contract.
The documentation covers this in more depth: Queries and stats to inspect headings, sections, links, code, and document metrics; Manipulation to edit sections and rearrange top-level blocks with minimal diffs; and Lint, fix, and format to enforce content and style policies.
Extend
Trusted extensions add custom blocks, leaf inlines, native and link-aware HTML decoration, document render projections, lint, formatting, metrics, heading-level projection, permalinks, and generated tables of contents through compiled contracts. Read Extensions and Extension compatibility for the extension contracts and migration notes from historical Alto CommonMark extensions.
Documentation
- Documentation index: browse the complete guide set.
- API reference and Errors: the public surface and recovery contracts.
Development
composer qa # phpstan (max), php-cs-fixer, phpunit composer tests # phpunit only composer coverage # phpunit with a 99% line-coverage floor
License
Alto Markdown is available under the MIT License.