s9e\TextFormatter

repository·master·Indexed 42 days ago

https://github.com/s9e/textformatter

A versatile PHP text formatting library that converts markup such as BBCode, Markdown, and HTML into other formats, typically HTML. It features a plugin-based architecture, a JavaScript port for client-side rendering, and specialized bundles like Fatdown for Markdown and a Forum bundle for BBCode-style text. The library supports secure XSS-resistant rendering, media embedding from various platforms, and custom bundle creation via a Configurator.

Tokens
72.8K
Snippets
201
Records
238
Agent score
53%

What's inside s9e TextFormatter

  1. Overview of s9e\TextFormatter

    master

    s9e\TextFormatter is a PHP-based text formatting library designed to support various markup languages including BBCode, Markdown, and HTML through a plugin-based architecture.

    Key features:

    • Extensibility: Uses plugins to support different markup formats.
    • Cross-platform: While written in PHP for server-side use, a JavaScript port is available for client-side real-time previews.
    • Semantic Versioning: Follows SemVer principles for predictable updates.
  2. Use the MediaEmbed plugin to embed content

    master

    The MediaEmbed plugin allows users to embed content from supported sites using either a [media] BBCode or by posting a supported URL as plain text. It includes built-in support for popular platforms like Facebook, Twitch, Twitter, and YouTube.

    Supported formats include:

    • [media]https://youtu.be/-cEzsCAzTak[/media]
    • https://www.youtube.com/watch?v=-cEzsCAzTak
    $configurator = new s9e\TextFormatter\Configurator;
    
    // Add the sites you want to support
    $configurator->MediaEmbed->add('facebook');
    $configurator->MediaEmbed->add('youtube');
    
    // Get an instance of the parser and the renderer
    extract($configurator->finalize());
    
    $text = 'https://www.youtube.com/watch?v=-cEzsCAzTak';
    $xml  = $parser->parse($text);
    $html = $renderer->render($xml);
    
    echo $html;
  3. Understand the callback signature for filters

    master

    Filters in s9e/textformatter (attribute and tag filters) receive a set of parameters during execution. By default, an attribute filter receives the attribute's value, and a tag filter receives the tag itself.

    You can extend this signature by appending additional parameters using:

    • addParameterByName(string $name): Appends a parameter that can be accessed by its name (e.g., a registered variable).
    • addParameterByValue(mixed $value): Appends a static literal value.
    • resetParameters(): Clears all appended parameters to start a new chain.

    Variables defined in $configurator->registeredVars are available by name and can be modified during parsing via $parser->registeredVars.

  4. How attribute filters work

    master

    Attribute filters are callbacks used during parsing to validate or sanitize user input for specific BBCode attributes.

    Mechanism:

    • The filter is called for each attribute.
    • The attribute's current value is passed as the sole argument to the filter.
    • The return value of the filter replaces the attribute's value.
    • Invalidation: If the filter returns false, the attribute is declared invalid, and no subsequent filters in the chain are applied.
  5. How tag filters work

    master

    Tag filters are callback functions executed during the parsing process. A filter is called for every instance of a specific tag, receiving the tag object as its sole argument.

    Tag filters are primarily used for two purposes:

    1. Invalidating tags: Removing a tag from the output if it doesn't meet specific criteria.
    2. Modifying attributes: Changing or adding attribute values dynamically during parsing.
  6. How the HTMLElements plugin works

    master

    The HTMLElements plugin implements a whitelist-based security model for HTML.

    • Default State: No HTML elements or attributes are allowed.
    • Safe Whitelist: Uses allowElement() and allowAttribute() for standard, non-executable HTML.
    • Unsafe Whitelist: Uses allowUnsafeElement() and allowUnsafeAttribute() for elements and attributes that could execute JavaScript or pose security risks. This separation prevents accidental exposure of vulnerabilities through standard configuration calls.
  7. Understand tag processing priorities

    master

    The textformatter library processes tags based on a priority system where tags with a lower priority number are processed before those with a higher number. This order is critical because the output of one plugin's processing can affect whether subsequent plugins recognize certain patterns.

    For example, a tag with priority -999 (like Litedown's indented code block) will be handled long before a tag with priority 1000 (like Autolink's v tag).

  8. Use the ParsedDOM utility for XML maintenance

    master

    The s9e\TextFormatter\Utils\ParsedDOM utility allows you to load the parsed XML representation of text (typically stored in a database) into a DOM document. You can then manipulate it using standard DOM methods and a specialized API.

    Key Benefits:

    • Provides better guarantees that the resulting XML will match what the parser produces compared to manual string manipulation.
    • Ideal for maintenance tasks and complex transformations.

    Note: For lightweight, real-time operations, use the more efficient s9e\TextFormatter\Utils class instead of ParsedDOM if possible.

    // Start with the parsed representation of the text
    $xml = '<r><p>Hello <EM><s>*</s>world<e>*</e></EM> &#128512;</p></r>';
    
    // Load it into a DOM document
    $dom = s9e\TextFormatter\Utils\ParsedDOM::loadXML($xml);
    
    // Select each EM elements using XPath...
    foreach ($dom->query('//EM') as $em)
    {
    	// ...and unparse it
    	$em->unparse();
    }
    
    // Converting the document to a string will serialize it back to XML in a way that
    // matches what the parser would output.
    echo '__toString() ', (string) $dom . "\n";
    echo 'saveXML()    ', $dom->saveXML();
  9. Use Attribute Preprocessors to parse complex attributes

    master

    Attribute preprocessors allow you to parse the content of an attribute using a regular expression to extract multiple sub-attributes. This is done using the {PARSE=regexp} token.

    How it works

    Any named subpattern (e.g., (?<name>...)) in the regex will create an attribute of that name.

    • Single Preprocessor: [name={PARSE=/(?<first>\w+) (?<last>\w+)/}] converts [name="John Smith"] into [name first="John" last="Smith"].
    • Multiple Preprocessors: You can define multiple regexps separated by commas within one {PARSE} token to handle different formats.
      • [name={PARSE=/(?<first>\w+) (?<last>\w+)/,/(?<last>\w+), (?<first>\w+)/}]
    • Cleaning Values: A preprocessor can overwrite its own attribute value to clean it up.
      • [id={PARSE=/^#?(?'id'\d+)$/}] converts [id=#123] to [id=123].

    Composite Attributes

    For phpBB compatibility, you can use "composite attributes" where multiple tokens are listed. This is automatically converted into a {PARSE} preprocessor.

    • [flash={NUMBER1},{NUMBER2}] becomes [flash={PARSE=/^(?<flash0>\d+),(?<flash1>\d+)$/}].
    • [flash={NUMBER1} {NUMBER2}] (with spaces) becomes [flash={PARSE=/^(?<flash0>\d+)\s+(?<flash1>\d+)$/}].
    [name={PARSE=/(?<first>\w+) (?<last>\w+)/}]
    [flash={NUMBER1},{NUMBER2}]
  10. Configure the FirstAvailable minification strategy

    master

    The FirstAvailable meta-minifier allows you to define a fallback chain of minifiers. The system executes them in the order they are added, and the result of the first successful minification is returned. This is useful for ensuring that minification always occurs, even if a preferred service (like a remote API) is unavailable.

    $configurator = new s9e\TextFormatter\Configurator;
    $configurator->enableJavaScript();
    
    $minifier = $configurator->javascript->setMinifier('FirstAvailable');
    $minifier->add('ClosureCompilerService');
    $minifier->add('MatthiasMullieMinify');
    $minifier->add('Noop');
  11. Automatic URL filtering in Preg replacements

    master

    If a Preg replacement template uses a captured group as a URL (e.g., in an href attribute), the plugin automatically applies the default URL filter. This prevents malicious protocols like javascript: from being rendered, while allowing safe protocols like http:.

    $configurator = new s9e\TextFormatter\Configurator;
    $configurator->Preg->replace(
    	'#<(.*?)>#',
    	'<a href="$1">$1</a>'
    );
    
    extract($configurator->finalize());
    
    $text = "Good link: <http://example.org/>\n" . "Bad link:  <javascript:alert(1)>";
    $xml  = $parser->parse($text);
    $html = $renderer->render($xml);
    
    echo $html;