nowo-tech / milkdown-editor-bundle
Symfony form type for Markdown editing with Milkdown and a reduced Crepe build, plus a league/commonmark renderer for the same dialect (page links, mentions, icons, directives).
Package info
github.com/nowo-tech/MilkdownEditorBundle
Language:JavaScript
Type:symfony-bundle
pkg:composer/nowo-tech/milkdown-editor-bundle
Requires
- php: >=8.2 <8.6
- league/commonmark: ^2.7
- psr/log: ^3.0
- symfony/asset: ^7.4 || ^8.0
- symfony/config: ^7.4 || ^8.0
- symfony/dependency-injection: ^7.4 || ^8.0
- symfony/form: ^7.4 || ^8.0
- symfony/framework-bundle: ^7.4 || ^8.0
- symfony/http-foundation: ^7.4 || ^8.0
- symfony/http-kernel: ^7.4 || ^8.0
- symfony/options-resolver: ^7.4 || ^8.0
- symfony/translation-contracts: ^3.5
- symfony/twig-bundle: ^7.4 || ^8.0
- twig/extra-bundle: ^3.21
- twig/string-extra: ^3.21
- twig/twig: ^3.21
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.64
- igor-php/igor-php: ^0.10
- nowo-tech/phpstan-frankenphp: ^1.1
- phpstan/phpstan: ^2.1
- phpstan/phpstan-phpunit: ^2.0
- phpstan/phpstan-symfony: ^2.0
- phpunit/phpunit: ^11.5
- rector/rector: ^2.0
- symfony/browser-kit: ^7.4 || ^8.0
- symfony/css-selector: ^7.4 || ^8.0
- symfony/translation: ^7.4 || ^8.0
- symfony/yaml: ^7.4 || ^8.0
- vincentlanglet/twig-cs-fixer: ^4.1
Suggests
None
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-10-31 09:44:08 UTC
README
⭐ Found this useful? Install from Packagist · Give it a star on GitHub so more developers can find it.
Milkdown Editor Bundle — a Symfony form type that edits Markdown with Milkdown and a reduced Crepe build, plus a league/commonmark renderer for the same Markdown dialect: page links by id resolved per viewer, mentions, Tabler icons, callouts, collapsible sections, highlights, Mermaid diagrams and math. Markdown is the stored value; the editor is accessible, works under a strict nonce-based CSP and loads code highlighting, KaTeX, Mermaid and real-time collaboration only when a field needs them.
📋 Compatible with Symfony 7.4+ and 8.0–8.1+ — PHP 8.2+ (Symfony 8.x requires PHP 8.4+).
This bundle is FrankenPHP worker mode friendly. See docs/FRANKENPHP-WORKER-AUDIT.md.
Features
Wiki profile — callout, tasks, table, Mermaid, math, selection toolbar |
Dark theme — @ suggestions with the ARIA listbox pattern
|
MilkdownEditorType— a textarea holding Markdown (the form value and the no-JavaScript fallback) turned into a Milkdown editor; named profiles (features, theme, icons, upload limits) and per-field options.- Reduced Crepe build — toolbar, link tooltip, tables, CodeMirror code blocks, placeholder, cursor, an accessible
/block menu, optional top bar; no list-item, image-block, block-handle, AI or emoji features. - Markdown dialect (TypeScript and PHP):
[[wiki:<uuid>#anchor]],@handle,:tabler-<name>:,:::callout{type=…},:::details{summary=…},::: {align=center},:mark[text]{color=…}, leaf directives such as::beacon{type=issue id=…}for host blocks,$math$/$$…$$, fencedmermaid. - Suggestions —
[[pages,@people,:icons and emoji,/blocks: remote candidate URLs, debounced, at most 10 results, combobox keys (Up / Down, Enter / Tab, Escape) on the multi-line editable. - Per-viewer page titles — chips resolve titles in one batched request; pages the viewer may not read show Content not visible (editor and renderer alike).
- Uploads — drop, paste or Insert file: multipart POST with the CSRF token in a header, progress and errors in a live region, size and type checks before sending.
- Accessibility — every control named, real
ul > lilists and task checkboxes, contrast-safe tokens and code colours, visible focus rings, Tab leaves the editor outside lists, tables and code (WCAG 2.1.2). - Strict CSP — no inline scripts or style elements without the nonce: CodeMirror and Mermaid styles get the page
nonce; the widget adds its
<script type="module">and stylesheet with it. - Opt-in extras — Mermaid (strict security level, no HTML labels) and KaTeX (no
\href), Yjs collaboration over Mercure (collaborationoption), all in lazy chunks. - PHP renderer —
milkdown_markdownTwig filter /MarkdownRendererInterface: CommonMark + GFM + the dialect, raw HTML escaped, unsafe links dropped, remote images turned into links, host resolvers for pages, users, icons and directives. - Theme tokens —
--nowo-milkdown-*custom properties, light / dark / auto. - 7 locales (en, es, de, fr, it, nl, pt) in the
NowoMilkdownEditorBundledomain.
Installation
composer require nowo-tech/milkdown-editor-bundle php bin/console assets:install
Without Symfony Flex, register Nowo\MilkdownEditorBundle\NowoMilkdownEditorBundle::class => ['all' => true] in
config/bundles.php (and TwigExtraBundle). Details: docs/INSTALLATION.md.
Quick start
use Nowo\MilkdownEditorBundle\Form\MilkdownEditorType; $builder->add('body', MilkdownEditorType::class, [ 'profile' => 'wiki', // a profile from nowo_milkdown_editor.profiles 'suggestions' => ['[[' => '/api/pages', '@' => '/api/users'], 'link_title_url' => '/api/pages/titles', 'upload_url' => '/api/upload', 'upload_csrf_token' => $csrf->getToken('upload')->getValue(), ]);
# config/packages/nowo_milkdown_editor.yaml nowo_milkdown_editor: default_profile: wiki profiles: wiki: features: [toolbar, link_tooltip, table, code_mirror, math, mermaid, placeholder, cursor, slash_menu] icon_sprite_url: /icons/tabler-sprite.svg icons: [bug, bolt, rocket] comment: features: [toolbar, link_tooltip, placeholder]
{{ form_row(form.body) }} {# the form theme is registered automatically #}
{{ page.body|milkdown_markdown }} {# safe HTML of the same dialect #}
Requirements
- PHP 8.2–8.5, Symfony 7.4 or 8.x (FrameworkBundle, Form, TwigBundle, Asset), Twig 3.21+ with Twig Extra
- league/commonmark 2.7+
- A browser with ES2022 modules (the editor is an ES module with lazy chunks)
Version information
| Bundle | PHP | Symfony | Milkdown / Crepe |
|---|---|---|---|
| 1.0.x | 8.2–8.5 | 7.4, 8.0, 8.1 | 7.23.0 |
Demo
A Symfony 8.1 demo on FrankenPHP (worker mode) lives in demo/symfony8: both profiles, mock candidate endpoints, a
forbidden page, uploads, the server-side render and a strict nonce CSP.
make -C demo up # http://localhost:8187 make test-e2e # Playwright + axe + CSP
Documentation
- Installation
- Configuration
- Usage
- Contributing
- Code of Conduct
- Changelog
- Upgrading
- Release
- Security
- Engram
- Spec-driven development
- GitHub Spec Kit
Additional documentation
- Architecture
- Standards compliance
- PSR evaluation
- Coverage policy
- Demo FrankenPHP
- FrankenPHP worker audit
- GitHub CI
Tests and coverage
- Tests: PHPUnit (unit, integration), Vitest (TypeScript, jsdom with the real editor), Playwright + axe (demo e2e)
- PHP: 100%
- TS/JS: 90.66%
- Python: N/A
PHP line coverage target: 100% of src/ (gate 100%, make test-coverage-100). TypeScript coverage is the
minimum of statements / branches / functions / lines (REQ-TEST-009); gate ≥ 90% lines.
make test
make test-coverage
make test-ts
make test-e2e
make qa
License
MIT © 2026 Héctor Franco Aceituno / Nowo.tech
Contributing
See docs/CONTRIBUTING.md. Issues and pull requests: GitHub.


