lnear / html
Utility functions for rendering html
Requires
- php: ^8.0
Requires (Dev)
- pestphp/pest: ^2.34
- symfony/console: ^7.1
README
This library provides a collection of functions for generating HTML elements and their attributes based on the HTML Living Standard.
Installation
To install the library, use the following command:
composer require lnear/html
Usage
The library provides functions named after HTML elements, which accept attributes as named arguments. There are two namespaces available: html
and html\strict
.
html\strict
Namespace: Only allows attributes that are valid for the element according to the HTML Living Standard.html
Namespace: More permissive, allowing any attribute to be passed to the function. Custom attribute names should be in camelCase.
Examples
// Using the strict namespace html\strict\a(href: 'https://example.com', dataFoo: 'bar'); // Throws an InvalidArgumentException // Using the permissive namespace html\a(href: 'https://example.com', dataFoo: 'bar'); // <a href="https://example.com" data-foo="bar"></a>
Other than the attribute restrictions, the two namespaces function identically. The following examples use the html
namespace, but you can use the html\strict
namespace to enforce the HTML standard.
data-*
Attributes
To pass data-*
attributes with the html\strict
namespace, use the dataset
attribute as an associative array with keys as the attribute names without the data-
prefix.
use function html\strict\a; echo a(href: 'https://example.com', dataset: ['fooBar' => 'baz']); // <a href="https://example.com" data-foo-bar="baz"></a> echo a(href: 'https://example.com', dataset: ['fooBar' => 'baz', 'barFoo' => 'qux']); // <a href="https://example.com" data-foo-bar="baz" data-bar-foo="qux"></a>
All functions return a Stringable
class (html\RenderResult
) of the HTML element they represent. The only exception is the var
function, which is named variable
to avoid conflicts with the reserved keyword var
.
Body Argument
The body
argument is present in all non-self-closing elements, used to add text or other elements inside the element.
use function html\div; echo div(body: 'Hello, World!'); // <div>Hello, World!</div>
The body
argument is also the first argument in these functions, so the argument name can be omitted.
use function html\div; echo div('Hello, World!'); // <div>Hello, World!</div>
Nested Elements
More complex elements can be created by nesting functions, with the body
argument as an array of elements.
use function html\{div, a, p}; echo div( class: 'container', body: [ a('Click me!', href: 'https://example.com', target: '_blank', rel: 'noopener noreferrer'), p('This is a paragraph.') ] ); // <div class="container"><a href="https://example.com" target="_blank" rel="noopener noreferrer">Click me!</a><p>This is a paragraph.</p></div>
Encoding
The html\RenderResult
class implements the Stringable
interface, allowing its use in any context where a string is expected. It can also be used to bypass HTML encoding of a string.
use function html\{div, RenderResult}; $unsafe = '<script>alert("XSS")</script>'; echo div(body: $unsafe); // Default encoding: <script>alert("XSS")</script> $safe = RenderResult::wrap($unsafe); // Explicit encoding echo div(body: $safe); // No double encoding: <div><script>alert("XSS")</script></div> $byPass = RenderResult::encoded($unsafe); // String already encoded echo div(body: $byPass); // <div><script>alert("XSS")</script></div> // Or use the bypass helper function use function html\bypass; echo div(body: bypass($unsafe)); // <div><script>alert("XSS")</script></div>
Elements
All elements share the following global attributes:
The following elements only have the global attributes:
The following elements have additional attributes: