Skip to content

Commit

Permalink
Merge pull request #98 from tronsha/fix/child-component-in-slot
Browse files Browse the repository at this point in the history
Fix handleSlots
  • Loading branch information
Macavity authored Apr 23, 2021
2 parents 188859e + 60404e8 commit 36f1477
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 74 deletions.
158 changes: 84 additions & 74 deletions src/Compiler.php
Original file line number Diff line number Diff line change
Expand Up @@ -315,81 +315,8 @@ public function convertNode(DOMNode $node, int $level = 0): DOMNode
$this->addScopedAttribute($node, $level);
}

// Registered Component
if (in_array($node->nodeName, array_keys($this->components))) {
$matchedComponent = $this->components[$node->nodeName];
$usedComponent = new Component($matchedComponent->getName(), $matchedComponent->getPath());

if ($node->hasAttributes()) {
/** @var DOMAttr $attribute */
foreach ($node->attributes as $attribute) {
if (strpos($attribute->name, 'v-bind:') === 0 || strpos($attribute->name, ':') === 0) {
$name = substr($attribute->name, strpos($attribute->name, ':') + 1);
$value = $attribute->value;

if (substr_count($value, '`')) {
$value = $this->refactorTemplateString($attribute->value);
} else {
$value = $this->builder->refactorCondition($value);
}

$usedComponent->addProperty($name, $value, true);
} else {
$usedComponent->addProperty($attribute->name, '"' . $attribute->value . '"', false);
}
}
}

foreach (iterator_to_array($node->childNodes) as $childNode) {
$this->convertNode($childNode, $level + 1);
}

// Slots
if ($node->hasChildNodes()) {
$this->handleNamedSlotsInclude($node, $usedComponent);
// Slots (Default)
if ($node->hasChildNodes() && !$usedComponent->hasSlot(Slot::SLOT_DEFAULT_NAME)) {
$this->addSlot(Slot::SLOT_DEFAULT_NAME, $node, $usedComponent);
}
} else {
$usedComponent->addEmptyDefaultSlot();
}

// Include Partial
$include = $this->document->createTextNode(
$this->builder->createIncludePartial(
$usedComponent->getPath(),
$this->preparePropertiesForInclude($usedComponent->getProperties(), $level === 1),
$this->vBind
)
);

$node->parentNode->insertBefore($include, $node);

if ($usedComponent->hasSlots()) {
foreach ($usedComponent->getSlots() as $slotName => $slot) {
// Add variable which contains the content (set)
$openSet = $this->document->createTextNode(
$this->builder->createSet($slot->getSlotValueName())
);
$node->parentNode->insertBefore($openSet, $include);

$setContent = $this->document->createTextNode($slot->getSlotContentVariableString());

$node->parentNode->insertBefore($setContent, $include);

// Close variable (endset)
$closeSet = $this->document->createTextNode(
$this->builder->closeSet()
);
$node->parentNode->insertBefore($closeSet, $include);
}
}

// Remove original node
$this->nodeHelper->removeNode($node);

return $node;
return $this->handleComponent($node, $level);
}

if ($node instanceof DOMElement) {
Expand All @@ -416,6 +343,83 @@ public function convertNode(DOMNode $node, int $level = 0): DOMNode
return $node;
}

private function handleComponent(DOMNode $node, int $level): DOMNode
{
$matchedComponent = $this->components[$node->nodeName];
$usedComponent = new Component($matchedComponent->getName(), $matchedComponent->getPath());

if ($node->hasAttributes()) {
/** @var DOMAttr $attribute */
foreach ($node->attributes as $attribute) {
if (strpos($attribute->name, 'v-bind:') === 0 || strpos($attribute->name, ':') === 0) {
$name = substr($attribute->name, strpos($attribute->name, ':') + 1);
$value = $attribute->value;

if (substr_count($value, '`')) {
$value = $this->refactorTemplateString($attribute->value);
} else {
$value = $this->builder->refactorCondition($value);
}

$usedComponent->addProperty($name, $value, true);
} else {
$usedComponent->addProperty($attribute->name, '"' . $attribute->value . '"', false);
}
}
}

foreach (iterator_to_array($node->childNodes) as $childNode) {
$this->convertNode($childNode, $level + 1);
}

// Slots
if ($node->hasChildNodes()) {
$this->handleNamedSlotsInclude($node, $usedComponent);
// Slots (Default)
if ($node->hasChildNodes() && !$usedComponent->hasSlot(Slot::SLOT_DEFAULT_NAME)) {
$this->addSlot(Slot::SLOT_DEFAULT_NAME, $node, $usedComponent);
}
} else {
$usedComponent->addEmptyDefaultSlot();
}

// Include Partial
$include = $this->document->createTextNode(
$this->builder->createIncludePartial(
$usedComponent->getPath(),
$this->preparePropertiesForInclude($usedComponent->getProperties(), $level === 1),
$this->vBind
)
);

$node->parentNode->insertBefore($include, $node);

if ($usedComponent->hasSlots()) {
foreach ($usedComponent->getSlots() as $slotName => $slot) {
// Add variable which contains the content (set)
$openSet = $this->document->createTextNode(
$this->builder->createSet($slot->getSlotValueName())
);
$node->parentNode->insertBefore($openSet, $include);

$setContent = $this->document->createTextNode($slot->getSlotContentVariableString());

$node->parentNode->insertBefore($setContent, $include);

// Close variable (endset)
$closeSet = $this->document->createTextNode(
$this->builder->closeSet()
);
$node->parentNode->insertBefore($closeSet, $include);
}
}

// Remove original node
$this->nodeHelper->removeNode($node);

return $node;
}

/**
* @param Property[] $variables
*
Expand Down Expand Up @@ -1347,6 +1351,12 @@ protected function handleSlots(DOMElement $node): void
return;
}

if ($node->hasChildNodes()) {
foreach ($node->childNodes as $childNode) {
$this->convertNode($childNode);
}
}

$slotFallback = $node->hasChildNodes() ? $this->innerHtmlOfNode($node) : null;

$slotName = Slot::SLOT_PREFIX;
Expand Down
4 changes: 4 additions & 0 deletions tests/fixtures/vue-slot/child-component-in-slot.twig
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{% set slot_default_fallback %}{% include "/templates/ChildComponent.twig" with { 'slot_default': "", 'class': "", 'style': "" } %}{% endset %}
<div class="{{ class|default('') }}" style="{{ style|default('') }}">
{{ slot_default|default(slot_default_fallback) }}
</div>
15 changes: 15 additions & 0 deletions tests/fixtures/vue-slot/child-component-in-slot.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<template>
<div>
<slot>
<ChildComponent/>
</slot>
</div>
</template>
<script>
export default {
name: 'component-with-child.vue',
component: {
ChildComponent,
}
};
</script>

0 comments on commit 36f1477

Please sign in to comment.