Skip to content

Commit 83ec510

Browse files
authored
[8.x] Fix extra space on blade class components that are inline (#35874)
This fixes extra spacing before and after Blade class components.
1 parent 67451f9 commit 83ec510

File tree

6 files changed

+56
-43
lines changed

6 files changed

+56
-43
lines changed

src/Illuminate/View/Compilers/BladeCompiler.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,10 @@ public function compileString($value)
251251
$result = $this->addFooters($result);
252252
}
253253

254-
return $result;
254+
return str_replace(
255+
['##BEGIN-COMPONENT-CLASS##', '##END-COMPONENT-CLASS##'],
256+
'',
257+
$result);
255258
}
256259

257260
/**

src/Illuminate/View/Compilers/ComponentTagCompiler.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ protected function compileSelfClosingTags(string $value)
193193

194194
$attributes = $this->getAttributesFromAttributeString($matches['attributes']);
195195

196-
return $this->componentString($matches[1], $attributes)."\n@endcomponentClass ";
196+
return $this->componentString($matches[1], $attributes)."\n@endComponentClass##END-COMPONENT-CLASS##";
197197
}, $value);
198198
}
199199

@@ -230,7 +230,7 @@ protected function componentString(string $component, array $attributes)
230230
$parameters = $data->all();
231231
}
232232

233-
return " @component('{$class}', '{$component}', [".$this->attributesToString($parameters, $escapeBound = false).'])
233+
return "##BEGIN-COMPONENT-CLASS##@component('{$class}', '{$component}', [".$this->attributesToString($parameters, $escapeBound = false).'])
234234
<?php $component->withAttributes(['.$this->attributesToString($attributes->all(), $escapeAttributes = $class !== DynamicComponent::class).']); ?>';
235235
}
236236

@@ -384,7 +384,7 @@ public function partitionDataAndAttributes($class, array $attributes)
384384
*/
385385
protected function compileClosingTags(string $value)
386386
{
387-
return preg_replace("/<\/\s*x[-\:][\w\-\:\.]*\s*>/", ' @endcomponentClass ', $value);
387+
return preg_replace("/<\/\s*x[-\:][\w\-\:\.]*\s*>/", ' @endComponentClass##END-COMPONENT-CLASS##', $value);
388388
}
389389

390390
/**

tests/Integration/View/BladeTest.php

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,18 @@ public function test_rendering_the_same_dynamic_component_with_different_attribu
4242
$this->assertSame('<span class="text-medium">
4343
Hello Taylor
4444
</span>
45-
46-
<span >
45+
<span >
4746
Hello Samuel
4847
</span>', trim($view));
4948
}
5049

50+
public function test_inline_link_type_attributes_dont_add_extra_spacing_at_end()
51+
{
52+
$view = View::make('uses-link')->render();
53+
54+
$this->assertSame('This is a sentence with a <a href="https://laravel.com">link</a>.', trim($view));
55+
}
56+
5157
public function test_appendable_attributes()
5258
{
5359
$view = View::make('uses-appendable-panel', ['name' => 'Taylor', 'withInjectedValue' => true])->render();
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
@props(['href'])
2+
3+
<a href="{{ $href }}">{{ $slot }}</a>
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
This is a sentence with a <x-link href="https://laravel.com">link</x-link>.

tests/View/Blade/BladeComponentTagCompilerTest.php

Lines changed: 37 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -40,69 +40,69 @@ public function testBasicComponentParsing()
4040

4141
$result = $this->compiler(['alert' => TestAlertComponent::class])->compileTags('<div><x-alert type="foo" limit="5" @click="foo" wire:click="changePlan(\'{{ $plan }}\')" required /><x-alert /></div>');
4242

43-
$this->assertSame("<div> @component('Illuminate\Tests\View\Blade\TestAlertComponent', 'alert', [])
43+
$this->assertSame("<div>##BEGIN-COMPONENT-CLASS##@component('Illuminate\Tests\View\Blade\TestAlertComponent', 'alert', [])
4444
<?php \$component->withAttributes(['type' => 'foo','limit' => '5','@click' => 'foo','wire:click' => 'changePlan(\''.e(\$plan).'\')','required' => true]); ?>\n".
45-
"@endcomponentClass @component('Illuminate\Tests\View\Blade\TestAlertComponent', 'alert', [])
45+
"@endComponentClass##END-COMPONENT-CLASS####BEGIN-COMPONENT-CLASS##@component('Illuminate\Tests\View\Blade\TestAlertComponent', 'alert', [])
4646
<?php \$component->withAttributes([]); ?>\n".
47-
'@endcomponentClass </div>', trim($result));
47+
'@endComponentClass##END-COMPONENT-CLASS##</div>', trim($result));
4848
}
4949

5050
public function testBasicComponentWithEmptyAttributesParsing()
5151
{
5252
$result = $this->compiler(['alert' => TestAlertComponent::class])->compileTags('<div><x-alert type="" limit=\'\' @click="" required /></div>');
5353

54-
$this->assertSame("<div> @component('Illuminate\Tests\View\Blade\TestAlertComponent', 'alert', [])
54+
$this->assertSame("<div>##BEGIN-COMPONENT-CLASS##@component('Illuminate\Tests\View\Blade\TestAlertComponent', 'alert', [])
5555
<?php \$component->withAttributes(['type' => '','limit' => '','@click' => '','required' => true]); ?>\n".
56-
'@endcomponentClass </div>', trim($result));
56+
'@endComponentClass##END-COMPONENT-CLASS##</div>', trim($result));
5757
}
5858

5959
public function testDataCamelCasing()
6060
{
6161
$result = $this->compiler(['profile' => TestProfileComponent::class])->compileTags('<x-profile user-id="1"></x-profile>');
6262

63-
$this->assertSame("@component('Illuminate\Tests\View\Blade\TestProfileComponent', 'profile', ['userId' => '1'])
64-
<?php \$component->withAttributes([]); ?> @endcomponentClass", trim($result));
63+
$this->assertSame("##BEGIN-COMPONENT-CLASS##@component('Illuminate\Tests\View\Blade\TestProfileComponent', 'profile', ['userId' => '1'])
64+
<?php \$component->withAttributes([]); ?> @endComponentClass##END-COMPONENT-CLASS##", trim($result));
6565
}
6666

6767
public function testColonData()
6868
{
6969
$result = $this->compiler(['profile' => TestProfileComponent::class])->compileTags('<x-profile :user-id="1"></x-profile>');
7070

71-
$this->assertSame("@component('Illuminate\Tests\View\Blade\TestProfileComponent', 'profile', ['userId' => 1])
72-
<?php \$component->withAttributes([]); ?> @endcomponentClass", trim($result));
71+
$this->assertSame("##BEGIN-COMPONENT-CLASS##@component('Illuminate\Tests\View\Blade\TestProfileComponent', 'profile', ['userId' => 1])
72+
<?php \$component->withAttributes([]); ?> @endComponentClass##END-COMPONENT-CLASS##", trim($result));
7373
}
7474

7575
public function testColonAttributesIsEscapedIfStrings()
7676
{
7777
$result = $this->compiler(['profile' => TestProfileComponent::class])->compileTags('<x-profile :src="\'foo\'"></x-profile>');
7878

79-
$this->assertSame("@component('Illuminate\Tests\View\Blade\TestProfileComponent', 'profile', [])
80-
<?php \$component->withAttributes(['src' => \Illuminate\View\Compilers\BladeCompiler::sanitizeComponentAttribute('foo')]); ?> @endcomponentClass", trim($result));
79+
$this->assertSame("##BEGIN-COMPONENT-CLASS##@component('Illuminate\Tests\View\Blade\TestProfileComponent', 'profile', [])
80+
<?php \$component->withAttributes(['src' => \Illuminate\View\Compilers\BladeCompiler::sanitizeComponentAttribute('foo')]); ?> @endComponentClass##END-COMPONENT-CLASS##", trim($result));
8181
}
8282

8383
public function testColonNestedComponentParsing()
8484
{
8585
$result = $this->compiler(['foo:alert' => TestAlertComponent::class])->compileTags('<x-foo:alert></x-foo:alert>');
8686

87-
$this->assertSame("@component('Illuminate\Tests\View\Blade\TestAlertComponent', 'foo:alert', [])
88-
<?php \$component->withAttributes([]); ?> @endcomponentClass", trim($result));
87+
$this->assertSame("##BEGIN-COMPONENT-CLASS##@component('Illuminate\Tests\View\Blade\TestAlertComponent', 'foo:alert', [])
88+
<?php \$component->withAttributes([]); ?> @endComponentClass##END-COMPONENT-CLASS##", trim($result));
8989
}
9090

9191
public function testColonStartingNestedComponentParsing()
9292
{
9393
$result = $this->compiler(['foo:alert' => TestAlertComponent::class])->compileTags('<x:foo:alert></x-foo:alert>');
9494

95-
$this->assertSame("@component('Illuminate\Tests\View\Blade\TestAlertComponent', 'foo:alert', [])
96-
<?php \$component->withAttributes([]); ?> @endcomponentClass", trim($result));
95+
$this->assertSame("##BEGIN-COMPONENT-CLASS##@component('Illuminate\Tests\View\Blade\TestAlertComponent', 'foo:alert', [])
96+
<?php \$component->withAttributes([]); ?> @endComponentClass##END-COMPONENT-CLASS##", trim($result));
9797
}
9898

9999
public function testSelfClosingComponentsCanBeCompiled()
100100
{
101101
$result = $this->compiler(['alert' => TestAlertComponent::class])->compileTags('<div><x-alert/></div>');
102102

103-
$this->assertSame("<div> @component('Illuminate\Tests\View\Blade\TestAlertComponent', 'alert', [])
103+
$this->assertSame("<div>##BEGIN-COMPONENT-CLASS##@component('Illuminate\Tests\View\Blade\TestAlertComponent', 'alert', [])
104104
<?php \$component->withAttributes([]); ?>\n".
105-
'@endcomponentClass </div>', trim($result));
105+
'@endComponentClass##END-COMPONENT-CLASS##</div>', trim($result));
106106
}
107107

108108
public function testClassNamesCanBeGuessed()
@@ -139,27 +139,27 @@ public function testComponentsCanBeCompiledWithHyphenAttributes()
139139

140140
$result = $this->compiler(['alert' => TestAlertComponent::class])->compileTags('<x-alert class="bar" wire:model="foo" x-on:click="bar" @click="baz" />');
141141

142-
$this->assertSame("@component('Illuminate\Tests\View\Blade\TestAlertComponent', 'alert', [])
142+
$this->assertSame("##BEGIN-COMPONENT-CLASS##@component('Illuminate\Tests\View\Blade\TestAlertComponent', 'alert', [])
143143
<?php \$component->withAttributes(['class' => 'bar','wire:model' => 'foo','x-on:click' => 'bar','@click' => 'baz']); ?>\n".
144-
'@endcomponentClass', trim($result));
144+
'@endComponentClass##END-COMPONENT-CLASS##', trim($result));
145145
}
146146

147147
public function testSelfClosingComponentsCanBeCompiledWithDataAndAttributes()
148148
{
149149
$result = $this->compiler(['alert' => TestAlertComponent::class])->compileTags('<x-alert title="foo" class="bar" wire:model="foo" />');
150150

151-
$this->assertSame("@component('Illuminate\Tests\View\Blade\TestAlertComponent', 'alert', ['title' => 'foo'])
151+
$this->assertSame("##BEGIN-COMPONENT-CLASS##@component('Illuminate\Tests\View\Blade\TestAlertComponent', 'alert', ['title' => 'foo'])
152152
<?php \$component->withAttributes(['class' => 'bar','wire:model' => 'foo']); ?>\n".
153-
'@endcomponentClass', trim($result));
153+
'@endComponentClass##END-COMPONENT-CLASS##', trim($result));
154154
}
155155

156156
public function testComponentCanReceiveAttributeBag()
157157
{
158158
$this->mockViewFactory();
159159
$result = $this->compiler(['profile' => TestProfileComponent::class])->compileTags('<x-profile class="bar" {{ $attributes }} wire:model="foo"></x-profile>');
160160

161-
$this->assertSame("@component('Illuminate\Tests\View\Blade\TestProfileComponent', 'profile', [])
162-
<?php \$component->withAttributes(['class' => 'bar','attributes' => \Illuminate\View\Compilers\BladeCompiler::sanitizeComponentAttribute(\$attributes),'wire:model' => 'foo']); ?> @endcomponentClass", trim($result));
161+
$this->assertSame("##BEGIN-COMPONENT-CLASS##@component('Illuminate\Tests\View\Blade\TestProfileComponent', 'profile', [])
162+
<?php \$component->withAttributes(['class' => 'bar','attributes' => \Illuminate\View\Compilers\BladeCompiler::sanitizeComponentAttribute(\$attributes),'wire:model' => 'foo']); ?> @endComponentClass##END-COMPONENT-CLASS##", trim($result));
163163
}
164164

165165
public function testSelfClosingComponentCanReceiveAttributeBag()
@@ -168,45 +168,45 @@ public function testSelfClosingComponentCanReceiveAttributeBag()
168168

169169
$result = $this->compiler(['alert' => TestAlertComponent::class])->compileTags('<div><x-alert title="foo" class="bar" {{ $attributes->merge([\'class\' => \'test\']) }} wire:model="foo" /></div>');
170170

171-
$this->assertSame("<div> @component('Illuminate\Tests\View\Blade\TestAlertComponent', 'alert', ['title' => 'foo'])
171+
$this->assertSame("<div>##BEGIN-COMPONENT-CLASS##@component('Illuminate\Tests\View\Blade\TestAlertComponent', 'alert', ['title' => 'foo'])
172172
<?php \$component->withAttributes(['class' => 'bar','attributes' => \Illuminate\View\Compilers\BladeCompiler::sanitizeComponentAttribute(\$attributes->merge(['class' => 'test'])),'wire:model' => 'foo']); ?>\n".
173-
'@endcomponentClass </div>', trim($result));
173+
'@endComponentClass##END-COMPONENT-CLASS##</div>', trim($result));
174174
}
175175

176176
public function testComponentsCanHaveAttachedWord()
177177
{
178178
$result = $this->compiler(['profile' => TestProfileComponent::class])->compileTags('<x-profile></x-profile>Words');
179179

180-
$this->assertSame("@component('Illuminate\Tests\View\Blade\TestProfileComponent', 'profile', [])
181-
<?php \$component->withAttributes([]); ?> @endcomponentClass Words", trim($result));
180+
$this->assertSame("##BEGIN-COMPONENT-CLASS##@component('Illuminate\Tests\View\Blade\TestProfileComponent', 'profile', [])
181+
<?php \$component->withAttributes([]); ?> @endComponentClass##END-COMPONENT-CLASS##Words", trim($result));
182182
}
183183

184184
public function testSelfClosingComponentsCanHaveAttachedWord()
185185
{
186186
$result = $this->compiler(['alert' => TestAlertComponent::class])->compileTags('<x-alert/>Words');
187187

188-
$this->assertSame("@component('Illuminate\Tests\View\Blade\TestAlertComponent', 'alert', [])
188+
$this->assertSame("##BEGIN-COMPONENT-CLASS##@component('Illuminate\Tests\View\Blade\TestAlertComponent', 'alert', [])
189189
<?php \$component->withAttributes([]); ?>\n".
190-
'@endcomponentClass Words', trim($result));
190+
'@endComponentClass##END-COMPONENT-CLASS##Words', trim($result));
191191
}
192192

193193
public function testSelfClosingComponentsCanBeCompiledWithBoundData()
194194
{
195195
$result = $this->compiler(['alert' => TestAlertComponent::class])->compileTags('<x-alert :title="$title" class="bar" />');
196196

197-
$this->assertSame("@component('Illuminate\Tests\View\Blade\TestAlertComponent', 'alert', ['title' => \$title])
197+
$this->assertSame("##BEGIN-COMPONENT-CLASS##@component('Illuminate\Tests\View\Blade\TestAlertComponent', 'alert', ['title' => \$title])
198198
<?php \$component->withAttributes(['class' => 'bar']); ?>\n".
199-
'@endcomponentClass', trim($result));
199+
'@endComponentClass##END-COMPONENT-CLASS##', trim($result));
200200
}
201201

202202
public function testPairedComponentTags()
203203
{
204204
$result = $this->compiler(['alert' => TestAlertComponent::class])->compileTags('<x-alert>
205205
</x-alert>');
206206

207-
$this->assertSame("@component('Illuminate\Tests\View\Blade\TestAlertComponent', 'alert', [])
207+
$this->assertSame("##BEGIN-COMPONENT-CLASS##@component('Illuminate\Tests\View\Blade\TestAlertComponent', 'alert', [])
208208
<?php \$component->withAttributes([]); ?>
209-
@endcomponentClass", trim($result));
209+
@endComponentClass##END-COMPONENT-CLASS##", trim($result));
210210
}
211211

212212
public function testClasslessComponents()
@@ -220,9 +220,9 @@ public function testClasslessComponents()
220220

221221
$result = $this->compiler()->compileTags('<x-anonymous-component :name="\'Taylor\'" :age="31" wire:model="foo" />');
222222

223-
$this->assertSame("@component('Illuminate\View\AnonymousComponent', 'anonymous-component', ['view' => 'components.anonymous-component','data' => ['name' => 'Taylor','age' => 31,'wire:model' => 'foo']])
223+
$this->assertSame("##BEGIN-COMPONENT-CLASS##@component('Illuminate\View\AnonymousComponent', 'anonymous-component', ['view' => 'components.anonymous-component','data' => ['name' => 'Taylor','age' => 31,'wire:model' => 'foo']])
224224
<?php \$component->withAttributes(['name' => \Illuminate\View\Compilers\BladeCompiler::sanitizeComponentAttribute('Taylor'),'age' => 31,'wire:model' => 'foo']); ?>\n".
225-
'@endcomponentClass', trim($result));
225+
'@endComponentClass##END-COMPONENT-CLASS##', trim($result));
226226
}
227227

228228
public function testPackagesClasslessComponents()
@@ -236,9 +236,9 @@ public function testPackagesClasslessComponents()
236236

237237
$result = $this->compiler()->compileTags('<x-package::anonymous-component :name="\'Taylor\'" :age="31" wire:model="foo" />');
238238

239-
$this->assertSame("@component('Illuminate\View\AnonymousComponent', 'package::anonymous-component', ['view' => 'package::components.anonymous-component','data' => ['name' => 'Taylor','age' => 31,'wire:model' => 'foo']])
239+
$this->assertSame("##BEGIN-COMPONENT-CLASS##@component('Illuminate\View\AnonymousComponent', 'package::anonymous-component', ['view' => 'package::components.anonymous-component','data' => ['name' => 'Taylor','age' => 31,'wire:model' => 'foo']])
240240
<?php \$component->withAttributes(['name' => \Illuminate\View\Compilers\BladeCompiler::sanitizeComponentAttribute('Taylor'),'age' => 31,'wire:model' => 'foo']); ?>\n".
241-
'@endcomponentClass', trim($result));
241+
'@endComponentClass##END-COMPONENT-CLASS##', trim($result));
242242
}
243243

244244
public function testAttributeSanitization()

0 commit comments

Comments
 (0)