decodelabs/tagged

PHP markup generation without the fuss


README

PHP from Packagist Latest Version Total Downloads GitHub Workflow Status PHPStan License

PHP markup generation without the fuss.

Tagged provides a simple, powerful and beautiful way to create HTML markup without the spaghetti.

Get news and updates on the DecodeLabs blog.

Installation

composer require decodelabs/tagged

Usage

Tagged uses Veneer to provide a unified frontage under DecodeLabs\Tagged. You can access all the primary HTML functionality via this static frontage without compromising testing and dependency injection.

HTML markup

Generate markup using a simple, flexible interface.

use DecodeLabs\Tagged as Html;

echo Html::{'div.my-class#my-id'}('This is element content', [
    'title' => 'This is a title'
]);

...creates:

<div class="my-class" id="my-id" title="This is a title">This is element content</div>

Create individual tags without content:

use DecodeLabs\Tagged as Html;

$tag = Html::tag('div.my-class');

echo $tag->open();
echo 'Content';
echo $tag->close();

Wrap HTML strings to be used where an instance of Markup is needed:

use DecodeLabs\Tagged as Html;

$buffer = Html::raw('<span class="test">My span</span>');

Dump script data to Html:

yield Html::script(Html::raw(json_encode( $some_data )), [
    'type' => 'application/json'
]);

Prepare arbitrary input for Markup output:

use DecodeLabs\Tagged as Html;

$markup = Html::wrap(
    function() {
        yield Html::h1('My title');
    },
    [Html::p(['This is ', Html::strong('mixed'), ' content'])]
);

Nesting

You can nest elements in multiple ways:

use DecodeLabs\Tagged as Html;

// Pass in nested elements via array
echo Html::div([
    Html::{'span.inner1'}('Inner 1'),
    ' ',
    Html::{'span.inner2'}('Inner 2')
]);


// Return anything and everything via a generator
echo Html::div(function($el) {
    // $el is the root element
    $el->addClass('container');

    // Nest elements with a single call
    yield Html::{'header > h1'}('This is a header');
    yield Html::p('This is a paragraph');

    // Set attributes inline
    yield Html::{'p[data-target=open]'}('Target paragraph');

    // Generator return values are rendered too
    return Html::{'div.awesome'}('This is awesome!');
});

Time and date

Format and wrap dates and intervals

use DecodeLabs\Tagged as Html;

// Custom format
Html::$time->format('now', 'd/m/Y', 'Europe/London');

// Locale format
// When timezone is true it is fetched from Cosmos::$timezone
Html::$time->locale('now', 'long', 'long', true);

// Locale shortcuts
Html::$time->dateTime('tomorrow'); // medium
Html::$time->longTime('yesterday');
Html::$time->shortDate('yesterday');
// ...etc


// Intervals
Html::$time->since('yesterday'); // 1 day ago
Html::$time->until('tomorrow'); // 1 day from now
Html::$time->sinceAbs('yesterday'); // 1 day
Html::$time->untilAbs('yesterday'); // -1 day
Html::$time->between('yesterday', 'tomorrow'); // 1 day

Media embeds

Normalize embed codes shared from media sites:

use DecodeLabs\Tagged\Embed\Video;

echo Video::parse('https://www.youtube.com/watch?v=RG9TMn1FJzc');

Components

Tagged also supports a higher level component abstraction allowing for more complex markup generation via the same interface. Components are called with using an @name syntax:

use DecodeLabs\Tagged as Html;

echo Html::{'@list'}($iterable, 'div.container', 'div.item', function($item) {
    return Html::{'span'}($item);
});

echo Html::{'@img'}('path/to/image.jpg', 'alt text');

See the components directory for a list of available components.

Licensing

Tagged is licensed under the MIT License. See LICENSE for the full license text.