@@ -26,6 +26,7 @@ const {
2626 ArrayPrototypeJoin,
2727 ArrayPrototypePop,
2828 ArrayPrototypePush,
29+ ArrayPrototypeReduce,
2930 Date,
3031 DatePrototypeGetDate,
3132 DatePrototypeGetHours,
@@ -44,6 +45,8 @@ const {
4445 ObjectSetPrototypeOf,
4546 ObjectValues,
4647 ReflectApply,
48+ RegExp,
49+ RegExpPrototypeSymbolReplace,
4750 StringPrototypePadStart,
4851 StringPrototypeToWellFormed,
4952} = primordials ;
@@ -254,8 +257,7 @@ function styleText(format, text, { validateStream = true, stream = process.stdou
254257 // If the format is not an array, convert it to an array
255258 const formatArray = ArrayIsArray ( format ) ? format : [ format ] ;
256259
257- let left = '' ;
258- let right = '' ;
260+ const codes = [ ] ;
259261 for ( const key of formatArray ) {
260262 if ( key === 'none' ) continue ;
261263 const formatCodes = inspect . colors [ key ] ;
@@ -264,11 +266,56 @@ function styleText(format, text, { validateStream = true, stream = process.stdou
264266 validateOneOf ( key , 'format' , ObjectKeys ( inspect . colors ) ) ;
265267 }
266268 if ( skipColorize ) continue ;
267- left += escapeStyleCode ( formatCodes [ 0 ] ) ;
268- right = `${ escapeStyleCode ( formatCodes [ 1 ] ) } ${ right } ` ;
269+ ArrayPrototypePush ( codes , formatCodes ) ;
269270 }
270271
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 } ` ;
272319}
273320
274321const months = [ 'Jan' , 'Feb' , 'Mar' , 'Apr' , 'May' , 'Jun' , 'Jul' , 'Aug' , 'Sep' ,
0 commit comments