File tree Expand file tree Collapse file tree 5 files changed +36
-6
lines changed
Expand file tree Collapse file tree 5 files changed +36
-6
lines changed Original file line number Diff line number Diff line change @@ -20,7 +20,7 @@ final class Buffer implements \IteratorAggregate
2020 public function __construct (
2121 /** @internal */
2222 private readonly \Generator $ generator ,
23- private int $ offset = 0
23+ private int $ offset = 0 ,
2424 ) {
2525 }
2626
@@ -136,4 +136,9 @@ public function replay(int $offset): void
136136 }
137137 }
138138 }
139+
140+ public function cleanReplay (): void
141+ {
142+ $ this ->replay = [];
143+ }
139144}
Original file line number Diff line number Diff line change @@ -229,6 +229,12 @@ private function finalize(): bool
229229 {
230230 $ tokens = $ this ->tokens ;
231231
232+ // A directive must have at least one keyword
233+ // Without it, it's just a char
234+ if (\count ($ tokens ) === 1 && $ tokens [0 ]->content === self ::DIRECTIVE_CHAR ) {
235+ return false ;
236+ }
237+
232238 foreach (\array_reverse ($ tokens , true ) as $ i => $ t ) {
233239 if ($ t ->type !== DynamicGrammar::TYPE_WHITESPACE ) {
234240 break ;
Original file line number Diff line number Diff line change @@ -45,20 +45,20 @@ final class DynamicGrammar implements GrammarInterface
4545 private readonly BracesGrammar $ raw ;
4646
4747 public function __construct (
48- private readonly ?DirectiveRendererInterface $ directiveRenderer = null
48+ private readonly ?DirectiveRendererInterface $ directiveRenderer = null ,
4949 ) {
5050 $ this ->echo = new BracesGrammar (
5151 '{{ ' ,
5252 '}} ' ,
5353 self ::TYPE_OPEN_TAG ,
54- self ::TYPE_CLOSE_TAG
54+ self ::TYPE_CLOSE_TAG ,
5555 );
5656
5757 $ this ->raw = new BracesGrammar (
5858 '{!! ' ,
5959 '!!} ' ,
6060 self ::TYPE_OPEN_RAW_TAG ,
61- self ::TYPE_CLOSE_RAW_TAG
61+ self ::TYPE_CLOSE_RAW_TAG ,
6262 );
6363 }
6464
@@ -107,6 +107,10 @@ public function parse(Buffer $src): \Generator
107107
108108 $ src ->replay ($ directive ->getLastOffset ());
109109 continue ;
110+ } else {
111+ // When we found directive char but it's not a directive, we need to clean the replay buffer
112+ // because it may contain extra tokens that we don't need to return back to the stream
113+ $ src ->cleanReplay ();
110114 }
111115
112116 $ src ->replay ($ n ->offset );
Original file line number Diff line number Diff line change 22
33declare (strict_types=1 );
44
5- namespace Directive ;
5+ namespace Spiral \ Tests \ Stempler \ Directive ;
66
77use Spiral \Tests \Stempler \fixtures \ImageDirective ;
8- use Spiral \Tests \Stempler \Directive \BaseTestCase ;
98
109final class DirectiveTest extends BaseTestCase
1110{
Original file line number Diff line number Diff line change 44
55namespace Spiral \Tests \Stempler \Transform ;
66
7+ use PHPUnit \Framework \Attributes \DataProvider ;
78use Spiral \Stempler \Directive \LoopDirective ;
89use Spiral \Stempler \Node \PHP ;
10+ use Spiral \Stempler \Node \Raw ;
911use Spiral \Stempler \Transform \Finalizer \DynamicToPHP ;
1012
1113class DynamicToPHPTest extends BaseTestCase
@@ -17,6 +19,20 @@ public function testOutput(): void
1719 self ::assertInstanceOf (PHP ::class, $ doc ->nodes [0 ]);
1820 }
1921
22+ public static function provideStringWithoutDirective (): iterable
23+ {
24+ yield ['https://unpkg.com/tailwindcss@^1.6/dist/tailwind.min.css ' ];
25+ }
26+
27+ #[DataProvider('provideStringWithoutDirective ' )]
28+ public function testLinkWithReservedSymbol (string $ string ): void
29+ {
30+ $ doc = $ this ->parse ($ string );
31+
32+ self ::assertInstanceOf (Raw::class, $ doc ->nodes [0 ]);
33+ self ::assertSame ($ string , $ doc ->nodes [0 ]->content );
34+ }
35+
2036 public function testDirective (): void
2137 {
2238 $ doc = $ this ->parse ('@foreach($users as $u) @endforeach ' );
You can’t perform that action at this time.
0 commit comments