Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 12ff875

Browse filesBrowse files
Merge pull request #10 from laravel/better-blade-parsing
Better Blade parsing
2 parents 2b87dd8 + acc138d commit 12ff875
Copy full SHA for 12ff875

File tree

2 files changed

+67
-33
lines changed
Filter options

2 files changed

+67
-33
lines changed

‎app/Parser/Walker.php

Copy file name to clipboardExpand all lines: app/Parser/Walker.php
+9Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use App\Contexts\Base;
66
use App\Support\Debugs;
77
use Microsoft\PhpParser\Node\SourceFileNode;
8+
use Microsoft\PhpParser\Node\Statement\InlineHtml;
89
use Microsoft\PhpParser\Parser;
910
use Microsoft\PhpParser\SkippedToken;
1011

@@ -31,6 +32,14 @@ public function __construct(protected string $document, $debug = false)
3132

3233
protected function documentSkipsClosingQuote()
3334
{
35+
if (count($this->sourceFile->statementList) === 1 && $this->sourceFile->statementList[0] instanceof InlineHtml) {
36+
// Probably Blade...
37+
$lastChar = substr($this->sourceFile->getFullText(), -1);
38+
$closesWithQuote = in_array($lastChar, ['"', "'"]);
39+
40+
return $closesWithQuote;
41+
}
42+
3443
foreach ($this->sourceFile->getDescendantNodesAndTokens() as $child) {
3544
if ($child instanceof SkippedToken && $child->getText($this->sourceFile->getFullText()) === "'") {
3645
return true;

‎app/Parsers/InlineHtmlParser.php

Copy file name to clipboardExpand all lines: app/Parsers/InlineHtmlParser.php
+58-33Lines changed: 58 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,20 @@
1010
use Microsoft\PhpParser\Parser;
1111
use Microsoft\PhpParser\Range;
1212
use Stillat\BladeParser\Document\Document;
13+
use Stillat\BladeParser\Nodes\BaseNode;
1314
use Stillat\BladeParser\Nodes\DirectiveNode;
1415
use Stillat\BladeParser\Nodes\EchoNode;
1516
use Stillat\BladeParser\Nodes\EchoType;
17+
use Stillat\BladeParser\Nodes\LiteralNode;
1618

1719
class InlineHtmlParser extends AbstractParser
1820
{
21+
protected $echoStrings = [
22+
'{!!' => '!!}',
23+
'{{{' => '}}}',
24+
'{{' => '}}',
25+
];
26+
1927
/**
2028
* @var Blade
2129
*/
@@ -42,6 +50,11 @@ public function parse(InlineHtml $node)
4250
protected function parseBladeContent($node)
4351
{
4452
foreach ($node->getNodes() as $child) {
53+
// TODO: Add other echo types as well
54+
if ($child instanceof LiteralNode) {
55+
$this->parseLiteralNode($child);
56+
}
57+
4558
if ($child instanceof DirectiveNode) {
4659
$this->parseBladeDirective($child);
4760
}
@@ -54,22 +67,18 @@ protected function parseBladeContent($node)
5467
}
5568
}
5669

57-
protected function parseBladeDirective(DirectiveNode $node)
70+
protected function doEchoParse(BaseNode $node, $prefix, $content)
5871
{
59-
if ($node->isClosingDirective || !$node->hasArguments()) {
60-
return;
61-
}
62-
63-
$methodUsed = '@' . $node->content;
64-
$safetyPrefix = 'directive';
65-
$snippet = "<?php\n" . str_repeat(' ', $node->getStartIndentationLevel()) . str_replace($methodUsed, $safetyPrefix . $node->content, $node->toString() . ';');
72+
$snippet = "<?php\n" . str_repeat(' ', $node->getStartIndentationLevel()) . str_replace($prefix, '', $content) . ';';
6673

6774
$sourceFile = (new Parser)->parseSourceFile($snippet);
6875

69-
Settings::$calculatePosition = function (Range $range) use ($node, $safetyPrefix) {
76+
$suffix = $this->echoStrings[$prefix];
77+
78+
Settings::$calculatePosition = function (Range $range) use ($node, $prefix, $suffix) {
7079
if ($range->start->line === 1) {
71-
$range->start->character -= strlen($safetyPrefix) - 1;
72-
$range->end->character -= strlen($safetyPrefix) - 1;
80+
$range->start->character += mb_strlen($prefix);
81+
$range->end->character += mb_strlen($suffix);
7382
}
7483

7584
$range->start->line += $node->position->startLine - 2;
@@ -80,35 +89,42 @@ protected function parseBladeDirective(DirectiveNode $node)
8089

8190
$result = Parse::parse($sourceFile);
8291

83-
$child = $result->children[0];
92+
if (count($result->children) === 0) {
93+
return;
94+
}
8495

85-
$child->methodName = '@' . substr($child->methodName, strlen($safetyPrefix));
96+
$child = $result->children[0];
8697

8798
$this->items[] = $child;
8899
}
89100

90-
protected function parseEchoNode(EchoNode $node)
101+
protected function parseLiteralNode(LiteralNode $node)
91102
{
92-
$snippet = "<?php\n" . str_repeat(' ', $node->getStartIndentationLevel()) . $node->innerContent . ';';
103+
foreach ($this->echoStrings as $prefix => $suffix) {
104+
if (!str_starts_with($node->content, $prefix)) {
105+
continue;
106+
}
93107

94-
$sourceFile = (new Parser)->parseSourceFile($snippet);
108+
$this->doEchoParse($node, $prefix, $node->content);
109+
}
110+
}
95111

96-
Settings::$calculatePosition = function (Range $range) use ($node) {
97-
$prefix = match ($node->type) {
98-
EchoType::RawEcho => '{!!',
99-
EchoType::TripleEcho => '{{{',
100-
default => '{{',
101-
};
112+
protected function parseBladeDirective(DirectiveNode $node)
113+
{
114+
if ($node->isClosingDirective || !$node->hasArguments()) {
115+
return;
116+
}
102117

103-
$suffix = match ($node->type) {
104-
EchoType::RawEcho => '!!}',
105-
EchoType::TripleEcho => '}}}',
106-
default => '}}',
107-
};
118+
$methodUsed = '@' . $node->content;
119+
$safetyPrefix = 'directive';
120+
$snippet = "<?php\n" . str_repeat(' ', $node->getStartIndentationLevel()) . str_replace($methodUsed, $safetyPrefix . $node->content, $node->toString() . ';');
108121

122+
$sourceFile = (new Parser)->parseSourceFile($snippet);
123+
124+
Settings::$calculatePosition = function (Range $range) use ($node, $safetyPrefix) {
109125
if ($range->start->line === 1) {
110-
$range->start->character += strlen($prefix);
111-
$range->end->character += strlen($suffix);
126+
$range->start->character -= mb_strlen($safetyPrefix) - 1;
127+
$range->end->character -= mb_strlen($safetyPrefix) - 1;
112128
}
113129

114130
$range->start->line += $node->position->startLine - 2;
@@ -119,12 +135,21 @@ protected function parseEchoNode(EchoNode $node)
119135

120136
$result = Parse::parse($sourceFile);
121137

122-
if (count($result->children) === 0) {
123-
return;
124-
}
125-
126138
$child = $result->children[0];
127139

140+
$child->methodName = '@' . substr($child->methodName, mb_strlen($safetyPrefix));
141+
128142
$this->items[] = $child;
129143
}
144+
145+
protected function parseEchoNode(EchoNode $node)
146+
{
147+
$prefix = match ($node->type) {
148+
EchoType::RawEcho => '{!!',
149+
EchoType::TripleEcho => '{{{',
150+
default => '{{',
151+
};
152+
153+
$this->doEchoParse($node, $prefix, $node->innerContent);
154+
}
130155
}

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.