@@ -29,6 +29,24 @@ function collectComments(node: SyntaxNode): string | undefined {
2929 return undefined ;
3030}
3131
32+ /**
33+ * Map of escape characters to their resolved values.
34+ * Used by both PHP (encapsed_string) and JS (string) handlers.
35+ */
36+ const escapeMap : Record < string , string > = {
37+ 'n' : '\n' ,
38+ 'r' : '\r' ,
39+ 't' : '\t' ,
40+ 'f' : '\f' ,
41+ 'v' : '\v' ,
42+ '0' : '\0' ,
43+ '\\' : '\\' ,
44+ '"' : '"' ,
45+ "'" : "'" ,
46+ '$' : '$' ,
47+ 'e' : '\x1b' ,
48+ } ;
49+
3250/**
3351 * Resolves the actual string value from a tree-sitter node,
3452 * handling escape sequences in double-quoted strings.
@@ -42,19 +60,9 @@ function resolveStringValue(node: SyntaxNode): string {
4260 return node . children
4361 . map ( ( child ) => {
4462 if ( child . type === 'escape_sequence' ) {
45- // Unescape common sequences
46- switch ( child . text ) {
47- case '\\n' : return '\n' ;
48- case '\\r' : return '\r' ;
49- case '\\t' : return '\t' ;
50- case '\\\\' : return '\\' ;
51- case '\\"' : return '"' ;
52- case '\\$' : return '$' ;
53- case '\\e' : return '\x1b' ;
54- case '\\f' : return '\f' ;
55- case '\\v' : return '\v' ;
56- default : return child . text ;
57- }
63+ // child.text is e.g. "\\n" — the char after the backslash is the key
64+ const ch = child . text . slice ( 1 ) ;
65+ return ch in escapeMap ? escapeMap [ ch ] : child . text ;
5866 }
5967 // Return literal content
6068 if ( child . type === 'string_content' ) {
@@ -75,8 +83,18 @@ function resolveStringValue(node: SyntaxNode): string {
7583 // Strip surrounding quotes if present
7684 if ( ( text . startsWith ( "'" ) && text . endsWith ( "'" ) ) ||
7785 ( text . startsWith ( '"' ) && text . endsWith ( '"' ) ) ) {
78- // Remove quotes and unescape escaped quotes
79- return text . slice ( 1 , - 1 ) . replace ( / \\ ' / g, "'" ) . replace ( / \\ \\ / g, "\\" ) ;
86+ const isDouble = text . startsWith ( '"' ) ;
87+ let inner = text . slice ( 1 , - 1 ) ;
88+ if ( isDouble ) {
89+ // Unescape common escape sequences for double-quoted strings
90+ inner = inner . replace ( / \\ ( .) / g, ( _match , ch ) =>
91+ ch in escapeMap ? escapeMap [ ch ] : _match
92+ ) ;
93+ } else {
94+ // Single-quoted: only unescape \\ and \'
95+ inner = inner . replace ( / \\ ' / g, "'" ) . replace ( / \\ \\ / g, "\\" ) ;
96+ }
97+ return inner ;
8098 }
8199 }
82100
0 commit comments