12
12
use Toolkit \Cli \Color ;
13
13
use function preg_match_all ;
14
14
use function preg_replace ;
15
+ use function preg_replace_callback ;
15
16
use function sprintf ;
16
17
use function str_replace ;
17
18
use function strpos ;
@@ -27,7 +28,7 @@ class ColorTag
27
28
public const STRIP_TAG = '/<[\/]?[a-zA-Z0-9=;]+>/ ' ;
28
29
29
30
// Regex to match tags/
30
- public const MATCH_TAG = '/<([a-zA-Z0-9=;_]+)>(.*? )<\/ \\1>/s ' ;
31
+ public const MATCH_TAG = '/<([a-zA-Z0-9=;_]+)>(.*)<\/ \\1>/s ' ;
31
32
32
33
// color
33
34
public const BLACK = 'black ' ;
@@ -109,10 +110,11 @@ public static function matchAll(string $text): array
109
110
110
111
/**
111
112
* @param string $text
113
+ * @param bool $recursive parse nested tags
112
114
*
113
115
* @return string
114
116
*/
115
- public static function parse (string $ text ): string
117
+ public static function parse (string $ text, bool $ recursive = false ): string
116
118
{
117
119
if (!$ text || false === strpos ($ text , '</ ' )) {
118
120
return $ text ;
@@ -123,24 +125,41 @@ public static function parse(string $text): string
123
125
return self ::strip ($ text );
124
126
}
125
127
126
- // match color tags
127
- if (!$ matches = self ::matchAll ($ text )) {
128
- return $ text ;
129
- }
128
+ return self ::pregReplaceTags ($ text , $ recursive );
129
+ }
130
130
131
- foreach ((array )$ matches [0 ] as $ i => $ m ) {
132
- $ key = $ matches [1 ][$ i ];
131
+ /**
132
+ * @param string $text
133
+ * @param bool $recursive
134
+ *
135
+ * @return string
136
+ */
137
+ public static function pregReplaceTags (string $ text , bool $ recursive = false ): string
138
+ {
139
+ return preg_replace_callback (self ::MATCH_TAG , static function (array $ match ) use ($ recursive ) {
140
+ $ colorCode = '' ;
141
+ $ tagName = $ match [1 ];
142
+
143
+ if (isset (Color::STYLES [$ tagName ])) {
144
+ $ colorCode = Color::STYLES [$ tagName ];
145
+ } elseif (strpos ($ tagName , '= ' )) {
146
+ $ colorCode = Color::stringToCode ($ tagName );
147
+ }
133
148
134
- if (isset (Color::STYLES [$ key ])) {
135
- $ text = self ::replaceColor ($ text , $ key , $ matches [2 ][$ i ], Color::STYLES [$ key ]);
149
+ // enhance: support parse nested tags
150
+ $ body = $ match [2 ];
151
+ if ($ recursive && false !== strpos ($ body , '</ ' )) {
152
+ $ body = self ::pregReplaceTags ($ body , $ recursive );
153
+ }
136
154
137
- /** Custom style format @see Color::stringToCode() */
138
- } elseif ( strpos ( $ key , ' = ' ) ) {
139
- $ text = self :: replaceColor ( $ text , $ key , $ matches [ 2 ][ $ i ], Color:: stringToCode ( $ key ) );
155
+ // wrap body with color codes
156
+ if ( $ colorCode ) {
157
+ return sprintf ( "\033 [%sm%s \033 [0m " , $ colorCode , $ body );
140
158
}
141
- }
142
159
143
- return $ text ;
160
+ // return raw contents.
161
+ return $ match [0 ];
162
+ }, $ text );
144
163
}
145
164
146
165
/**
0 commit comments