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