Skip to content

Commit dff3884

Browse files
authored
fix(view): render doctype and html tags properly (#910)
1 parent 9fe4466 commit dff3884

File tree

5 files changed

+51
-7
lines changed

5 files changed

+51
-7
lines changed

src/Tempest/Core/src/Kernel.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020

2121
final class Kernel
2222
{
23-
public const VERSION = '1.0.0-alpha.5';
23+
public const string VERSION = '1.0.0-alpha.5';
2424

2525
public readonly Container $container;
2626

src/Tempest/View/src/Elements/ElementFactory.php

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
namespace Tempest\View\Elements;
66

77
use Dom\Comment;
8+
use Dom\DocumentType;
89
use Dom\Element as DomElement;
910
use Dom\Node;
1011
use Dom\Text;
@@ -22,8 +23,7 @@ final class ElementFactory
2223
public function __construct(
2324
private readonly ViewConfig $viewConfig,
2425
private readonly Container $container,
25-
) {
26-
}
26+
) {}
2727

2828
public function setViewCompiler(TempestViewCompiler $compiler): self
2929
{
@@ -42,6 +42,12 @@ public function make(Node $node): ?Element
4242

4343
private function makeElement(Node $node, ?Element $parent): ?Element
4444
{
45+
if ($node instanceof DocumentType) {
46+
$content = $node->ownerDocument->saveHTML($node);
47+
48+
return new RawElement(tag: null, content: $content);
49+
}
50+
4551
if ($node instanceof Text) {
4652
if (trim($node->textContent) === '') {
4753
return null;

src/Tempest/View/src/Elements/RawElement.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ final class RawElement implements Element
1414
public function __construct(
1515
private readonly ?string $tag,
1616
private readonly string $content,
17-
array $attributes,
17+
array $attributes = [],
1818
) {
1919
$this->attributes = $attributes;
2020
}

src/Tempest/View/src/Renderers/TempestViewCompiler.php

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ private function retrieveTemplate(string $path): string
8080
return file_get_contents($searchPath);
8181
}
8282

83-
private function parseDom(string $template): NodeList
83+
private function parseDom(string $template): HTMLDocument|NodeList
8484
{
8585
$template = str($template)
8686

@@ -104,6 +104,12 @@ private function parseDom(string $template): NodeList
104104
},
105105
);
106106

107+
if ($template->startsWith(['<html', '<!DOCTYPE', '<!doctype'])) {
108+
// If we're rendering a full HTML document, we'll parse it as is
109+
return HTMLDocument::createFromString($template->toString(), LIBXML_NOERROR | HTML_NO_DEFAULT_NS);
110+
}
111+
112+
// If we're rendering an HTML snippet, we'll wrap it in a div, and return the resulting nodelist
107113
$dom = HTMLDocument::createFromString("<div id='tempest_render'>{$template}</div>", LIBXML_NOERROR | HTML_NO_DEFAULT_NS);
108114

109115
return $dom->getElementById('tempest_render')->childNodes;
@@ -112,11 +118,15 @@ private function parseDom(string $template): NodeList
112118
/**
113119
* @return Element[]
114120
*/
115-
private function mapToElements(NodeList $nodeList): array
121+
private function mapToElements(HTMLDocument|NodeList $nodes): array
116122
{
117123
$elements = [];
118124

119-
foreach ($nodeList as $node) {
125+
if ($nodes instanceof HTMLDocument) {
126+
$nodes = $nodes->childNodes;
127+
}
128+
129+
foreach ($nodes as $node) {
120130
$element = $this->elementFactory->make($node);
121131

122132
if ($element === null) {

tests/Integration/View/TempestViewRendererTest.php

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -474,4 +474,32 @@ public function test_self_closing_component_tags_are_compiled(): void
474474
str_replace(PHP_EOL, '', $this->render('<x-foo foo="bar" :baz="$hello"/><x-foo foo="bar" :baz="$hello"/>')),
475475
);
476476
}
477+
478+
public function test_html_tags(): void
479+
{
480+
$view = <<<'HTML'
481+
<!doctype html>
482+
<html lang="en">
483+
<!-- test comment -->
484+
<head>
485+
<title>Tempest</title>
486+
<meta charset="UTF-8">
487+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
488+
<link href="/main.css" rel="stylesheet">
489+
</head>
490+
<body class="flex justify-center items-center">
491+
492+
<h1 class="text-5xl font-bold text-[#4f95d1]">Tempest</h1>
493+
</body>
494+
</html>
495+
HTML;
496+
497+
$html = $this->render($view);
498+
499+
$this->assertStringContainsString('<!DOCTYPE html>', $html);
500+
$this->assertStringContainsString('<html lang="en">', $html);
501+
$this->assertStringContainsString('<head>', $html);
502+
$this->assertStringContainsString('<body', $html);
503+
$this->assertStringContainsString('<!-- test comment -->', $html);
504+
}
477505
}

0 commit comments

Comments
 (0)