From a7f454c4d4b84fd7a1e18f77cfbc38d032481936 Mon Sep 17 00:00:00 2001 From: Taylor Otwell Date: Fri, 12 May 2023 14:36:39 -0500 Subject: [PATCH] Name attributes on slots (#47065) * support name attributes on slots if using inline syntax * add file * formatting and another test * simplify conditions --- .../View/Compilers/ComponentTagCompiler.php | 15 +++++-- tests/Integration/View/BladeTest.php | 44 +++++++++++++++++++ .../components/input-with-slot.blade.php | 7 +++ 3 files changed, 63 insertions(+), 3 deletions(-) create mode 100644 tests/Integration/View/templates/components/input-with-slot.blade.php diff --git a/src/Illuminate/View/Compilers/ComponentTagCompiler.php b/src/Illuminate/View/Compilers/ComponentTagCompiler.php index 4bfa870aafda..f052cf3bcc59 100644 --- a/src/Illuminate/View/Compilers/ComponentTagCompiler.php +++ b/src/Illuminate/View/Compilers/ComponentTagCompiler.php @@ -505,7 +505,8 @@ public function compileSlots(string $value) \s* x[\-\:]slot (?:\:(?\w+(?:-\w+)*))? - (?:\s+(:?)name=(?(\"[^\"]+\"|\\\'[^\\\']+\\\'|[^\s>]+)))? + (?:\s+name=(?(\"[^\"]+\"|\\\'[^\\\']+\\\'|[^\s>]+)))? + (?:\s+\:name=(?(\"[^\"]+\"|\\\'[^\\\']+\\\'|[^\s>]+)))? (? (?: \s+ @@ -544,13 +545,14 @@ public function compileSlots(string $value) /x"; $value = preg_replace_callback($pattern, function ($matches) { - $name = $this->stripQuotes($matches['inlineName'] ?: $matches['name']); + $name = $this->stripQuotes($matches['inlineName'] ?: $matches['name'] ?: $matches['boundName']); if (Str::contains($name, '-') && ! empty($matches['inlineName'])) { $name = Str::camel($name); } - if ($matches[2] !== ':') { + // If the name was given as a simple string, we will wrap it in quotes as if it was bound for convenience... + if (! empty($matches['inlineName']) || ! empty($matches['name'])) { $name = "'{$name}'"; } @@ -558,6 +560,13 @@ public function compileSlots(string $value) $attributes = $this->getAttributesFromAttributeString($matches['attributes']); + // If an inline name was provided and a name or bound name was *also* provided, we will assume the name should be an attribute... + if (! empty($matches['inlineName']) && (! empty($matches['name']) || ! empty($matches['boundName']))) { + $attributes = ! empty($matches['name']) + ? array_merge($attributes, $this->getAttributesFromAttributeString('name='.$matches['name'])) + : array_merge($attributes, $this->getAttributesFromAttributeString(':name='.$matches['boundName'])); + } + return " @slot({$name}, null, [".$this->attributesToString($attributes).']) '; }, $value); diff --git a/tests/Integration/View/BladeTest.php b/tests/Integration/View/BladeTest.php index b3d8f51eedc7..17e149ece9f1 100644 --- a/tests/Integration/View/BladeTest.php +++ b/tests/Integration/View/BladeTest.php @@ -122,6 +122,50 @@ public function test_consume_with_props()
Slot: F, Color: yellow, Default: foo
', trim($view)); } + public function test_name_attribute_can_be_used_if_using_short_slot_names() + { + $content = Blade::render(' + Test +'); + + $this->assertSame('
+ +
', trim($content)); + } + + public function test_name_attribute_cant_be_used_if_not_using_short_slot_names() + { + $content = Blade::render(' + Test +'); + + $this->assertSame('
+ +
', trim($content)); + } + + public function test_bound_name_attribute_can_be_used_if_using_short_slot_names() + { + $content = Blade::render(' + Test +'); + + $this->assertSame('
+ +
', trim($content)); + } + + public function test_bound_name_attribute_can_be_used_if_using_short_slot_names_and_not_first_attribute() + { + $content = Blade::render(' + Test +'); + + $this->assertSame('
+ +
', trim($content)); + } + protected function getEnvironmentSetUp($app) { $app['config']->set('view.paths', [__DIR__.'/templates']); diff --git a/tests/Integration/View/templates/components/input-with-slot.blade.php b/tests/Integration/View/templates/components/input-with-slot.blade.php new file mode 100644 index 000000000000..810a1912fdcc --- /dev/null +++ b/tests/Integration/View/templates/components/input-with-slot.blade.php @@ -0,0 +1,7 @@ +@props([ + 'input' +]) + +
+ attributes->class('input') }} /> +