erikvv/hyperscript

There is no license information available for the latest version (dev-master) of this package.

dev-master 2023-03-22 12:17 UTC

This package is auto-updated.

Last update: 2024-12-22 15:13:13 UTC


README

HTML generation in pure PHP, replaces a template engine.

Advantages

Advantages compared to a template engine:

  • Easy to create components, using classes and functions
  • No need to learn a DSL
  • Safe from XSS
  • IDE support

Setup

composer require erikvv/hyperscript
use DOMDocument;
use Erikvv\Hyperscript\Hyperscript;

require './vendor/autoload.php';

$h = new Hyperscript(new DOMDocument());

Background

Hyperscript for PHP is built on top of the DOM extension.

It is inspired by similar libraries such as HyperScript for JS, Hiccup for Clojure and Elm

Erikvv/hyperscript improves on spatie/html-element because that library is vulnerable to XSS.

Examples

Text fragment:

$fragment = $h->fragment(
    $h->h1('.welcome-header', 'Welcome'),
    $h->p('Write some hyperscript'),
);

echo $h->render($fragment);
<h1 class="welcome-header">Welcome</h1>
<p>Write some Hyperscript</p>

Form:

$error = 'Cartoon birds not allowed';
$birdName = 'Donald Duck';

$element =
    $h->form(
        '#bird-form', [
            'method' => 'post',
            'action' => '/bird/submit',
        ],
        $error ? $h->div('.error', $error) : null,
        $h->div(
            $h->label(['for' => 'bird-name'], 'Name'),
            $h->input(
                '.bird-name', [
                    'name' => 'bird-name',
                    'value' => $birdName
                ]
            )
        ),
        $h->button('Submit')
    );

echo $h->render($element);
<form id="bird-form" method="post" action="/bird/submit">
    <div class="error">Cartoon birds not allowed</div>
    <div>
        <label for="bird-name">Name</label>
        <input id="bird-name" name="bird-name" value="Donald Duck">
    </div>
    <button>Submit</button>
</form>

Escaping by default:

$element = $h->div('<script>alert(1)</script>');

echo $h->render($element);
<div>&lt;script&gt;alert(1)&lt;/script&gt;</div>

Disable escaping:

$element = $h->div(
    $h->unsafe('<script>alert(1)</script>')
);

echo $h->render($element);
<div><script>alert(1)</script></div>

Custom element:

$element = $h('my-custom-element', 'my-content')

echo $h->render($element);
<my-custom-element>my-content</my-custom-element>

Custom component:

/**
 * You can improve this class with object-oriented 
 * or functional techniques to fit your usecase.
 */
class RoundedMillimeterTable
{
    public static function row(Hyperscript $h, string $rowHeader, float ...$values): DOMElement 
    {
        $cells = [
            $h->td($rowHeader)
        ];

        foreach ($values as $value) {
            $cells[] = $h->td(number_format($value, 1) . ' mm');
        }

        return $h->tr(...$cells);
    }
}

$row = RoundedMillimeterTable::row($h, 'displacement', 1.8, 2.0);

echo $h->render($row);
<tr>
    <td>displacement</td>
    <td>1.8 mm</td>
    <td>2.0 mm</td>
</tr>