bedivierre / text-parser
Format-independent rich text parsing and transformation library
Requires
- php: ^8.2
- ext-dom: *
- ext-libxml: *
Requires (Dev)
- phpstan/phpstan: ^2.2
- phpunit/phpunit: ^11.0 || ^12.0
This package is auto-updated.
Last update: 2026-08-03 17:59:09 UTC
README
A PHP library for parsing, transforming, validating, and converting rich text between multiple formats through a shared abstract syntax tree.
Requirements
- PHP 8.2 or newer
- Composer
Installation
composer require bedivierre/text-parser
Basic usage
Parse text
use Bedivierre\TextParser\TextParser; use Bedivierre\TextParser\Parser\MarkdownRichTextParser; $document = TextParser::parse( 'md', '# Hello **world**', ); $parser = new MarkdownRichTextParser(); $document2 = TextParser::parse( $parser, '# Hello **world** yet another time', );
The result is a RichText document containing a normalized serializable tree of nodes that can be saved as json, text or specified format into DB or file.
Transform a document
$html = $document->transformTo('html'); $json = $document->transformTo('json'); $text = $document->transformTo('text');
Convert directly
use Bedivierre\TextParser\Parser\MarkdownRichTextParser; $parser = new MarkdownRichTextParser(); $html = TextParser::convert( from: $parser, // can use 'md'/'markdown' as preinstalled alias to: 'html', source: '# Hello **world**', );
Supported formats
| Format | Parse | Transform |
|---|---|---|
| Markdown | ✓ | ✓ |
| HTML | ✓ | ✓ |
| JSON | ✓ | ✓ |
| Plain text | ✓ | ✓ |
Common aliases such as md, markdown, html,text/html, json,application/json, and text may be used where registered.
End users can make own implementations for parsers and transformers, and register
it via TextParser::registerParser($format, $parser, $replace)
or TextParser::registerTransformer($format, $transformer, $replace)
Markdown support
The Markdown parser supports the main practical Markdown and GFM-style features:
- paragraphs;
- ATX and Setext headings;
- bold, italic, and strikethrough;
- inline code;
- fenced and indented code blocks;
- blockquotes;
- ordered and unordered lists;
- nested and loose lists;
- links and images;
- URL and email autolinks;
- hard and soft line breaks;
- horizontal rules;
- GFM-style tables and column alignment.
The parser is CommonMark-inspired but does not aim to reproduce every edge case of the full CommonMark specification.
Rich-text model
All parsed formats are converted into a shared AST represented by RichText, ElementNode, and TextNode.
Common node types include:
- paragraph;
- heading;
- blockquote;
- bold;
- italic;
- strikethrough;
- link;
- image;
- inline code;
- code block;
- list;
- list item;
- table;
- table row;
- table cell;
- line break;
- horizontal rule.
Example:
use Bedivierre\TextParser\Model\Node\NodeType; $headings = $document ->walker() ->findByType(NodeType::HEADING);
Builder
Documents can be created programmatically:
use Bedivierre\TextParser\Builder\RichTextBuilder; $document = RichTextBuilder::create() ->heading(1, 'Example') ->paragraph() ->text('Hello ') ->bold('world') ->end() ->unorderedList() ->item('First') ->item() ->text('Second') ->unorderedList() ->item('Nested') ->end() ->end() ->end() ->build(validate: true);
Transform the generated document normally:
$markdown = $document->transformTo('md'); $html = $document->transformTo('html');
Validation
A document can be validated before further processing:
TextParser::assertValid($document);
The validator checks node types, attributes, child-node restrictions, nesting, and document structure.
The builder can also validate automatically:
$document = RichTextBuilder::create() // ... ->build(validate: true);
Validation rules can be adjusted or created from zero for end user implementation.
URL policy
Links and images are filtered through a shared URL policy.
A custom policy can restrict allowed schemes and relative URLs:
use Bedivierre\TextParser\Url\UrlPolicy; use Bedivierre\TextParser\Parser\MarkdownRichTextParser; $policy = new UrlPolicy( allowedSchemes: ['https', 'mailto'], allowRelative: false, allowProtocolRelative: false, ); $parser = new MarkdownRichTextParser( urlPolicy: $policy, ); $document = $parser->parse( <<<'MD' # Title [Illegal Link](javascript:void(0)) [Normal Link](https://example.com) [Phone Link](tel:+1234567890) [Email Link](mailto:test@example.com) MD); );
transforms into
# Title Illegal Link [Normal Link](https://example.com) Phone Link [Email Link](mailto:test@example.com)
Unsafe URLs are not emitted as active links or image sources.
Stability
The public API is still under active development. Until version 1.0.0, backward-incompatible changes may occur between minor releases.
License
Apache-2.0