A fully extensible HTML-Builder supporting emmet input
composer require stefanwimmer128/html-builderuse function Stefanwimmer128\HtmlBuilder\render;
use function Stefanwimmer128\HtmlBuilder\h;
use function Stefanwimmer128\HtmlBuilder\capture;
use function Stefanwimmer128\HtmlBuilder\map;
$test = '<p>TEST</p>';
$values = [
'a' => 0,
'b' => 1,
'c' => 2,
];
render(h('xml[version="1.0" standalone=yes]', [], [
h('doctype', 'html', [
h('html[lang=en]', [], [
h('head > title{Hello World!}'),
h('body', [], [
h('.container.container-content#container-content-main', [], [
h('a[href="#"][disabled]', 'LINK'),
'<p>TEST</p>',
capture('printf', '%s', $test)
]),
h('comment', 'COMMENT'),
h('p', ['data-values' => json_encode($values, JSON_THROW_ON_ERROR)], [
h('b', 'LIST:'),
h('br'),
map($values, fn($value, $key) => h('span', ['data-key' => $key], $value))
])
])
])
])
]));<?xml version="1.0" standalone="yes" ?><!DOCTYPE html><html lang="en"><head><title>Hello World!</title></head><body><div class="container container-content" id="container-content-main"><a href="#" disabled>LINK</a><p>TEST</p><p>TEST</p></div><!-- COMMENT --><p data-values="{"a":0,"b":1,"c":2}"><b>LIST:</b><br /><span data-key="a">0</span><span data-key="b">1</span><span data-key="c">2</span></p></body></html>The following elements are special.
Thus, if you want to use the keywords as simple tags, you will have to use the special tag function:
use function Stefanwimmer128\HtmlBuilder\render;
use function Stefanwimmer128\HtmlBuilder\h;
use function Stefanwimmer128\HtmlBuilder\tag;
render(h('comment', 'Test'));
render(tag('comment', 'Test'));<!-- Test -->
<comment>Test</comment>Generate HTML comment. Any string(s) or HtmlElement(s) can be used as children.
use function Stefanwimmer128\HtmlBuilder\render;
use function Stefanwimmer128\HtmlBuilder\h;
render(h('comment', 'Test'));<!-- Test -->Generate HTML doctype. Can receive children, that will be rendered after tag.
use function Stefanwimmer128\HtmlBuilder\render;
use function Stefanwimmer128\HtmlBuilder\h;
render(h('doctype', 'html', ...$children));<!DOCTYPE html>...children...Generates lorem ipsum text (default: 30 words).
To set the number of words to generate append it to the tag: lorem20 generates 20 words, lipsum40 generates 40 words.
use function Stefanwimmer128\HtmlBuilder\render;
use function Stefanwimmer128\HtmlBuilder\h;
render(h('lorem50'));Generates 50 words of lorem ipsum.
Create XML header. Works pretty similar to a html tag.
use function Stefanwimmer128\HtmlBuilder\render;
use function Stefanwimmer128\HtmlBuilder\h;
render(h('xml[version="1.0"]', [], ...$children));<?xml version="1.0" ?>...children...h(string $input, ...$args): HtmlElementCreate element from input using parser (default: Emmet)tag(string $tag = 'div', ...$args): HtmlTagCreate tag elementtext(string $text): HtmlTextCreate text elementraw(string $value): RawStringCreate raw stringcapture(callable $callable, ...$args): RawStringCaptures output (echo) and returns it as raw stringmap(array $array, callable $callable): arrayarray_map with keysrender(...$elements): stringRender elements as HTML
Create element from input using parser (default: Emmet)
Also works like tag().
use function Stefanwimmer128\HtmlBuilder\render;
use function Stefanwimmer128\HtmlBuilder\h;
render(h('table[border=0] > thead > .row > .col', 'Content'));
render(h('div', [], 'Some text <b>with html</b>'));<table border="0"><thead><tr class="row"><td class="col">Content</td></tr></thead></table>
<div>Some text <p>with html</b></div>Create tag element
use function Stefanwimmer128\HtmlBuilder\render;
use function Stefanwimmer128\HtmlBuilder\tag;
render(tag('div', ['class' => 'container'], [
'Text',
tag('p', 'Some text <b>with html</b>')
]));<div class="container">Text<p>Some text <p>with html</b></p></div>Create text element
This is automatically applied to strings that are passed as children to h() or tag().
use function Stefanwimmer128\HtmlBuilder\render;
use function Stefanwimmer128\HtmlBuilder\text;
render(text('Some text <b>with html</b>'));Some text <p>with html</b>Create raw string
use function Stefanwimmer128\HtmlBuilder\render;
use function Stefanwimmer128\HtmlBuilder\raw;
render(raw('Some text <b>with html</b>'));Some text <b>with html</b>Captures output (echo) and returns it as raw string
Useful with functions that instead of returning the markup directly output it (eg. Wordpress).
use function Stefanwimmer128\HtmlBuilder\render;
use function Stefanwimmer128\HtmlBuilder\tag;
use function Stefanwimmer128\HtmlBuilder\capture;
render(tag('div', [], capture('the_widget', 'widget')));<div>...widget markup...</div>array_map with keys
use function Stefanwimmer128\HtmlBuilder\render;
use function Stefanwimmer128\HtmlBuilder\tag;
use function Stefanwimmer128\HtmlBuilder\map;
$values = [
'key0' => 'value0',
'key1' => 'value1',
];
render(tag('ul', [], map($values, fn($value, $key) => tag('li', ['id' => $key], $value))));<ul><li id="key0">value0</li><li id="key1">value1</li></ul>Render elements as HTML
See all the above.
Any custom element must extend \Stefanwimmer128\HtmlBuilder\HtmlElement.
First you create your element class:
use Stefanwimmer128\HtmlBuilder\HtmlElement;
class CustomElement extends HtmlElement {
private string $someData;
public function __construct(string $someData) {
$this->someData = $someData;
}
public function render(): string {
return sprintf('(%s)', $this->someData);
}
}If your element is tag-like, you might want to extend \Stefanwimmer128\HtmlBuilder\HtmlTag:
use Stefanwimmer128\HtmlBuilder\HtmlTag;
class CustomElement extends HtmlTag {
public function __construct(...$args) {
parent::__construct('custom', ...$args);
}
public function render(): string {
return sprintf('(%s)%s', $this->renderAttributes(), $this->renderChildren());
}
}If your custom element should receive parsed information, your element must implement \Stefanwimmer128\HtmlBuilder\Parser\ParserCompatibleElement.
After which you have to register your element, by putting this code before your usage of the element:
use Stefanwimmer128\HtmlBuilder\HtmlElement;
HtmlElement::$ELEMENTS['custom'] = CustomElement::class;Any parser must extend \Stefanwimmer128\HtmlBuilder\Parser\AbstractParser.
Since creating a custom parser is very much tied to what you want to parse, please orientate yourself using the included \Stefanwimmer128\HtmlBuilder\Parser\Emmet\EmmetParser.
use Stefanwimmer128\HtmlBuilder\Parser\AbstractParser;
class CustomParser extends AbstractParser {
public function __construct(string $input) {
// your parsing logic goes here
}
public function getTag(): string {
// return tag here
}
public function getAttributes(): array {
// return attributes here
}
public function getClasses(): array {
// return classes here
}
public function getId(): ?string {
// return id here if provided or null
}
public function getText() : ?string {
// return text here if provided or null
}
public function getChild() : ?AbstractParser {
// return child here if provided or null
}
public function isSelfclosing() : ?bool{
// return whether tag self-closes if provided or null
}
}After which you can set your parser by:
use Stefanwimmer128\HtmlBuilder\Parser\AbstractParser;
AbstractParser::$DEFAULT_PARSER = CustomParser::class;