nks-hub / nette-markdown
Nette DI extension wrapping league/commonmark with Latte filter support
Requires
- php: ^8.2
- latte/latte: ^3.0
- league/commonmark: ^2.8
- nette/di: ^3.1
Requires (Dev)
- nette/bootstrap: ^3.2
- phpunit/phpunit: ^10.0
This package is auto-updated.
Last update: 2026-03-12 10:06:02 UTC
README
Nette Framework DI extension wrapping league/commonmark with GitHub Flavored Markdown support, Latte filter integration, and configurable extension system.
Why nette-markdown?
Nette Framework lacks a first-class Markdown integration. While league/commonmark is an excellent CommonMark parser, wiring it into Nette's DI container, configuring extensions, and registering Latte filters requires boilerplate code in every project.
This package provides a zero-config drop-in that just works:
- Nette DI Extension — Register in
config.neon, getMarkdownConverterautowired everywhere - Latte Filter — Use
{$content|markdown}in any template, automatically registered - GFM by Default — Tables, task lists, strikethrough, autolinks out of the box
- Configurable — Enable/disable extensions, set security policies, add heading permalinks
- Safe by Default — HTML input stripped, unsafe links blocked
Quick Start
Installation
composer require nks-hub/nette-markdown
Register in Nette DI
# config/common.neon extensions: markdown: NksHub\Markdown\DI\MarkdownExtension
That's it. MarkdownConverter is now available for injection, and the |markdown Latte filter is registered automatically.
Usage
In Presenters / Services (Dependency Injection)
use NksHub\Markdown\MarkdownConverter; class WikiPresenter extends Nette\Application\UI\Presenter { public function __construct( private MarkdownConverter $markdown, ) {} public function renderView(string $slug): void { $page = $this->pages->findBySlug($slug); $this->template->htmlContent = $this->markdown->convert($page->getContent()); } }
In Latte Templates
{* Filter syntax *} {$page->getContent()|markdown|noescape} {* Or in a block *} {var $html = ($page->getContent()|markdown)} {$html|noescape}
Standalone (Without Nette DI)
use NksHub\Markdown\MarkdownConverter; $converter = new MarkdownConverter(); $html = $converter->convert('# Hello **World**'); // <h1>Hello <strong>World</strong></h1> // Safe mode — strips all HTML, blocks unsafe links $safeHtml = $converter->convertSafe($userInput);
Features
| Feature | Description |
|---|---|
| CommonMark | Full CommonMark spec compliance via league/commonmark 2.x |
| GFM Tables | Pipe-delimited tables with alignment |
| Task Lists | - [x] Done / - [ ] Todo checkbox rendering |
| Strikethrough | ~~deleted~~ to <del>deleted</del> |
| Autolinks | URLs automatically converted to clickable links |
| Footnotes | [^1] reference-style footnotes (opt-in) |
| Smart Punctuation | Curly quotes, em-dashes, ellipsis (opt-in) |
| Heading Permalinks | Anchor links on headings for deep linking (opt-in) |
| Table of Contents | Auto-generated TOC from headings (opt-in) |
| Fenced Code Blocks | ```lang syntax with language class output |
| XSS Protection | HTML stripped, unsafe links (javascript:) blocked by default |
| Latte Integration | |markdown filter auto-registered on all Latte engines |
Configuration
Default (Zero Config)
extensions: markdown: NksHub\Markdown\DI\MarkdownExtension
Defaults: CommonMark + GFM (tables, task lists, strikethrough, autolinks), HTML stripped, unsafe links blocked.
Full Configuration
extensions: markdown: NksHub\Markdown\DI\MarkdownExtension markdown: # Extensions to enable (default: commonmark + gfm) extensions: - commonmark # Core CommonMark spec (always needed) - gfm # Tables + Strikethrough + Task Lists + Autolinks - footnote # Reference-style footnotes - smartpunct # Curly quotes, em-dashes, ellipsis - heading_permalink # Anchor links on headings - toc # Auto-generated Table of Contents # HTML input handling: strip (default), allow, escape html_input: strip # Block javascript:, vbscript:, data: links (default: false = blocked) allow_unsafe_links: false # Heading permalink symbol (only when heading_permalink extension enabled) heading_permalink: symbol: '#'
Available Extensions
| Key | Extension | Description |
|---|---|---|
commonmark |
CommonMarkCoreExtension |
Core CommonMark spec — always include this |
gfm |
Tables + Strikethrough + TaskList + Autolink | GitHub Flavored Markdown bundle |
footnote |
FootnoteExtension |
[^1] reference-style footnotes |
smartpunct |
SmartPunctExtension |
Smart quotes, dashes, ellipsis |
heading_permalink |
HeadingPermalinkExtension |
Clickable anchor links on headings |
toc |
TableOfContentsExtension |
Auto-generated TOC from headings |
API Reference
MarkdownConverter
use NksHub\Markdown\MarkdownConverter; // Default: CommonMark + GFM, HTML stripped, unsafe links blocked $converter = new MarkdownConverter(); // Custom config $converter = new MarkdownConverter([ 'extensions' => ['commonmark', 'gfm', 'footnote'], 'html_input' => 'allow', 'allow_unsafe_links' => false, ]); // Convert Markdown to HTML $html = $converter->convert($markdown); // Safe conversion (always strips HTML + blocks unsafe links, regardless of config) $safeHtml = $converter->convertSafe($untrustedInput);
MarkdownFilter (Latte)
Automatically registered when using the DI extension. Callable as a Latte filter:
{$content|markdown|noescape}
Returns Latte\Runtime\Html instance, so |noescape is required to render the HTML.
MarkdownExtension (Nette DI)
Registers two services:
NksHub\Markdown\MarkdownConverter— injectable converterNksHub\Markdown\Latte\MarkdownFilter— auto-registered on all Latte engines
Security
The converter is safe by default:
| Setting | Default | Effect |
|---|---|---|
html_input |
strip |
Removes all raw HTML from Markdown input |
allow_unsafe_links |
false |
Blocks javascript:, vbscript:, data: URLs |
For user-generated content, use convertSafe() which enforces both settings regardless of constructor config.
Never use html_input: allow with untrusted input — it allows raw HTML injection including <script> tags.
Development
# Install dependencies composer install # Run tests (PHPUnit 10) vendor/bin/phpunit # Run with coverage vendor/bin/phpunit --coverage-html coverage/ # Static analysis vendor/bin/phpstan analyse
Requirements
- PHP: 8.2+
- league/commonmark: ^2.8
- nette/di: ^3.1
- latte/latte: ^3.0
Contributing
Contributions are welcome! For major changes, please open an issue first.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'feat: description') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
Support
- 📧 Email: dev@nks-hub.cz
- 🐛 Bug reports: GitHub Issues
- 📖 CommonMark docs: commonmark.thephpleague.com
- 🏗️ Nette Framework: nette.org
License
MIT License — see LICENSE for details.
Links
- league/commonmark — The underlying CommonMark parser
- Packagist Package
- @nks-hub/texy-editor — TypeScript Texy/Markdown editor with toolbar
Made with ❤️ by NKS Hub