@@ -34,10 +34,11 @@ class ComponentLexer extends Lexer
3434 public const BLOCK_TAGS_CLOSE = '/<\s*\/\s*t:block\s*>/ ' ;
3535 public const ATTRIBUTE_BAG_REGEX = '/(?:^|\s+)\{\{\s*(attributes(?:.+?(?<!\s))?)\s*\}\}/x ' ;
3636 public const ATTRIBUTE_KEY_VALUE_REGEX = '/(?<attribute>[\w\-:.@]+)(=(?<value>(\"[^\"]+\"| \\\'[^ \\\']+ \\\'|[^\s>]+)))?/x ' ;
37-
37+
3838 public function tokenize (Source $ source ): TokenStream
3939 {
40- $ preparsed = $ this ->preparsed ($ source ->getCode ());
40+ $ preLexer = new TwigPreLexer ();
41+ $ preparsed = $ preLexer ->preLexComponents ($ source ->getCode ());
4142
4243 return parent ::tokenize (
4344 new Source (
@@ -47,124 +48,4 @@ public function tokenize(Source $source): TokenStream
4748 )
4849 );
4950 }
50-
51- private function preparsed (string $ value )
52- {
53- $ value = $ this ->lexBlockTags ($ value );
54- $ value = $ this ->lexBlockTagsClose ($ value );
55- $ value = $ this ->lexSelfCloseTag ($ value );
56- $ value = $ this ->lexOpeningTags ($ value );
57- $ value = $ this ->lexClosingTag ($ value );
58-
59- return $ value ;
60- }
61-
62- private function lexOpeningTags (string $ value )
63- {
64- return preg_replace_callback (
65- self ::OPEN_TAGS_REGEX ,
66- function (array $ matches ) {
67- $ name = $ matches ['name ' ];
68- $ attributes = $ this ->getAttributesFromAttributeString ($ matches ['attributes ' ]);
69-
70- return '{% component ' .$ name .' with ' .$ attributes .'%} ' ;
71- },
72- $ value
73- );
74- }
75-
76- private function lexClosingTag (string $ value )
77- {
78- return preg_replace (self ::CLOSE_TAGS_REGEX , '{% endcomponent %} ' , $ value );
79- }
80-
81- private function lexSelfCloseTag (string $ value )
82- {
83- return preg_replace_callback (
84- self ::SELF_CLOSE_TAGS_REGEX ,
85- function (array $ matches ) {
86- $ name = $ matches ['name ' ];
87- $ attributes = $ this ->getAttributesFromAttributeString ($ matches ['attributes ' ]);
88-
89- return "{{ component(' " .$ name ."', " .$ attributes .') }} ' ;
90- },
91- $ value
92- );
93- }
94-
95- private function lexBlockTags (string $ value )
96- {
97- return preg_replace_callback (
98- self ::BLOCK_TAGS_OPEN ,
99- function (array $ matches ) {
100- $ name = $ matches ['name ' ];
101-
102- return '{% block ' .$ name .' %} ' ;
103- },
104- $ value
105- );
106- }
107-
108- private function lexBlockTagsClose (string $ value )
109- {
110- return preg_replace (
111- self ::BLOCK_TAGS_CLOSE ,
112- '{% endblock %} ' ,
113- $ value
114- );
115- }
116-
117- protected function getAttributesFromAttributeString (string $ attributeString )
118- {
119- $ attributeString = $ this ->parseAttributeBag ($ attributeString );
120-
121- if (!preg_match_all (self ::ATTRIBUTE_KEY_VALUE_REGEX , $ attributeString , $ matches , \PREG_SET_ORDER )) {
122- return '{} ' ;
123- }
124-
125- $ attributes = [];
126- foreach ($ matches as $ match ) {
127- $ attribute = $ match ['attribute ' ];
128- $ value = $ match ['value ' ] ?? null ;
129-
130- if (null === $ value ) {
131- $ value = 'true ' ;
132- }
133-
134- if (str_starts_with ($ attribute , ': ' )) {
135- $ attribute = str_replace (': ' , '' , $ attribute );
136- $ value = $ this ->stripQuotes ($ value );
137- }
138-
139- $ valueWithoutQuotes = $ this ->stripQuotes ($ value );
140-
141- if (str_starts_with ($ valueWithoutQuotes , '{{ ' ) && (strpos ($ valueWithoutQuotes , '}} ' ) === \strlen ($ valueWithoutQuotes ) - 2 )) {
142- $ value = substr ($ valueWithoutQuotes , 2 , -2 );
143- } else {
144- $ value = $ value ;
145- }
146-
147- $ attributes [$ attribute ] = $ value ;
148- }
149-
150- $ out = '{ ' ;
151- foreach ($ attributes as $ key => $ value ) {
152- $ key = "' $ key' " ;
153- $ out .= "$ key: $ value, " ;
154- }
155-
156- return rtrim ($ out , ', ' ).'} ' ;
157- }
158-
159- public function stripQuotes (string $ value )
160- {
161- return str_starts_with ($ value , '" ' ) || str_starts_with ($ value , '\'' )
162- ? substr ($ value , 1 , -1 )
163- : $ value ;
164- }
165-
166- protected function parseAttributeBag (string $ attributeString )
167- {
168- return preg_replace (self ::ATTRIBUTE_BAG_REGEX , ' :attributes="$1" ' , $ attributeString );
169- }
17051}
0 commit comments