+
User Profile
+ {{-- Lots of static markup here --}}
+
+ @unblaze(scope: ['userId' => $userId, 'showStatus' => $showStatus])
+ @if($scope['showStatus'])
+
User #{{ $scope['userId'] }} - Last seen: {{ session('last_seen') }}
+ @endif
+ @endunblaze
+
+```
+
+**How scope works:**
+- Variables captured in `scope:` are encoded into the compiled view
+- Inside the `@unblaze` block, access them via `$scope['key']`
+- This allows the unblaze section to use component props while keeping the rest folded
+
+### Nested components inside @unblaze
+
+You can render other components inside `@unblaze` blocks, which is useful for extracting reusable dynamic sections:
+
+```blade
+@blaze
+
+@props(['name', 'label'])
+
+');
+ expect($compiled)->toContain('
Static Header ');
+ expect($compiled)->toContain('
');
+
+ // The unblaze block should be preserved as dynamic content
+ expect($compiled)->toContain('{{ $dynamicValue }}');
+ expect($compiled)->not->toContain('
';
+
+ $compiled = app('blaze')->compile($input);
+
+ // Static parts should be folded
+ expect($compiled)->toContain('Static Header');
+ expect($compiled)->toContain('Static Footer');
+
+ // Dynamic parts inside @unblaze should remain dynamic
+ expect($compiled)->toContain('$dynamicValue');
+ });
+
+ it('handles unblaze with scope parameter', function () {
+ $input = '
';
+
+ $compiled = app('blaze')->compile($input);
+
+ // The component should be folded
+ expect($compiled)->toContain('
');
+ expect($compiled)->toContain('
Title ');
+ expect($compiled)->toContain('
Static paragraph
');
+
+ // The scope should be captured and made available
+ expect($compiled)->toContain('$scope');
+ });
+
+ it('encodes scope into compiled view for runtime access', function () {
+ $input = '
';
+
+ $compiled = app('blaze')->compile($input);
+
+ // Should contain PHP code to set up the scope
+ expect($compiled)->toMatch('/\$scope\s*=\s*array\s*\(/');
+
+ // The dynamic content should reference $scope
+ expect($compiled)->toContain('$scope[\'message\']');
+ });
+
+ it('renders unblaze component correctly at runtime', function () {
+ $template = '
';
+
+ $rendered = \Illuminate\Support\Facades\Blade::render($template);
+
+ // Static content should be present
+ expect($rendered)->toContain('
');
+ expect($rendered)->toContain('
Title ');
+ expect($rendered)->toContain('
Static paragraph
');
+
+ // Dynamic content should be rendered with the scope value
+ // Note: The actual rendering of scope variables happens at runtime
+ expect($rendered)->toContain('class="dynamic"');
+ });
+
+ it('allows punching a hole in static component for dynamic section', function () {
+ $input = <<<'BLADE'
+
+ Static content here
+ @unblaze
+ {{ $dynamicValue }}
+ @endunblaze
+ More static content
+
+BLADE;
+
+ $compiled = app('blaze')->compile($input);
+
+ // Card should be folded
+ expect($compiled)->toContain('
');
+ expect($compiled)->toContain('Static content here');
+ expect($compiled)->toContain('More static content');
+
+ // But dynamic part should be preserved
+ expect($compiled)->toContain('{{ $dynamicValue }}');
+ expect($compiled)->not->toContain('
');
+ });
+
+ it('supports multiple unblaze blocks in same component', function () {
+ $template = <<<'BLADE'
+@blaze
+
+
Static 1
+ @unblaze
+
{{ $dynamic1 }}
+ @endunblaze
+
Static 2
+ @unblaze
+
{{ $dynamic2 }}
+ @endunblaze
+
Static 3
+
+BLADE;
+
+ $compiled = app('blaze')->compile($template);
+
+ // All static parts should be folded
+ expect($compiled)->toContain('Static 1
');
+ expect($compiled)->toContain('Static 2
');
+ expect($compiled)->toContain('Static 3
');
+
+ // Both dynamic parts should be preserved
+ expect($compiled)->toContain('{{ $dynamic1 }}');
+ expect($compiled)->toContain('{{ $dynamic2 }}');
+ });
+
+ it('handles nested components with unblaze', function () {
+ $input = <<<'BLADE'
+
+ Static Button
+ @unblaze
+ {{ $dynamicLabel }}
+ @endunblaze
+
+BLADE;
+
+ $compiled = app('blaze')->compile($input);
+
+ // Outer card and static button should be folded
+ expect($compiled)->toContain('');
+ expect($compiled)->toContain('Static Button');
+
+ // Dynamic button inside unblaze should be preserved
+ expect($compiled)->toContain('{{ $dynamicLabel }}');
+ });
+
+ it('static folded content with random strings stays the same between renders', function () {
+ // First render
+ $render1 = \Illuminate\Support\Facades\Blade::render('
');
+
+ // Second render
+ $render2 = \Illuminate\Support\Facades\Blade::render('
');
+
+ // The random string should be the same because it was folded at compile time
+ expect($render1)->toBe($render2);
+
+ // Verify it contains the static structure
+ expect($render1)->toContain('class="static-component"');
+ expect($render1)->toContain('This should be folded and not change between renders');
+ });
+
+ it('unblazed dynamic content changes between renders while static parts stay the same', function () {
+ // First render with a value
+ $render1 = \Illuminate\Support\Facades\Blade::render('
', ['dynamicValue' => 'first-value']);
+
+ // Second render with a different value
+ $render2 = \Illuminate\Support\Facades\Blade::render('
', ['dynamicValue' => 'second-value']);
+
+ // Extract the static parts (header and footer with random strings)
+ preg_match('/
Static Random: (.+?)<\/h1>/', $render1, $matches1);
+ preg_match('/Static Random: (.+?)<\/h1>/', $render2, $matches2);
+ $staticRandom1 = $matches1[1] ?? '';
+ $staticRandom2 = $matches2[1] ?? '';
+
+ // The static random strings should be IDENTICAL (folded at compile time)
+ expect($staticRandom1)->toBe($staticRandom2);
+ expect($staticRandom1)->not->toBeEmpty();
+
+ // But the dynamic parts should be DIFFERENT
+ expect($render1)->toContain('Dynamic value: first-value');
+ expect($render2)->toContain('Dynamic value: second-value');
+ expect($render1)->not->toContain('second-value');
+ expect($render2)->not->toContain('first-value');
+ });
+
+ it('multiple renders of unblaze component proves folding optimization', function () {
+ // Render the same template multiple times with different dynamic values
+ $renders = [];
+ foreach (['one', 'two', 'three'] as $value) {
+ $renders[] = \Illuminate\Support\Facades\Blade::render(
+ ' ',
+ ['dynamicValue' => $value]
+ );
+ }
+
+ // Extract the static footer random string from each render
+ $staticFooters = [];
+ foreach ($renders as $render) {
+ preg_match('/Static Footer: (.+?)<\/footer>/', $render, $matches);
+ $staticFooters[] = $matches[1] ?? '';
+ }
+
+ // All static random strings should be IDENTICAL (proving they were folded)
+ expect($staticFooters[0])->toBe($staticFooters[1]);
+ expect($staticFooters[1])->toBe($staticFooters[2]);
+ expect($staticFooters[0])->not->toBeEmpty();
+
+ // But each render should have its unique dynamic value
+ expect($renders[0])->toContain('Dynamic value: one');
+ expect($renders[1])->toContain('Dynamic value: two');
+ expect($renders[2])->toContain('Dynamic value: three');
+ });
+});
diff --git a/tests/fixtures/components/mixed-random.blade.php b/tests/fixtures/components/mixed-random.blade.php
new file mode 100644
index 00000000..861183c8
--- /dev/null
+++ b/tests/fixtures/components/mixed-random.blade.php
@@ -0,0 +1,8 @@
+@blaze
+
+
Static Random: {{ \Illuminate\Support\Str::random(20) }}
+ @unblaze
+
Dynamic value: {{ $dynamicValue ?? 'none' }}
+ @endunblaze
+
Static Footer: {{ \Illuminate\Support\Str::random(10) }}
+
diff --git a/tests/fixtures/components/random-static.blade.php b/tests/fixtures/components/random-static.blade.php
new file mode 100644
index 00000000..635ae031
--- /dev/null
+++ b/tests/fixtures/components/random-static.blade.php
@@ -0,0 +1,5 @@
+@blaze
+
+
Random: {{ \Illuminate\Support\Str::random(20) }}
+
This should be folded and not change between renders
+
diff --git a/tests/fixtures/components/scoped-dynamic.blade.php b/tests/fixtures/components/scoped-dynamic.blade.php
new file mode 100644
index 00000000..afe6405f
--- /dev/null
+++ b/tests/fixtures/components/scoped-dynamic.blade.php
@@ -0,0 +1,8 @@
+@blaze
+
+
Static: {{ \Illuminate\Support\Str::random(15) }}
+ @unblaze(scope: ['value' => $value])
+
Value: {{ $scope['value'] }}
+ @endunblaze
+
Static paragraph: {{ \Illuminate\Support\Str::random(10) }}
+
diff --git a/tests/fixtures/components/with-unblaze-scope.blade.php b/tests/fixtures/components/with-unblaze-scope.blade.php
new file mode 100644
index 00000000..d818e5d9
--- /dev/null
+++ b/tests/fixtures/components/with-unblaze-scope.blade.php
@@ -0,0 +1,8 @@
+@blaze
+
+
Title
+ @unblaze(scope: ['message' => $message])
+
{{ $scope['message'] }}
+ @endunblaze
+
Static paragraph
+
diff --git a/tests/fixtures/components/with-unblaze.blade.php b/tests/fixtures/components/with-unblaze.blade.php
new file mode 100644
index 00000000..a24bb4b7
--- /dev/null
+++ b/tests/fixtures/components/with-unblaze.blade.php
@@ -0,0 +1,8 @@
+@blaze
+
+
Static Header
+ @unblaze
+
Dynamic content: {{ $dynamicValue }}
+ @endunblaze
+
+