hirasso/prose

Format rich text / prose HTML: obfuscate addresses, mark external links, tidy empty tags 🐘

Maintainers

Package info

github.com/hirasso/prose

pkg:composer/hirasso/prose

Transparency log

Fund package maintenance!

hirasso

Statistics

Installs: 1

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v0.1.0 2026-07-10 09:59 UTC

This package is auto-updated.

Last update: 2026-07-10 11:13:54 UTC


README

Latest Version on Packagist Test Status Code Coverage

Format rich text / prose HTML in PHP. Fully HTML5-compatible 🐘

A tiny, framework-agnostic formatter for WYSIWYG / rich text content. Pass a string, get a string back:

  • Obfuscate email/phone links against spam bots (via hirasso/html-obfuscator)
  • Mark external links (target="_blank", custom attributes)
  • Strip tags to an allowlist
  • Remove whitespace-only elements (e.g. empty <p>)

Installation

composer require hirasso/prose

Usage

use Hirasso\Prose\Prose;
use Hirasso\Prose\ProseOptions;

// Minimal: sensible defaults (obfuscate + prune empty <p>)
echo Prose::format($html);

// Configured
echo Prose::format($html, new ProseOptions(
    allowedTags: ['p', 'a', 'br', 'strong', 'em', 'ul', 'li'],
    siteUrl: 'https://example.com',      // required to detect external links
    removeEmptyElements: ['p'],
    obfuscate: true,
));

Note

Prose::format() expects a prose fragment, not a full HTML document. It throws an InvalidArgumentException if the input contains <!doctype>, <html>, <head> or <body>.

Options

Option Default Purpose
allowedTags null Tags to keep when stripping. null = don't strip.
obfuscate true Obfuscate email/phone links.
removeEmptyElements ['p'] Selectors of whitespace-only elements to prune.
siteUrl null Your site's URL. Required to detect external links.
externalLinkAttributes ['data-external' => '', 'target' => '_blank'] Attributes added to external links.

WordPress / ACF

The package ships no framework glue. Wire it into an acf/format_value filter in your project:

add_filter('acf/format_value/type=wysiwyg', function (mixed $value, $postID, array $field): mixed {
    if (!is_string($value) || trim($value) === '') {
        return $value;
    }
    return Prose::format($value, new ProseOptions(
        allowedTags: ['p', 'a', 'br', 'blockquote', 'strong', 'b', 'i', 'em', 'ul', 'li', 'sup'],
        siteUrl: home_url(),
    ));
}, 11, 3);

// Inject the obfuscator client script once, in <head>:
add_action('wp_head', fn () => print(\Hirasso\HTMLObfuscator\clientScript()));

License

MIT © Rasso Hilber