@@ -21,14 +21,44 @@ export function getAppendCommaPos(text: string) {
2121 scanner . setText ( text ) ;
2222
2323 try {
24- if ( scanner . scan ( ) === ts . SyntaxKind . EndOfFileToken )
24+ let token = scanner . scan ( ) ;
25+
26+ if ( token === ts . SyntaxKind . EndOfFileToken )
2527 return - 1 ;
2628
27- while ( scanner . scan ( ) !== ts . SyntaxKind . EndOfFileToken ) {
28- // just keep scanning...
29+ // A stack to track nested template literals and their inner brace expressions
30+ // otherwise, the scanner will interpret text in template literals as actual tokens,
31+ // e.g. the /* in `${p}/*` will be interpreted as a comment, not inside the template literal
32+ const templateStack : ts . SyntaxKind [ ] = [ ] ;
33+
34+ while ( token !== ts . SyntaxKind . EndOfFileToken ) {
35+ switch ( token ) {
36+ case ts . SyntaxKind . TemplateHead :
37+ templateStack . push ( token ) ;
38+ break ;
39+ case ts . SyntaxKind . OpenBraceToken :
40+ if ( templateStack . length > 0 )
41+ templateStack . push ( token ) ;
42+ break ;
43+ case ts . SyntaxKind . CloseBraceToken : {
44+ if ( templateStack . length > 0 ) {
45+ const lastTemplateStackToken = templateStack . at ( - 1 ) ;
46+ if ( lastTemplateStackToken === ts . SyntaxKind . TemplateHead ) {
47+ // Re-scan the template token to skip the inner text
48+ token = scanner . reScanTemplateToken ( false ) ;
49+ // Only pop for TemplateTail, not for TemplateMiddle
50+ if ( token === ts . SyntaxKind . TemplateTail )
51+ templateStack . pop ( ) ;
52+ } else
53+ templateStack . pop ( ) ;
54+ }
55+ break ;
56+ }
57+ }
58+ token = scanner . scan ( ) ;
2959 }
3060
31- const pos = scanner . getStartPos ( ) ;
61+ const pos = scanner . getTokenFullStart ( ) ;
3262 return text [ pos - 1 ] === "," ? - 1 : pos ;
3363 } finally {
3464 // ensure the scanner doesn't hold onto the text so the string
0 commit comments