@@ -40,8 +40,8 @@ const terminalStyles = {
40
40
// Log level icons/badges similar to consola
41
41
const levelIcons = {
42
42
debug : '🔍' ,
43
- info : 'ℹ' ,
44
- success : '✓' ,
43
+ info : terminalStyles . green ( 'ℹ' ) ,
44
+ success : terminalStyles . green ( '✓' ) ,
45
45
warning : terminalStyles . yellow ( 'WARN' ) , // Use badge style for warnings
46
46
error : terminalStyles . red ( 'ERROR' ) , // Use badge style for errors
47
47
}
@@ -100,6 +100,7 @@ export class Logger {
100
100
private fancy : boolean // Whether to use fancy terminal output
101
101
private tagFormat : TagFormat
102
102
private timestampPosition : 'left' | 'right'
103
+ private readonly ANSI_PATTERN = / \u001B \[ \d + m / g
103
104
104
105
constructor ( name : string , options : Partial < ExtendedLoggerOptions > = { } ) {
105
106
this . name = name
@@ -791,12 +792,29 @@ export class Logger {
791
792
}
792
793
793
794
private formatConsoleTimestamp ( date : Date ) : string {
794
- return terminalStyles . gray ( date . toLocaleTimeString ( ) )
795
+ return this . fancy ? terminalStyles . gray ( date . toLocaleTimeString ( ) ) : date . toLocaleTimeString ( )
795
796
}
796
797
797
798
private formatConsoleMessage ( parts : { timestamp : string , icon ?: string , tag ?: string , message : string , level ?: LogLevel , showTimestamp ?: boolean } ) : string {
798
799
const { timestamp, icon = '' , tag = '' , message, level, showTimestamp = true } = parts
799
800
801
+ // If fancy mode is disabled, return a simple format
802
+ if ( ! this . fancy ) {
803
+ const components = [ ]
804
+ if ( showTimestamp )
805
+ components . push ( timestamp )
806
+ if ( level === 'warning' )
807
+ components . push ( 'WARN' )
808
+ else if ( level === 'error' )
809
+ components . push ( 'ERROR' )
810
+ else if ( icon )
811
+ components . push ( icon . replace ( / [ ^ \p{ L} \p{ N} \p{ P} \p{ Z} ] / gu, '' ) )
812
+ if ( tag )
813
+ components . push ( tag . replace ( / [ [ \] ] / g, '' ) )
814
+ components . push ( message )
815
+ return components . join ( ' ' )
816
+ }
817
+
800
818
// Get terminal width, default to 120 if not available
801
819
const terminalWidth = process . stdout . columns || 120
802
820
@@ -806,10 +824,14 @@ export class Logger {
806
824
// For warning and error, show badge-style level indicator
807
825
mainPart = `${ icon } ${ message } `
808
826
}
809
- else {
810
- // For other levels, show icon followed by message
827
+ else if ( level === 'info' || level === 'success' ) {
828
+ // For info and success, keep icon colored but message plain
811
829
mainPart = `${ icon } ${ tag } ${ message } `
812
830
}
831
+ else {
832
+ // For other levels, apply standard formatting
833
+ mainPart = `${ icon } ${ tag } ${ terminalStyles . cyan ( message ) } `
834
+ }
813
835
814
836
// If we don't need to show timestamp, just return the message
815
837
if ( ! showTimestamp ) {
@@ -821,6 +843,48 @@ export class Logger {
821
843
return `${ mainPart . trim ( ) } ${ ' ' . repeat ( padding ) } ${ timestamp } `
822
844
}
823
845
846
+ private formatMessage ( message : string , args : any [ ] ) : string {
847
+ // If the last argument is an array, use positional {n} formatting
848
+ if ( args . length === 1 && Array . isArray ( args [ 0 ] ) ) {
849
+ return message . replace ( / \{ ( \d + ) \} / g, ( match , index ) => {
850
+ const position = Number . parseInt ( index , 10 )
851
+ return position < args [ 0 ] . length ? String ( args [ 0 ] [ position ] ) : match
852
+ } )
853
+ }
854
+
855
+ // Otherwise use the existing %s style formatting
856
+ const formatRegex = / % ( [ s d i j f o % ] ) / g
857
+ let argIndex = 0
858
+ let formattedMessage = message . replace ( formatRegex , ( match , type ) => {
859
+ if ( type === '%' )
860
+ return '%'
861
+ if ( argIndex >= args . length )
862
+ return match
863
+ const arg = args [ argIndex ++ ]
864
+ switch ( type ) {
865
+ case 's' :
866
+ return String ( arg )
867
+ case 'd' :
868
+ case 'i' :
869
+ return Number ( arg ) . toString ( )
870
+ case 'j' :
871
+ case 'o' :
872
+ return JSON . stringify ( arg , null , 2 )
873
+ default :
874
+ return match
875
+ }
876
+ } )
877
+
878
+ // Append any remaining args
879
+ if ( argIndex < args . length ) {
880
+ formattedMessage += ` ${ args . slice ( argIndex ) . map ( arg =>
881
+ typeof arg === 'object' ? JSON . stringify ( arg , null , 2 ) : String ( arg ) ,
882
+ ) . join ( ' ' ) } `
883
+ }
884
+
885
+ return formattedMessage
886
+ }
887
+
824
888
private async log ( level : LogLevel , message : string | Error , ...args : any [ ] ) : Promise < void > {
825
889
if ( ! this . shouldLog ( level ) )
826
890
return
@@ -838,40 +902,7 @@ export class Logger {
838
902
errorStack = message . stack
839
903
}
840
904
else {
841
- formattedMessage = message
842
- }
843
-
844
- // Format the message with format strings if there are args
845
- if ( args && args . length > 0 ) {
846
- // Handle format strings
847
- const formatRegex = / % ( [ s d i j f o % ] ) / g
848
- let argIndex = 0
849
- formattedMessage = formattedMessage . replace ( formatRegex , ( match , type ) => {
850
- if ( type === '%' )
851
- return '%'
852
- if ( argIndex >= args . length )
853
- return match
854
- const arg = args [ argIndex ++ ]
855
- switch ( type ) {
856
- case 's' :
857
- return String ( arg )
858
- case 'd' :
859
- case 'i' :
860
- return Number ( arg ) . toString ( )
861
- case 'j' :
862
- case 'o' :
863
- return JSON . stringify ( arg , null , 2 )
864
- default :
865
- return match
866
- }
867
- } )
868
-
869
- // Append any remaining args
870
- if ( argIndex < args . length ) {
871
- formattedMessage += ` ${ args . slice ( argIndex ) . map ( arg =>
872
- typeof arg === 'object' ? JSON . stringify ( arg , null , 2 ) : String ( arg ) ,
873
- ) . join ( ' ' ) } `
874
- }
905
+ formattedMessage = this . formatMessage ( message , args )
875
906
}
876
907
877
908
// Format console output
0 commit comments