Skip to content
This repository has been archived by the owner on Feb 27, 2024. It is now read-only.

Commit

Permalink
Added vue macro to ComponentAttributeBag
Browse files Browse the repository at this point in the history
  • Loading branch information
pascalbaljet committed Jan 20, 2024
1 parent 49fef2d commit 6b31fa7
Show file tree
Hide file tree
Showing 2 changed files with 98 additions and 0 deletions.
59 changes: 59 additions & 0 deletions app/tests/Unit/ComponentAttributeBagTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<?php

namespace Tests\Unit;

use Illuminate\View\ComponentAttributeBag;
use Tests\TestCase;

class ComponentAttributeBagTest extends TestCase
{
private function attr($attribute, $value = null, bool $omitBlankValue = true, bool $escape = true): string
{
return (new ComponentAttributeBag)
->vue($attribute, $value, $omitBlankValue, $escape)
->toHtml();
}

/** @test */
public function it_omits_blank_values_by_default()
{
$this->assertEmpty($this->attr('animation', ''));
$this->assertEmpty($this->attr('animation', null));
$this->assertEmpty($this->attr('animation', []));
}

/** @test */
public function it_doesnt_affect_non_vue_attributes()
{
$this->assertEquals('animation="default"', $this->attr('animation', 'default'));
}

/** @test */
public function it_rewrites_a_vue_event_shortcut_to_the_full_notation()
{
$this->assertEquals('v-on:click="doSomething"', $this->attr('@click', 'doSomething'));
$this->assertEquals('v-on:click="doSomething"', $this->attr('v-on:click', 'doSomething'));
}

/** @test */
public function it_rewrites_a_vue_binding_shortcut_to_the_full_notation()
{
$this->assertEquals('v-bind:animation="default"', $this->attr(':animation', 'default'));
$this->assertEquals('v-bind:animation="default"', $this->attr('v-bind:animation', 'default'));
}

/** @test */
public function it_rewrites_a_boolean_value_to_a_string()
{
$this->assertEquals('v-bind:animation="true"', $this->attr(':animation', true));
$this->assertEquals('v-bind:animation="false"', $this->attr(':animation', false));
}

/** @test */
public function it_can_bind_arrays()
{
$this->assertEquals('v-bind:animation="JSON.parse(&#039;[1,2,3]&#039;)"', $this->attr(':animation', [1, 2, 3]));
$this->assertEquals('v-bind:animation="JSON.parse(&#039;[true,false]&#039;)"', $this->attr(':animation', [true, false]));
$this->assertEquals('v-bind:animation="JSON.parse(&#039;[\u0022a\u0022,\u0022b\u0022]&#039;)"', $this->attr(':animation', ['a', 'b']));
}
}
39 changes: 39 additions & 0 deletions src/SpladeCoreServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,11 @@
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\Event;
use Illuminate\Support\Facades\Route;
use Illuminate\Support\Js;
use Illuminate\Support\Str;
use Illuminate\View\Compilers\ComponentTagCompiler;
use Illuminate\View\Component;
use Illuminate\View\ComponentAttributeBag;
use Illuminate\View\DynamicComponent;
use Illuminate\View\Engines\EngineResolver;
use ProtoneMedia\SpladeCore\Commands\BuildComponents;
Expand Down Expand Up @@ -45,6 +48,7 @@ public function packageRegistered()
$this->registerComponentHelper();
$this->registerBladeEngine();
$this->registerFactory();
$this->registerComponentAttributeBagMacro();

$this->app->singleton(SpladeCoreRequest::class, function (Application $app) {
return new SpladeCoreRequest(fn () => $app['request']);
Expand Down Expand Up @@ -160,4 +164,39 @@ public function packageBooted()
}
});
}

protected function registerComponentAttributeBagMacro()
{
ComponentAttributeBag::macro('vue', function ($attribute, $value = null, bool $omitBlankValue = true, bool $escape = true) {
/** @var ComponentAttributeBag $this */
if ($omitBlankValue && blank($value)) {
return $this;
}

$isEvent = Str::startsWith($attribute, ['@', 'v-on:']);
$isBinding = Str::startsWith($attribute, [':', 'v-bind:']);

if (! $isEvent && ! $isBinding) {
return $this->merge([$attribute => $value], $escape);
}

foreach (['@', 'v-on:', ':', 'v-bind:'] as $modifier) {
if (Str::startsWith($attribute, $modifier)) {
$attribute = Str::substr($attribute, strlen($modifier));
}
}

$shortBindAttribute = ($isEvent ? '@' : ':').$attribute;
$fullBindAttribute = ($isEvent ? 'v-on:' : 'v-bind:').$attribute;

return $this->unless($this->has($shortBindAttribute) || $this->has($fullBindAttribute), function () use ($fullBindAttribute, $value, $escape) {
if (is_array($value) || is_bool($value) || is_object($value)) {
$value = Js::from($value)->toHtml();
}

/** @var ComponentAttributeBag $this */
return $this->merge([$fullBindAttribute => $value], $escape);
});
});
}
}

0 comments on commit 6b31fa7

Please sign in to comment.