token27 / nexus-ai-formatters
Framework-agnostic formatter registry for serializing structured content to Gutenberg/WP, HTML, Markdown, AMP, and plain text
Requires
- php: ^8.3
Requires (Dev)
- phpstan/phpstan: ^2.0
- phpunit/phpunit: ^11.0
This package is auto-updated.
Last update: 2026-05-20 06:30:59 UTC
README
A framework-agnostic content formatter registry for PHP 8.3+. Designed to seamlessly serialize structured content (DTOs, sections, lists, images) into highly specific output formats like Gutenberg Blocks, HTML, Markdown, AMP, and Plain Text.
Built as part of the NexusAI ecosystem, this library aims to strictly decouple content generation from content presentation, allowing your AI workflows to output clean data structures and formatting the result at the final integration layer.
Zero dependencies. No underlying templating engines. Pure PHP 8.3.
Features
- 100% Framework Agnostic — Integrates smoothly with Laravel, Symfony, CakePHP, or pure PHP apps.
- Zero Dependencies — Requires only PHP 8.3+. No hidden vendor bloat.
- 5 Built-in Formats — Out-of-the-box support for
gutenberg,html,markdown,amp, andplaintext. - Intelligent Serialization — Handles headings with auto-slug generation, lists (including nested arrays), paragraphs, bodies with multiple sections, images, and content guides.
- Registry Pattern — Easily manage, retrieve, and override formatters via the
FormatterRegistry. - Extensible — Built to allow custom formatting logic (e.g., JSON, XML) by simply implementing
ContentFormatterInterface. - Type Safe — Validated by PHPStan at Level 8.
Installation
composer require token27/nexus-ai-formatters
Quick Start
Initialize the registry and resolve your targeted format by name:
use Token27\NexusAI\Formatters\FormatterRegistry; $registry = new FormatterRegistry(); // Pre-loads the 5 default formatters // Resolve a formatter by name $formatter = $registry->resolve('gutenberg'); $formatter->getName(); // 'gutenberg'
Basic Element Formatting
// Headings (auto-clamped between 1 and 6) echo $formatter->formatHeading('Introduction', 2, 'intro'); // output: <!-- wp:heading {"level":2} --><h2 id="intro">Introduction</h2><!-- /wp:heading --> // Images echo $formatter->formatImage('https://cdn.example.com/img.jpg', 'Alt Text', 'Caption'); // output: <!-- wp:image --><figure class="wp-block-image"><img src="..." alt="..."><figcaption>Caption</figcaption></figure><!-- /wp:image --> // Nested Lists $items = [ ['title' => 'Top Level'], ['title' => 'Nested Child', 'level' => 1] ]; echo $formatter->formatList($items);
Complete Content Construction
Pass a structured array of sections to construct an entire formatted body:
$sections = [ [ 'title' => 'Chapter 1: The Beginning', 'content' => "Paragraph 1\n\nParagraph 2", 'level' => 0 // +2 relative offset -> <h2> ] ]; // Returns the full article formatted in Gutenberg blocks natively. echo $formatter->formatBody($sections);
Architecture
The system is designed around a single interface and a centralized registry.
App \ Controller
└── FormatterRegistry::resolve('html')
└── HtmlFormatter (implements ContentFormatterInterface)
├── formatHeading()
├── formatParagraph()
├── formatList()
├── formatBody()
├── formatContentGuide()
└── formatImage()
By passing a DTO abstraction (like ArticleContent->toSections()), you can effortlessly swap the output channel (Publish to WordPress => gutenberg, Publish to Social Media => plaintext) natively within your transport layer without altering the workflow layer that generated the text.
Documentation
Full documentation is available in the docs/ directory:
- Installation & Setup
- Architectural Concepts
- The Registry
- Provided Formatters
- Writing Custom Formatters
- Testing Workflow
- Contributing
Requirements
- PHP 8.3 or higher
License
MIT. Please see LICENSE for more information.