soundasleep/html2text
Convert HTML to clean, readable plain text in PHP. soundasleep/html2text handles tags, links, images, and whitespace to produce email-friendly, human-readable output, with sensible defaults and options for tweaking formatting.
Installation
composer require soundasleep/html2text
Add to composer.json if not using Composer globally:
"require": {
"soundasleep/html2text": "^3.0"
}
Basic Usage
use Soundasleep\Html2Text\Html2Text;
$html = '<h1>Hello World</h1><p>This is <strong>HTML</strong>.</p>';
$converter = new Html2Text();
$text = $converter->getText($html);
// Output: "Hello World\n\nThis is HTML."
First Use Case Convert HTML emails to plain text for storage or display in a text-only interface:
$emailHtml = '<h2>Welcome!</h2><p>Click <a href="/login">here</a>.</p>';
$plainText = (new Html2Text())->getText($emailHtml);
Laravel Service Provider Integration
Register the converter in AppServiceProvider:
public function register()
{
$this->app->singleton(Html2Text::class, function () {
return new Html2Text();
});
}
Inject via constructor:
public function __construct(private Html2Text $converter) {}
Middleware for Text-Only Responses Convert HTML responses to plain text in middleware:
public function handle($request, Closure $next)
{
$response = $next($request);
if ($request->wantsText()) {
$text = app(Html2Text::class)->getText($response->getContent());
$response->setContent($text);
}
return $response;
}
Model Observers for Automatic Conversion Store plain-text versions of HTML fields:
public function saving(Model $model)
{
if ($model->html_content) {
$model->text_content = app(Html2Text::class)->getText($model->html_content);
}
}
Blade Directives Create a Blade directive for inline conversion:
Blade::directive('toText', function ($expression) {
return "<?php echo app(\\Soundasleep\\Html2Text\\Html2Text::class)->getText({$expression}); ?>";
});
Usage:
@toText($htmlVariable)
API Response Transformation Use in Laravel API resources:
public function toArray($request)
{
return [
'title' => $this->title,
'content_text' => app(Html2Text::class)->getText($this->content),
];
}
Customize Conversion Rules Extend the converter for domain-specific needs:
$converter = new Html2Text();
$converter->setOption('ignore_links', true); // Skip links entirely
$converter->setOption('width', 80); // Wrap text at 80 chars
Batch Processing Useful for converting large datasets (e.g., blog posts):
$posts = Post::all();
foreach ($posts as $post) {
$post->update(['text_content' => $converter->getText($post->content)]);
}
Testing Mock the converter in tests:
$this->app->instance(Html2Text::class, Mockery::mock(Html2Text::class));
Link Handling
[text](url). Disable with:
$converter->setOption('ignore_links', true);
$converter->setOption('link_style', 'text (url)');
Nested HTML
Complex nested HTML (e.g., tables, lists) may not convert as expected. Use setOption('skip_tags', ['table', 'div']) to ignore problematic tags.
Whitespace Preservation Extra whitespace in HTML may cause awkward line breaks. Trim input:
$converter->getText(trim($html));
Character Encoding Ensure input HTML is UTF-8 encoded to avoid mojibake in output.
Performance Avoid instantiating the converter repeatedly. Use dependency injection or a singleton.
Inspect Conversion Rules Dump the converter’s options to debug:
var_dump($converter->getOptions());
Log Raw vs. Converted Output Compare input/output for discrepancies:
\Log::debug("Input HTML:", [$html]);
\Log::debug("Converted Text:", [$converter->getText($html)]);
Check for Malformed HTML
Use a validator like HTMLPurifier to clean input before conversion if needed.
Custom Tag Handlers Override how specific tags are processed:
$converter->setOption('pre_tags', ['pre', 'code']); // Preserve preformatted text
Post-Processing
Chain with str_replace or regex for fine-tuning:
$text = $converter->getText($html);
$text = preg_replace('/\s+/', ' ', $text); // Normalize whitespace
Event Listeners Trigger actions on conversion (e.g., log changes):
$converter->addListener(function ($text) {
\Log::info("Converted text:", [$text]);
});
Laravel Events Dispatch events after conversion:
event(new TextConverted($text));
Default Options Key options:
$converter->setOption('width', 78); // Line width
$converter->setOption('xhtml', true); // Handle XHTML
$converter->setOption('proportional_headers', true); // Scale headers
Case Sensitivity
Tag names in options are case-insensitive (e.g., 'ignore_tags' or 'Ignore_Tags').
Priority Options set later override earlier ones. Reset with:
$converter->resetOptions();
How can I help you explore Laravel packages today?