@@ -63,11 +63,43 @@ function displayError(
6363 const sourceStyle = color ? "color: blue" : "" ;
6464 for ( const error of errors ) {
6565 console . error ( `%cError%c: ${ error . message } ` , red , "" ) ;
66- if ( error instanceof PositionedError ) {
67- const position = error . position ;
68- const lines = source . slice ( 0 , position ?. position ) . split ( / \r ? \n / ) ;
69- const line = lines . length ;
70- const column = lines [ lines . length - 1 ] . length + 1 ;
66+ if ( error instanceof PositionedError && error . position != null ) {
67+ const { position, length } = error . position ;
68+ const end = position + length ;
69+ // The only instance returning -1 is useful
70+ const startLine = source . lastIndexOf ( "\n" , position ) + 1 ;
71+ let currentLine = startLine ;
72+ let currentPosition = position ;
73+
74+ while ( true ) {
75+ const index = source . indexOf ( "\n" , currentLine ) ;
76+ const nextLine = index === - 1 ? source . length : index + 1 ;
77+ const line = source . slice ( currentLine , nextLine ) . trimEnd ( ) ;
78+ console . error ( line ) ;
79+ let relativeStart = currentPosition - currentLine ;
80+ let relativeEnd = Math . min ( end - currentLine , line . length ) ;
81+ if ( relativeEnd - relativeStart === 0 ) {
82+ if ( relativeStart !== 0 ) {
83+ relativeStart -- ;
84+ }
85+ if ( relativeEnd !== line . length ) {
86+ relativeEnd ++ ;
87+ }
88+ }
89+ console . error (
90+ `${ " " . repeat ( relativeStart ) } %c${
91+ "^" . repeat ( relativeEnd - relativeStart )
92+ } `,
93+ red ,
94+ ) ;
95+ if ( end <= nextLine ) {
96+ break ;
97+ } else {
98+ currentLine = currentPosition = nextLine ;
99+ }
100+ }
101+ const line = source . slice ( 0 , startLine ) . split ( / \n (? ! $ ) / ) . length ;
102+ const column = position - startLine + 1 ;
71103 console . error ( ` at %c${ SOURCE } :${ line } :${ column } ` , sourceStyle ) ;
72104 console . error ( ) ;
73105 }
0 commit comments