Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 15 additions & 37 deletions src/Compiler/SlotCompiler.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,24 +26,33 @@ public function __construct(
public function compile(string $slotsVariableName, array $children): string
{
$output = '';
$hasExplicitDefault = $this->hasExplicitDefaultSlot($children);

// Compile implicit default slot from loose content (non-SlotNode children)
if (! $this->hasExplicitDefaultSlot($children)) {
$output .= $this->compileSlot('slot', $this->renderLooseContent($children), '[]', $slotsVariableName) . "\n";
if (! $hasExplicitDefault) {
$output .= '<' . '?php ob_start(); ?>';
}

// Compile each named slot
foreach ($children as $child) {
if ($child instanceof SlotNode) {
$output .= $this->compileSlot(
$output .= ' ' . $this->compileSlot(
$this->resolveSlotName($child),
$this->renderChildren($child->children),
$this->compileSlotAttributes($child),
$slotsVariableName,
) . "\n";
);
} else {
$output .= $child->render();
}
}

if (! $hasExplicitDefault) {
$contentHandler = $this->manager->isFolding()
? '$__blaze->processPassthroughContent(\'trim\', trim(ob_get_clean()))'
: 'trim(ob_get_clean())';

$output .= '<' . '?php ' . $slotsVariableName . '[\'slot\'] = new \Illuminate\View\ComponentSlot(' . $contentHandler . ', []); ?>' . "\n";
}

return $output;
}

Expand All @@ -63,37 +72,6 @@ protected function hasExplicitDefaultSlot(array $children): bool
return false;
}

/**
* Render non-SlotNode children as the default slot content.
*
* @param array<Node> $children
*/
protected function renderLooseContent(array $children): string
{
$content = '';
$previousWasSlot = false;

foreach ($children as $child) {
if ($child instanceof SlotNode) {
$previousWasSlot = true;
continue;
}

$rendered = $child->render();

// Laravel's slot compilation consumes the newline after </x-slot> and adds a leading space.
// We match this by prepending a space and stripping any leading newline.
if ($previousWasSlot) {
$rendered = ' ' . preg_replace('/^\n/', '', $rendered);
}

$content .= $rendered;
$previousWasSlot = false;
}

return $content;
}

/**
* Compile a slot into ob_start/ob_get_clean code.
*/
Expand Down
22 changes: 22 additions & 0 deletions tests/ComparisonTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -99,4 +99,26 @@
</x-card>
</x-card>
BLADE
));

test('conditional slots', fn () => compare(<<<'BLADE'
<x-card>
@if(false)
<x-slot name="header">
Header
</x-slot>
@endif
</x-card>
BLADE
));

test('foldable conditional slots', fn () => compare(<<<'BLADE'
<x-foldable.card>
@if(false)
<x-slot name="header">
Header
</x-slot>
@endif
</x-foldable.card>
BLADE
));
4 changes: 3 additions & 1 deletion tests/Compiler/CompilerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,11 @@
'<?php if (isset($__attrs'. $hash .')) $__attrsOriginal = $__attrs'. $hash .'; ?> ',
'<?php $__attrs'. $hash .' = [\'class\' => \'mt-8\']; ?> ',
'<?php $__slots'. $hash .' = []; ?> ',
'<?php ob_start(); ?> Body <?php $__slots'. $hash .'[\'slot\'] = new \Illuminate\View\ComponentSlot(trim(ob_get_clean()), []); ?> ',
'<?php ob_start(); ?> ',
'<?php ob_start(); ?> Header <?php $__slots'. $hash .'[\'header\'] = new \Illuminate\View\ComponentSlot(trim(ob_get_clean()), [\'class\' => \'p-2\']); ?> ',
'Body ',
'<?php ob_start(); ?> Footer <?php $__slots'. $hash .'[\'footer\'] = new \Illuminate\View\ComponentSlot(trim(ob_get_clean()), [\'class\' => \'mt-4\']); ?> ',
'<?php $__slots'. $hash .'[\'slot\'] = new \Illuminate\View\ComponentSlot(trim(ob_get_clean()), []); ?> ',
'<?php $__blaze->pushData($__attrs'. $hash .'); ?> ',
'<?php $__blaze->pushSlots($__slots'. $hash .'); ?> ',
'<?php _'. $hash .'($__blaze, $__attrs'. $hash .', $__slots'. $hash .', [], isset($this) ? $this : null); ?> ',
Expand Down
Loading