Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
47 / 47
100.00% covered (success)
100.00%
35 / 35
CRAP
n/a
0 / 0
Epic64\Elem\_applyCommon
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
4
Epic64\Elem\el
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
Epic64\Elem\a
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
Epic64\Elem\div
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
Epic64\Elem\span
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
Epic64\Elem\p
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
Epic64\Elem\h
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
Epic64\Elem\img
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
Epic64\Elem\button
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
Epic64\Elem\input
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
Epic64\Elem\form
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
Epic64\Elem\label
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
Epic64\Elem\ul
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
Epic64\Elem\ol
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
Epic64\Elem\li
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
Epic64\Elem\table
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
Epic64\Elem\tr
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
Epic64\Elem\td
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
Epic64\Elem\th
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
Epic64\Elem\textarea
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
Epic64\Elem\select
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
Epic64\Elem\html
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
Epic64\Elem\head
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
Epic64\Elem\body
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
Epic64\Elem\title
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
Epic64\Elem\meta
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
Epic64\Elem\style
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
Epic64\Elem\script
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
Epic64\Elem\link
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
Epic64\Elem\stylesheet
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
Epic64\Elem\icon
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
Epic64\Elem\font
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
2
Epic64\Elem\text
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
Epic64\Elem\raw
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
Epic64\Elem\list_of
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
2
1<?php
2
3declare(strict_types=1);
4
5namespace Epic64\Elem;
6
7use Epic64\Elem\Elements\Anchor;
8use Epic64\Elem\Elements\Body;
9use Epic64\Elem\Elements\Button;
10use Epic64\Elem\Elements\Div;
11use Epic64\Elem\Elements\Form;
12use Epic64\Elem\Elements\Head;
13use Epic64\Elem\Elements\Heading;
14use Epic64\Elem\Elements\Html;
15use Epic64\Elem\Elements\Image;
16use Epic64\Elem\Elements\Input;
17use Epic64\Elem\Elements\Label;
18use Epic64\Elem\Elements\Link;
19use Epic64\Elem\Elements\ListItem;
20use Epic64\Elem\Elements\Meta;
21use Epic64\Elem\Elements\OrderedList;
22use Epic64\Elem\Elements\Paragraph;
23use Epic64\Elem\Elements\RawHtml;
24use Epic64\Elem\Elements\Script;
25use Epic64\Elem\Elements\Select;
26use Epic64\Elem\Elements\Span;
27use Epic64\Elem\Elements\Style;
28use Epic64\Elem\Elements\Table;
29use Epic64\Elem\Elements\TableCell;
30use Epic64\Elem\Elements\TableHeader;
31use Epic64\Elem\Elements\TableRow;
32use Epic64\Elem\Elements\Text;
33use Epic64\Elem\Elements\Textarea;
34use Epic64\Elem\Elements\Title;
35use Epic64\Elem\Elements\UnorderedList;
36
37/**
38 * Apply common attributes (id and class) to an element.
39 * @template T of Element
40 * @param T $element
41 * @return T
42 */
43function _applyCommon(Element $element, ?string $id, ?string $class): Element
44{
45    if ($id !== null) {
46        $element->id($id);
47    }
48    if ($class !== null && $class !== '') {
49        $element->class(...explode(' ', $class));
50    }
51    return $element;
52}
53
54function el(string $tag, ?string $id = null, ?string $class = null, ?string $text = null): Element
55{
56    return _applyCommon(new Element($tag, $text), $id, $class);
57}
58
59function a(string $href, ?string $id = null, ?string $class = null, ?string $text = null): Anchor
60{
61    /** @var Anchor */
62    return _applyCommon(new Anchor($href, $text), $id, $class);
63}
64
65function div(?string $id = null, ?string $class = null, ?string $text = null): Div
66{
67    /** @var Div */
68    return _applyCommon(new Div($text), $id, $class);
69}
70
71function span(?string $id = null, ?string $class = null, ?string $text = null): Span
72{
73    /** @var Span */
74    return _applyCommon(new Span($text), $id, $class);
75}
76
77function p(?string $id = null, ?string $class = null, ?string $text = null): Paragraph
78{
79    /** @var Paragraph */
80    return _applyCommon(new Paragraph($text), $id, $class);
81}
82
83function h(int $level, ?string $id = null, ?string $class = null, ?string $text = null): Heading
84{
85    /** @var Heading */
86    return _applyCommon(new Heading($level, $text), $id, $class);
87}
88
89function img(string $src, ?string $id = null, ?string $class = null, string $alt = ''): Image
90{
91    /** @var Image */
92    return _applyCommon(new Image($src, $alt), $id, $class);
93}
94
95function button(?string $id = null, ?string $class = null, ?string $text = null, string $type = 'button'): Button
96{
97    /** @var Button */
98    return _applyCommon(new Button($text, $type), $id, $class);
99}
100
101function input(string $type, ?string $id = null, ?string $class = null, ?string $name = null): Input
102{
103    /** @var Input */
104    return _applyCommon(new Input($type, $name), $id, $class);
105}
106
107function form(?string $id = null, ?string $class = null, ?string $action = null, string $method = 'post'): Form
108{
109    /** @var Form */
110    return _applyCommon(new Form($action, $method), $id, $class);
111}
112
113function label(?string $id = null, ?string $class = null, ?string $text = null, ?string $for = null): Label
114{
115    /** @var Label */
116    return _applyCommon(new Label($text, $for), $id, $class);
117}
118
119function ul(?string $id = null, ?string $class = null): UnorderedList
120{
121    /** @var UnorderedList */
122    return _applyCommon(new UnorderedList(), $id, $class);
123}
124
125function ol(?string $id = null, ?string $class = null): OrderedList
126{
127    /** @var OrderedList */
128    return _applyCommon(new OrderedList(), $id, $class);
129}
130
131function li(?string $id = null, ?string $class = null, ?string $text = null): ListItem
132{
133    /** @var ListItem */
134    return _applyCommon(new ListItem($text), $id, $class);
135}
136
137function table(?string $id = null, ?string $class = null): Table
138{
139    /** @var Table */
140    return _applyCommon(new Table(), $id, $class);
141}
142
143function tr(?string $id = null, ?string $class = null): TableRow
144{
145    /** @var TableRow */
146    return _applyCommon(new TableRow(), $id, $class);
147}
148
149function td(?string $id = null, ?string $class = null, ?string $text = null): TableCell
150{
151    /** @var TableCell */
152    return _applyCommon(new TableCell($text), $id, $class);
153}
154
155function th(?string $id = null, ?string $class = null, ?string $text = null): TableHeader
156{
157    /** @var TableHeader */
158    return _applyCommon(new TableHeader($text), $id, $class);
159}
160
161function textarea(?string $id = null, ?string $class = null, ?string $name = null, ?string $content = null): Textarea
162{
163    /** @var Textarea */
164    return _applyCommon(new Textarea($name, $content), $id, $class);
165}
166
167function select(?string $id = null, ?string $class = null, ?string $name = null): Select
168{
169    /** @var Select */
170    return _applyCommon(new Select($name), $id, $class);
171}
172
173function html(?string $lang = null): Html
174{
175    return new Html($lang);
176}
177
178function head(): Head
179{
180    return new Head();
181}
182
183function body(?string $id = null, ?string $class = null): Body
184{
185    /** @var Body */
186    return _applyCommon(new Body(), $id, $class);
187}
188
189function title(?string $text = null): Title
190{
191    return new Title($text);
192}
193
194function meta(?string $charset = null, ?string $name = null, ?string $content = null): Meta
195{
196    return new Meta($charset, $name, $content);
197}
198
199function style(?string $css = null): Style
200{
201    return new Style($css);
202}
203
204function script(?string $code = null, ?string $src = null): Script
205{
206    return new Script($code, $src);
207}
208
209/**
210 * Create a <link> element for external resources.
211 *
212 * Note: For stylesheets, you probably want to use the stylesheet() helper instead:
213 * stylesheet('/css/style.css')
214 */
215function link(?string $href = null, ?string $rel = null): Link
216{
217    return new Link($href, $rel);
218}
219
220function stylesheet(string $href): Link
221{
222    return new Link($href, 'stylesheet');
223}
224
225function icon(string $href, ?string $type = null): Link
226{
227    $link = new Link($href, 'icon');
228    if ($type !== null) {
229        $link->type($type);
230    }
231    return $link;
232}
233
234function font(string $href, ?string $type = null): Link
235{
236    $link = new Link($href, 'preload');
237    $link->attr('as', 'font');
238    $link->attr('crossorigin', 'anonymous');
239    if ($type !== null) {
240        $link->type($type);
241    }
242    return $link;
243}
244
245/**
246 * Create a text node that will be safely escaped when rendered.
247 *
248 * This is useful when you want to explicitly create a text node as a sibling
249 * to other elements, rather than using the `text` parameter of an element.
250 *
251 * @example
252 * ```php
253 * div()(
254 *     text('Hello, '),
255 *     span(class: 'name', text: $username),
256 *     text('!')
257 * )
258 * ```
259 */
260function text(string $content): Text
261{
262    return new Text($content);
263}
264
265/**
266 * Create a raw HTML fragment that will not be escaped.
267 *
268 * WARNING: Only use this with trusted content. Using raw HTML with
269 * user-provided input can lead to XSS vulnerabilities.
270 *
271 * @example
272 * ```php
273 * div()(
274 *     raw('<strong>Bold text</strong>'),
275 *     raw($trustedHtmlFromMarkdownParser)
276 * )
277 * ```
278 */
279function raw(string $html): RawHtml
280{
281    return new RawHtml($html);
282}
283
284/**
285 * Create a Collection from an iterable for fluent transformations.
286 *
287 * Example:
288 *   list_of($users)
289 *       ->filter(fn($u) => $u->isAdmin())
290 *       ->map(fn($u) => div(class: 'user', text: $u->name))
291 *
292 * @template T
293 * @param iterable<T> $items
294 * @return ElementsList<T>
295 */
296function list_of(iterable $items): ElementsList
297{
298    return new ElementsList(is_array($items) ? $items : iterator_to_array($items));
299}