diff --git a/app/resources/views/props-in-template.blade.php b/app/resources/views/props-in-template.blade.php index 15d8eb1..ad1df7a 100644 --- a/app/resources/views/props-in-template.blade.php +++ b/app/resources/views/props-in-template.blade.php @@ -1,3 +1,13 @@ - + + + + + \ No newline at end of file diff --git a/app/tests/Browser/PropsTest.php b/app/tests/Browser/PropsTest.php index ea469b4..cda9f26 100644 --- a/app/tests/Browser/PropsTest.php +++ b/app/tests/Browser/PropsTest.php @@ -13,7 +13,9 @@ public function it_exposes_the_props_to_the_template_data() $this->browse(function (Browser $browser) { $browser->visit('/props-in-template') ->assertSeeIn('h2', 'Default title') - ->assertSeeIn('h3', 'Default subtitle'); + ->assertSeeIn('h3', 'Default subtitle') + ->press('Update title') + ->assertSeeIn('h2', 'New title'); }); } } diff --git a/app/tests/Unit/ScriptParserTest.php b/app/tests/Unit/ScriptParserTest.php index 3fa0c21..283744f 100644 --- a/app/tests/Unit/ScriptParserTest.php +++ b/app/tests/Unit/ScriptParserTest.php @@ -15,6 +15,7 @@ public function it_can_merge_the_props_when_no_props_are_defined() $this->assertEquals([ 'original' => '', 'new' => 'const props = defineProps({foo: String});', + 'keys' => ['foo'], ], $parser->getDefineProps([ 'foo' => 'String', ])); @@ -32,6 +33,7 @@ public function it_can_extract_the_define_props_when_called_with_an_array() $this->assertEquals([ 'original' => "defineProps(['foo', 'bar']);", 'new' => 'const props = defineProps({foo: {}, bar: {}});', + 'keys' => ['foo', 'bar'], ], $parser->getDefineProps()); } @@ -47,6 +49,7 @@ public function it_can_extract_the_define_props_when_called_with_an_array_with_a $this->assertEquals([ 'original' => "const props = defineProps(['foo', 'bar']);", 'new' => 'const props = defineProps({foo: {}, bar: {}});', + 'keys' => ['foo', 'bar'], ], $parser->getDefineProps()); } @@ -62,6 +65,7 @@ public function it_can_extract_the_define_props_when_called_with_an_array_and_me $this->assertEquals([ 'original' => "defineProps(['foo', 'bar']);", 'new' => 'const props = defineProps({foo: {}, bar: {}, baz: String});', + 'keys' => ['foo', 'bar', 'baz'], ], $parser->getDefineProps([ 'baz' => 'String', ])); @@ -79,6 +83,7 @@ public function it_can_extract_the_define_props_when_called_with_an_object() $this->assertEquals([ 'original' => 'defineProps({foo: {type: String}, bar: {type: Array}});', 'new' => 'const props = defineProps({foo: {type: String}, bar: {type: Array}});', + 'keys' => ['foo', 'bar'], ], $parser->getDefineProps()); } @@ -94,6 +99,7 @@ public function it_can_extract_the_define_props_when_called_with_an_object_and_o $this->assertEquals([ 'original' => 'defineProps({foo: String, bar: Array});', 'new' => 'const props = defineProps({foo: String, bar: Array});', + 'keys' => ['foo', 'bar'], ], $parser->getDefineProps()); } @@ -109,6 +115,7 @@ public function it_can_extract_the_define_props_when_called_with_an_object_and_m $this->assertEquals([ 'original' => 'defineProps({foo: {type: String}, bar: {type: Array}});', 'new' => 'const props = defineProps({baz: String, foo: {type: String}, bar: {type: Array}});', + 'keys' => ['foo', 'bar', 'baz'], ], $parser->getDefineProps([ 'baz' => 'String', ])); @@ -126,6 +133,7 @@ public function it_can_extract_the_define_props_when_called_with_an_object_and_o $this->assertEquals([ 'original' => 'defineProps({foo: String, bar: Array});', 'new' => 'const props = defineProps({baz: String, foo: String, bar: Array});', + 'keys' => ['foo', 'bar', 'baz'], ], $parser->getDefineProps([ 'baz' => 'String', ])); @@ -143,6 +151,7 @@ public function it_can_extract_the_define_props_when_called_with_an_object_with_ $this->assertEquals([ 'original' => 'const props = defineProps({foo: {type: String}, bar: {type: Array}});', 'new' => 'const props = defineProps({foo: {type: String}, bar: {type: Array}});', + 'keys' => ['foo', 'bar'], ], $parser->getDefineProps()); } diff --git a/src/BladeViewExtractor.php b/src/BladeViewExtractor.php index 1fb1175..4dc2d04 100644 --- a/src/BladeViewExtractor.php +++ b/src/BladeViewExtractor.php @@ -7,6 +7,7 @@ use Illuminate\Support\Collection; use Illuminate\Support\Facades\Process; use Illuminate\Support\Str; +use Illuminate\View\ComponentAttributeBag; use InvalidArgumentException; use ProtoneMedia\SpladeCore\Facades\SpladePlugin; @@ -122,7 +123,15 @@ public function handle(Filesystem $filesystem): string } // Adjust the current defineProps, or generate a new one if it didn't exist yet. - [$script, $defineProps] = $this->extractDefinePropsFromScript(); + [$script, $defineProps, $definePropsObject, $definePropNames] = $this->extractDefinePropsFromScript(); + + $attrs = collect($definePropNames)->mapWithKeys(function (string $prop) { + return ['v-bind:'.$prop => $prop]; + })->all(); + + $bag = new ComponentAttributeBag($attrs); + + $template = ""; $vueComponent = implode(PHP_EOL, array_filter([ '', - '', + $template, ])); $directory = config('splade-core.compiled_scripts'); @@ -339,12 +348,14 @@ protected function extractDefinePropsFromScript(): array $defineProps = $this->scriptParser->getDefineProps($defaultProps->all()); if (! $defineProps['original']) { - return [$this->originalScript, $defineProps['new']]; + return [$this->originalScript, $defineProps['new'], $defineProps['object'], $defineProps['keys']]; } return [ str_replace($defineProps['original'], '', $this->originalScript), $defineProps['new'], + $defineProps['object'], + $defineProps['keys'], ]; } @@ -511,7 +522,7 @@ protected function getImportedComponents(): array /** * Renders the SpladeRender 'h'-function. */ - protected function renderSpladeRenderFunction(): string + protected function renderSpladeRenderFunction($definePropsObject): string { $inheritAttrs = $this->attributesAreCustomBound() ? <<<'JS' inheritAttrs: false, @@ -545,7 +556,7 @@ protected function renderSpladeRenderFunction(): string {$componentsObject} template: spladeTemplates[props.spladeTemplateId], data: () => { return { {$dataObject} } }, - props, + props: {$definePropsObject}, }); JS; } diff --git a/src/ScriptParser.php b/src/ScriptParser.php index 3763b13..a4391ab 100644 --- a/src/ScriptParser.php +++ b/src/ScriptParser.php @@ -99,6 +99,8 @@ private function toPropsObjectDefinition(array|Collection $props): string */ public function getDefineProps(array $mergeWith = []): array { + $propKeys = []; + foreach ($this->rootNode->query('CallExpression[callee.name="defineProps"]') as $node) { /** @var CallExpression $node */ $definePropsScript = collect(explode(PHP_EOL, $this->script)) @@ -114,16 +116,22 @@ public function getDefineProps(array $mergeWith = []): array if ($firstArgument instanceof ArrayExpression) { $props = collect($firstArgument->getElements()) ->map(fn (StringLiteral $element) => $element->getValue()) - ->mapWithKeys(fn (string $prop) => [$prop => '']) + ->mapWithKeys(function (string $prop) use (&$propKeys) { + $propKeys[] = $prop; + + return [$prop => '']; + }) ->merge($mergeWith) ->pipe(fn (Collection $props) => $this->toPropsObjectDefinition($props)); $newPropsObject = "{{$props}}"; } elseif ($firstArgument instanceof ObjectExpression) { $props = collect($firstArgument->getProperties()) - ->mapWithKeys(function (Property $property) { + ->mapWithKeys(function (Property $property) use (&$propKeys) { $key = $property->getKey()->getName(); + $propKeys[] = $key; + if ($property->getValue() instanceof Identifier) { return [$key => $property->getValue()->getName()]; } @@ -145,6 +153,8 @@ public function getDefineProps(array $mergeWith = []): array return [ 'original' => trim($definePropsScript), 'new' => "const props = defineProps({$newPropsObject});", + 'object' => $newPropsObject, + 'keys' => [...$propKeys, ...array_keys($mergeWith)], ]; } @@ -153,6 +163,8 @@ public function getDefineProps(array $mergeWith = []): array return [ 'original' => '', 'new' => 'const props = defineProps({'.$keys.'});', + 'object' => '{'.$keys.'}', + 'keys' => [...$propKeys, ...array_keys($mergeWith)], ]; }