Skip to content

Commit

Permalink
fix(view): attributes for raw elements (#734)
Browse files Browse the repository at this point in the history
  • Loading branch information
brendt authored Nov 15, 2024
1 parent 613b884 commit f89eb5d
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 26 deletions.
46 changes: 22 additions & 24 deletions src/Tempest/View/src/Elements/ElementFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,47 +52,45 @@ private function makeElement(DOMNode $node, ?Element $parent): ?Element
);
}

if (
! $node instanceof DOMElement
$attributes = [];

/** @var DOMAttr $attribute */
foreach ($node->attributes as $attribute) {
$name = str($attribute->name)->camel()->toString();

$attributes[$name] = $attribute->value;
}

if (! $node instanceof DOMElement
|| $node->tagName === 'pre'
|| $node->tagName === 'code'
) {
return new RawElement($node->ownerDocument->saveHTML($node));
|| $node->tagName === 'code') {
$content = '';
foreach ($node->childNodes as $child) {
$content .= $node->ownerDocument->saveHTML($child);
}

return new RawElement(
tag: $node->tagName ?? null,
content: $content,
attributes: $attributes,
);
}

if ($viewComponentClass = $this->viewConfig->viewComponents[$node->tagName] ?? null) {
if (! $viewComponentClass instanceof ViewComponent) {
$viewComponentClass = $this->container->get($viewComponentClass);
}

$attributes = [];

/** @var DOMAttr $attribute */
foreach ($node->attributes as $attribute) {
$name = (string)str($attribute->name)->camel();

$attributes[$name] = $attribute->value;
}

$element = new ViewComponentElement(
$this->compiler,
$viewComponentClass,
$attributes
$attributes,
);
} elseif ($node->tagName === 'x-slot') {
$element = new SlotElement(
name: $node->getAttribute('name') ?: 'slot',
);
} else {
$attributes = [];

/** @var DOMAttr $attribute */
foreach ($node->attributes as $attribute) {
$name = (string)str($attribute->name)->camel();

$attributes[$name] = $attribute->value;
}

$element = new GenericElement(
tag: $node->tagName,
attributes: $attributes,
Expand Down
36 changes: 34 additions & 2 deletions src/Tempest/View/src/Elements/RawElement.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,51 @@

namespace Tempest\View\Elements;

use function Tempest\Support\str;
use Tempest\View\Element;

final class RawElement implements Element
{
use IsElement;

public function __construct(
private readonly string $html,
private readonly ?string $tag,
private readonly string $content,
array $attributes,
) {
$this->attributes = $attributes;
}

public function compile(): string
{
return $this->html;
if ($this->tag === null) {
return $this->content;
}

$attributes = [];

foreach ($this->getAttributes() as $name => $value) {
$name = str($name);

if ($name->startsWith(':')) {
$name = ':' . $name->kebab()->toString();
} else {
$name = $name->kebab()->toString();
}

if ($value) {
$attributes[] = $name . '="' . $value . '"';
} else {
$attributes[] = $name;
}
}

$attributes = implode(' ', $attributes);

if ($attributes !== '') {
$attributes = ' ' . $attributes;
}

return "<{$this->tag}{$attributes}>{$this->content}</{$this->tag}>";
}
}
24 changes: 24 additions & 0 deletions tests/Integration/View/TempestViewRendererDataPassingTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -262,4 +262,28 @@ public function test_boolean_attributes(): void
HTML, value: 'value', selected: false, name: 'name'),
);
}

public function test_expression_attribute_in_raw_element(): void
{
$this->registerViewComponent(
'x-test',
<<<'HTML'
<div><x-slot/></div>
HTML,
);

$html = $this->render(<<<'HTML'
<x-test>
<pre :data-lang="$language"><hello></hello>foo<p>bar</p></pre>
</x-test>
HTML, language: 'php');

$this->assertStringEqualsStringIgnoringLineEndings(
<<<'HTML'
<div><pre data-lang="php"><hello></hello>foo<p>bar</p></pre>
</div>
HTML,
$html
);
}
}

0 comments on commit f89eb5d

Please # to comment.