markup-carve / carve-php
PHP parser for Carve, a human-centered lightweight markup language derived from Markdown and Djot.
Fund package maintenance!
Requires
- php: ^8.2
Requires (Dev)
- brianium/paratest: ^7.8
- nikic/php-fuzzer: ^0.0.11
- php-collective/code-sniffer: ^0.6.8
- phpstan/phpstan: ^2.1.32
- phpunit/phpunit: ^11.0 || ^12.0 || ^13.0
Suggests
- ext-intl: Recommended for heading-ID transliteration: enables ICU romanization of non-Latin scripts (e.g. CJK, Arabic). Without it, a baked map covers Latin/Cyrillic/punctuation identically and other scripts fall back to the generated `section` id.
Provides
None
Conflicts
None
Replaces
None
README
PHP parser and renderer for Carve, a post-Markdown lightweight markup language with visual mnemonics and human-centered design.
Implements Carve spec 0.1 (see Versioning & Changelog).
Origins
Carve-PHP is a hard fork of djot-php by the PHP Collective. The fork preserves the architecture, AST, renderer pipeline, profiles, and extensions, and replaces Djot's syntax rules with Carve's. The MIT license carries over; copyright lines remain in LICENSE.
For the original Djot implementation, use php-collective/djot instead.
Installation
composer require markup-carve/carve-php
Usage
use MarkupCarve\Carve\CarveConverter; $converter = new CarveConverter(); $html = $converter->convert('# Hello /Carve/');
HTML, Markdown, Djot and BBCode can return a versioned migration-fidelity report
through each converter's convertWithFidelityReport() method. It uses one
preserved, normalized, degraded, and dropped vocabulary while retaining
format-specific diagnostic codes. HTML also has its detailed import report; see
docs/html-import.md.
Until Markdown, Djot and BBCode provide construct-level evidence, their reports
fail closed with a dropped / fallback fidelity-unverified diagnostic.
The migration CLI writes this envelope with --report FILE (or --report -
for stderr), and --check-loss exits non-zero for degraded or dropped content.
Opaque raw HTML is degraded even when its bytes survive because it is not
modeled or editable by the importer.
Besides HTML the converter renders Markdown, plain text and ANSI. The Markdown writer's options are in docs/markdown-output.md, and every node can carry its source line - docs/source-lines.md.
A document can pull in other files with {{ chapter.crv }}. It is opt-in and
off by default - the core parser performs no file I/O - and the resolver you
supply is the security boundary: docs/includes.md.
Source-aware tools can prepare stale-safe structured formatting changes through
CarveConverter::toCarvePatch(); see the
source-preserving patch guide.
CLI
vendor/bin/carve README.crv > README.html # render (HTML by default) vendor/bin/carve --markdown README.crv # or --plain, --ansi, --json vendor/bin/carve lint README.crv # report problems, change nothing vendor/bin/carve migrate --from html p.html # convert into Carve
Every subcommand and flag is in docs/cli.md.
Sandbox
Try this implementation live in the Carve sandbox - explore syntax and extensions, inspect output, and share snippets via pastebin-style links. It also powers the wp-carve WordPress plugin.
ProseMirror / Tiptap
The AST converts to a ProseMirror document and back, so a Tiptap editor in the browser and PHP rendering on the server share one source of truth with no Node runtime. See docs/prosemirror.md.
Untrusted input
Rendering attacker-controlled Carve needs the safe path, which escapes raw HTML instead of emitting it and bounds nesting depth. The threat model, the defaults and the full checklist are in docs/security.md.
Linting
carve lint reports constructs that parse but render differently from what
the author intended. The rules and options are in docs/lint.md.
Documentation
- Importing HTML - the loss report and the diagnostic path locator.
- Extensions - the extension set, and writing a parse-stage matcher.
- Command line - every subcommand and flag.
- Untrusted input - the threat model and the safe path.
- Linting - the lint rules and options.
- Markdown output - the Markdown writer's options.
- Source-line tracking - carrying source positions on the AST.
- Source-preserving patches - stale-safe UTF-8 edits.
- Stored documents - spec versions and stored content.
- ProseMirror / Tiptap - editor interchange.
- AST JSON - the interchange format.
- Integrated definition layout - collecting and resolving reference, footnote and abbreviation definitions.
- Configured conversion fast path - reusing a configured converter.