Skip to content

Commit 420e5d8

Browse files
authored
fix(view): self-closing view component tags (#818)
1 parent 8b95679 commit 420e5d8

File tree

2 files changed

+42
-5
lines changed

2 files changed

+42
-5
lines changed

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

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
use Tempest\View\Element;
1313
use Tempest\View\Elements\ElementFactory;
1414
use function Tempest\path;
15+
use function Tempest\Support\str;
1516
use const Dom\HTML_NO_DEFAULT_NS;
1617

1718
final readonly class TempestViewCompiler
@@ -81,11 +82,27 @@ private function retrieveTemplate(string $path): string
8182

8283
private function parseDom(string $template): NodeList
8384
{
84-
$template = str_replace(
85-
search: array_keys(self::TOKEN_MAPPING),
86-
replace: array_values(self::TOKEN_MAPPING),
87-
subject: $template,
88-
);
85+
$template = str($template)
86+
87+
// Escape PHP tags
88+
->replace(
89+
search: array_keys(self::TOKEN_MAPPING),
90+
replace: array_values(self::TOKEN_MAPPING),
91+
)
92+
93+
// Convert self-closing tags
94+
->replaceRegex(
95+
regex: '/<x-(?<element>.*?)\/>/',
96+
replace: function (array $match) {
97+
$closingTag = str($match['element'])->before(' ')->toString();
98+
99+
return sprintf(
100+
'<x-%s></x-%s>',
101+
$match['element'],
102+
$closingTag,
103+
);
104+
},
105+
);
89106

90107
$dom = HTMLDocument::createFromString("<div id='tempest_render'>{$template}</div>", LIBXML_NOERROR | HTML_NO_DEFAULT_NS);
91108

tests/Integration/View/TempestViewRendererTest.php

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -439,4 +439,24 @@ public function test_slot_with_comment(): void
439439
),
440440
);
441441
}
442+
443+
public function test_self_closing_component_tags_are_compiled(): void
444+
{
445+
$this->registerViewComponent('x-foo', '<div>foo</div>');
446+
447+
$this->assertStringEqualsStringIgnoringLineEndings(
448+
'<div>foo</div><div>foo</div>',
449+
str_replace(PHP_EOL, '', $this->render('<x-foo /><x-foo />')),
450+
);
451+
452+
$this->assertStringEqualsStringIgnoringLineEndings(
453+
'<div>foo</div><div>foo</div>',
454+
str_replace(PHP_EOL, '', $this->render('<x-foo/><x-foo/>')),
455+
);
456+
457+
$this->assertStringEqualsStringIgnoringLineEndings(
458+
'<div>foo</div><div>foo</div>',
459+
str_replace(PHP_EOL, '', $this->render('<x-foo foo="bar" :baz="$hello"/><x-foo foo="bar" :baz="$hello"/>')),
460+
);
461+
}
442462
}

0 commit comments

Comments
 (0)