@@ -26,6 +26,7 @@ const {
26
26
ArrayPrototypeJoin,
27
27
ArrayPrototypePop,
28
28
ArrayPrototypePush,
29
+ ArrayPrototypeReduce,
29
30
Date,
30
31
DatePrototypeGetDate,
31
32
DatePrototypeGetHours,
@@ -44,6 +45,8 @@ const {
44
45
ObjectSetPrototypeOf,
45
46
ObjectValues,
46
47
ReflectApply,
48
+ RegExp,
49
+ RegExpPrototypeSymbolReplace,
47
50
StringPrototypePadStart,
48
51
StringPrototypeToWellFormed,
49
52
} = primordials ;
@@ -254,8 +257,7 @@ function styleText(format, text, { validateStream = true, stream = process.stdou
254
257
// If the format is not an array, convert it to an array
255
258
const formatArray = ArrayIsArray ( format ) ? format : [ format ] ;
256
259
257
- let left = '' ;
258
- let right = '' ;
260
+ const codes = [ ] ;
259
261
for ( const key of formatArray ) {
260
262
if ( key === 'none' ) continue ;
261
263
const formatCodes = inspect . colors [ key ] ;
@@ -264,11 +266,56 @@ function styleText(format, text, { validateStream = true, stream = process.stdou
264
266
validateOneOf ( key , 'format' , ObjectKeys ( inspect . colors ) ) ;
265
267
}
266
268
if ( skipColorize ) continue ;
267
- left += escapeStyleCode ( formatCodes [ 0 ] ) ;
268
- right = `${ escapeStyleCode ( formatCodes [ 1 ] ) } ${ right } ` ;
269
+ ArrayPrototypePush ( codes , formatCodes ) ;
269
270
}
270
271
271
- return skipColorize ? text : `${ left } ${ text } ${ right } ` ;
272
+ if ( skipColorize ) {
273
+ return text ;
274
+ }
275
+
276
+ // Build opening codes
277
+ let openCodes = '' ;
278
+ for ( let i = 0 ; i < codes . length ; i ++ ) {
279
+ openCodes += escapeStyleCode ( codes [ i ] [ 0 ] ) ;
280
+ }
281
+
282
+ // Process the text to handle nested styles
283
+ let processedText ;
284
+ if ( codes . length > 0 ) {
285
+ processedText = ArrayPrototypeReduce (
286
+ codes ,
287
+ ( text , code ) => RegExpPrototypeSymbolReplace (
288
+ // Find the reset code
289
+ new RegExp ( `\\u001b\\[${ code [ 1 ] } m` , 'g' ) ,
290
+ text ,
291
+ ( match , offset ) => {
292
+ // Check if there's more content after this reset
293
+ if ( offset + match . length < text . length ) {
294
+ if (
295
+ code [ 0 ] === inspect . colors . dim [ 0 ] ||
296
+ code [ 0 ] === inspect . colors . bold [ 0 ]
297
+ ) {
298
+ // Dim and bold are not mutually exclusive, so we need to reapply
299
+ return `${ match } ${ escapeStyleCode ( code [ 0 ] ) } ` ;
300
+ }
301
+ return `${ escapeStyleCode ( code [ 0 ] ) } ` ;
302
+ }
303
+ return match ;
304
+ } ,
305
+ ) ,
306
+ text ,
307
+ ) ;
308
+ } else {
309
+ processedText = text ;
310
+ }
311
+
312
+ // Build closing codes in reverse order
313
+ let closeCodes = '' ;
314
+ for ( let i = codes . length - 1 ; i >= 0 ; i -- ) {
315
+ closeCodes += escapeStyleCode ( codes [ i ] [ 1 ] ) ;
316
+ }
317
+
318
+ return `${ openCodes } ${ processedText } ${ closeCodes } ` ;
272
319
}
273
320
274
321
const months = [ 'Jan' , 'Feb' , 'Mar' , 'Apr' , 'May' , 'Jun' , 'Jul' , 'Aug' , 'Sep' ,
0 commit comments