Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
a54de99
Refactor Tokenizer
ganyicz Aug 6, 2026
abcfc13
Formatting
ganyicz Aug 6, 2026
e35bf7a
Fix regex
ganyicz Aug 6, 2026
eb04c9e
Refactor Parser
ganyicz Aug 6, 2026
9d4d4ad
Fix tests
ganyicz Aug 6, 2026
15daf17
Stop storing uncompiled blocks
ganyicz Aug 6, 2026
8241166
Refactor Wrapper to use AST
ganyicz Aug 6, 2026
ee9326e
Remove unused methods
ganyicz Aug 6, 2026
4e88639
Refactor ComponentSource to use AST
ganyicz Aug 6, 2026
584e9ab
Fix visibility
ganyicz Aug 6, 2026
7105566
Cache parsed templates
ganyicz Aug 6, 2026
3750eac
Cache props and aware
ganyicz Aug 6, 2026
638ee78
Refactor unblaze to use AST
ganyicz Aug 7, 2026
f9a79c1
Remove DirectiveCompiler
ganyicz Aug 7, 2026
267e3dc
Delete DirectiveCompilerTest.php
ganyicz Aug 7, 2026
78a2d5d
Refactor
ganyicz Aug 7, 2026
340975c
Refactor
ganyicz Aug 7, 2026
27f89cb
Refactor
ganyicz Aug 7, 2026
5c40d75
Fix
ganyicz Aug 7, 2026
6a676c5
Revert "Refactor"
ganyicz Aug 7, 2026
c453cf9
Refactor
ganyicz Aug 7, 2026
bb08784
Make Walker static
ganyicz Aug 7, 2026
9e5ba51
Refactor
ganyicz Aug 7, 2026
25a096f
Formatting
ganyicz Aug 7, 2026
e70dc6e
Reset unblaze after replacing
ganyicz Aug 7, 2026
be4777d
Fix
ganyicz Aug 7, 2026
3f5ecbc
Formatting
ganyicz Aug 7, 2026
c2a32cc
Formatting
ganyicz Aug 7, 2026
7de0cd7
Formatting
ganyicz Aug 7, 2026
b2293c3
Revert "Reset unblaze after replacing"
ganyicz Aug 7, 2026
f7a735f
Rename
ganyicz Aug 7, 2026
5834fbb
Add todos
ganyicz Aug 7, 2026
67fb5e0
Update BlazeServiceProvider.php
ganyicz Aug 8, 2026
be10c91
Add todos
ganyicz Aug 8, 2026
43e5d31
Formatting
ganyicz Aug 9, 2026
46e2092
Remove todo
ganyicz Aug 9, 2026
baea97e
Refactor
ganyicz Aug 9, 2026
bee1460
Remove todo
ganyicz Aug 9, 2026
69f3887
Refactor
ganyicz Aug 9, 2026
ce12c14
Add todo
ganyicz Aug 9, 2026
e4e31e3
Add EchoNode to parser
ganyicz Aug 9, 2026
b0907f1
Refactor
ganyicz Aug 9, 2026
4c859a0
Remove todo
ganyicz Aug 9, 2026
e14da71
Refactor
ganyicz Aug 9, 2026
48dd8f2
Fix slot injection
ganyicz Aug 9, 2026
a9492a7
Add CompiledBlockNode
ganyicz Aug 9, 2026
49ee1d8
Handle dynamic slot names
ganyicz Aug 9, 2026
88c9f17
Fix container state
ganyicz Aug 10, 2026
fe30dc9
Fix
ganyicz Aug 10, 2026
0614990
Clone nodes
ganyicz Aug 10, 2026
6b71107
Fix
ganyicz Aug 10, 2026
d7a8d68
Formatting
ganyicz Aug 10, 2026
9498cfb
Fix whitespace
ganyicz Aug 10, 2026
f885941
Remove unused slot name resolver
ganyicz Aug 11, 2026
ab460ce
Merge branch 'main' into filip/parser-refactor
ganyicz Aug 11, 2026
1912870
Update AttributeTest.php
ganyicz Aug 11, 2026
80d2750
Fix failing tests
ganyicz Aug 12, 2026
8df68d7
Merge branch 'main' into filip/parser-refactor
ganyicz Aug 12, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 1 addition & 8 deletions src/BladeRenderer.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\File;
use Illuminate\View\Compilers\BladeCompiler;
use Illuminate\View\Component;
use Illuminate\View\ComponentSlot;
use Livewire\Blaze\Parser\Attribute;
use Livewire\Blaze\Parser\Nodes\ComponentNode;
Expand Down Expand Up @@ -70,13 +69,7 @@ public function render(ComponentNode $component, string $path): string
'footer' => [],
'prepareStringsForCompilationUsing' => [
function ($input) {
if (Unblaze::hasUnblaze($input)) {
$input = Unblaze::processUnblazeDirectives($input);
};

$input = $this->manager->compileForFolding($input, $this->blade->getPath());

return $input;
return $this->manager->compileForFolding($input, $this->blade->getPath());
},
],
'path' => null,
Expand Down
109 changes: 25 additions & 84 deletions src/BladeService.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,15 @@
use Illuminate\View\Compilers\BladeCompiler;
use Illuminate\View\Compilers\ComponentTagCompiler;
use Illuminate\View\Factory;
use Livewire\Blaze\Compiler\DirectiveCompiler;
use Livewire\Blaze\Parser\Attribute;
use Livewire\Blaze\Support\LaravelRegex;
use ReflectionClass;

class BladeService
{
protected ComponentTagCompiler $tagCompiler;

protected ReflectionClass $compilerReflection;
protected ReflectionClass $tagCompilerReflection;

protected ?array $customConditions = null;

Expand All @@ -27,6 +28,9 @@ public function __construct(
$compiler->getClassComponentNamespaces(),
$compiler,
);

$this->compilerReflection = new ReflectionClass($this->compiler);
$this->tagCompilerReflection = new ReflectionClass($this->tagCompiler);
}

/**
Expand All @@ -49,77 +53,12 @@ public function earliestPreCompilationHook(callable $callback): void
});
}

/**
* Invoke the Blade compiler's storeUncompiledBlocks via reflection.
*/
public function preStoreUncompiledBlocks(string $input): string
{
$output = $input;

$output = $this->storeVerbatimBlocks($output);
$output = $this->storePhpBlocks($output);

return $output;
}

/**
* Store only @verbatim blocks as raw block placeholders.
*/
public function storeVerbatimBlocks(string $input): string
{
return $this->storeRawBlock(LaravelRegex::VERBATIM_BLOCK, $input);
}

/**
* Store only @verbatim blocks as raw block placeholders.
*/
public function storePhpBlocks(string $input): string
{
return $this->storeRawBlock(LaravelRegex::PHP_BLOCK, $input);
}

/**
* Store a raw block placeholder via the Blade compiler.
*/
protected function storeRawBlock(string $pattern, string $content): string
{
$reflection = new \ReflectionClass($this->compiler);
$method = $reflection->getMethod('storeRawBlock');

return preg_replace_callback($pattern, function ($matches) use ($method) {
return $method->invoke($this->compiler, $matches[0]);
}, $content);
}

/**
* Restore raw block placeholders to their original content.
*/
public function restoreRawBlocks(string $input): string
{
$reflection = new \ReflectionClass($this->compiler);
$method = $reflection->getMethod('restoreRawContent');

return $method->invoke($this->compiler, $input);
}

/**
* Restore raw block placeholders to their original content.
*/
public function restorePhpBlocks(string $input): string
{
$reflection = new \ReflectionClass($this->compiler);
$method = $reflection->getMethod('restorePhpBlocks');

return $method->invoke($this->compiler, $input);
}

/**
* Invoke the Blade compiler's compileComments via reflection.
*/
public function compileComments(string $input): string
{
$reflection = new \ReflectionClass($this->compiler);
$compileComments = $reflection->getMethod('compileComments');
$compileComments = $this->compilerReflection->getMethod('compileComments');

return $compileComments->invoke($this->compiler, $input);
}
Expand All @@ -129,8 +68,7 @@ public function compileComments(string $input): string
*/
public function hasEvenNumberOfParentheses(string $expression): bool
{
$reflection = new ReflectionClass($this->compiler);
$method = $reflection->getMethod('hasEvenNumberOfParentheses');
$method = $this->compilerReflection->getMethod('hasEvenNumberOfParentheses');

return $method->invoke($this->compiler, $expression);
}
Expand Down Expand Up @@ -162,14 +100,11 @@ public function preprocessAttributeString(string $attributeString): string
})->call($this->tagCompiler, $attributeString);
}

public function compileUseStatements(string $input): string
public function compileUseStatements(string $expression): string
{
return DirectiveCompiler::make()->directive('use', function ($expression) {
$reflection = new \ReflectionClass($this->compiler);
$method = $reflection->getMethod('compileUse');
$method = $this->compilerReflection->getMethod('compileUse');

return $method->invoke($this->compiler, $expression);
})->compile($input);
return $method->invoke($this->compiler, $expression);
}

/**
Expand All @@ -181,8 +116,7 @@ public function customConditions(): array
return $this->customConditions;
}

$reflection = new ReflectionClass($this->compiler);
$conditions = $reflection->getProperty('conditions')->getValue($this->compiler);
$conditions = $this->compilerReflection->getProperty('conditions')->getValue($this->compiler);

return $this->customConditions = collect($conditions)->keys()->all();
}
Expand Down Expand Up @@ -212,8 +146,7 @@ public function compileAttribute(Attribute $attribute, bool $escapeBound = false
*/
public function compileAttributeEchos(string $input): string
{
$reflection = new \ReflectionClass($this->tagCompiler);
$method = $reflection->getMethod('compileAttributeEchos');
$method = $this->tagCompilerReflection->getMethod('compileAttributeEchos');

return Str::unwrap("'".$method->invoke($this->tagCompiler, $input)."'", "''.", ".''");
}
Expand Down Expand Up @@ -271,6 +204,16 @@ public function componentNameToPath($name): string
return '';
}

/**
* Check if the Blade compiler has any echo handlers registered.
*/
public function hasEchoHandlers(): bool
{
$handlers = $this->compilerReflection->getProperty('echoHandlers')->getValue($this->compiler);

return ! empty($handlers);
}

/**
* Determine if a component resolves to a class rather than a blade view.
*
Expand Down Expand Up @@ -301,16 +244,14 @@ protected function hasClassBasedComponent(string $name): bool

protected function guessAnonymousComponentUsingNamespaces(Factory $viewFactory, string $component): string|null
{
$reflection = new \ReflectionClass($this->tagCompiler);
$method = $reflection->getMethod('guessAnonymousComponentUsingNamespaces');
$method = $this->tagCompilerReflection->getMethod('guessAnonymousComponentUsingNamespaces');

return $method->invoke($this->tagCompiler, $viewFactory, $component);
}

protected function guessAnonymousComponentUsingPaths(Factory $viewFactory, string $component): string|null
{
$reflection = new \ReflectionClass($this->tagCompiler);
$method = $reflection->getMethod('guessAnonymousComponentUsingPaths');
$method = $this->tagCompilerReflection->getMethod('guessAnonymousComponentUsingPaths');

return $method->invoke($this->tagCompiler, $viewFactory, $component);
}
Expand Down
Loading
Loading