Skip to content

Commit 029d0cb

Browse files
committed
Merge branch 'main' into sourcemap-mappings
2 parents 42daa43 + e1caca6 commit 029d0cb

File tree

4 files changed

+59
-2
lines changed

4 files changed

+59
-2
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# esrap changelog
22

3+
## 1.4.1
4+
5+
### Patch Changes
6+
7+
- 10c6156: fix: escape newlines when quoting strings
8+
39
## 1.4.0
410

511
### Minor Changes

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "esrap",
3-
"version": "1.4.0",
3+
"version": "1.4.1",
44
"description": "Parse in reverse",
55
"repository": {
66
"type": "git",

src/handlers.js

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,26 @@ function prepend_comments(comments, state, newlines) {
115115
* @param {'\'' | '"'} char
116116
*/
117117
function quote(string, char) {
118-
return char + string.replaceAll(char, '\\' + char) + char;
118+
let out = char;
119+
let escaped = false;
120+
121+
for (const c of string) {
122+
if (escaped) {
123+
out += c;
124+
escaped = false;
125+
} else if (c === '\\') {
126+
out += '\\\\';
127+
escaped = true;
128+
} else if (c === char) {
129+
out += '\\' + c;
130+
} else if (c === '\n') {
131+
out += '\\n';
132+
} else {
133+
out += c;
134+
}
135+
}
136+
137+
return out + char;
119138
}
120139

121140
const OPERATOR_PRECEDENCE = {

test/quotes.test.js

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,3 +61,35 @@ test('escape double quotes if present in string literal', () => {
6161

6262
expect(code).toMatchInlineSnapshot(`"const foo = "b\\"ar";"`);
6363
});
64+
65+
test('escapes new lines', () => {
66+
const ast = load('const str = "a\\nb"');
67+
clean(ast);
68+
const code = print(ast).code;
69+
70+
expect(code).toMatchInlineSnapshot(`"const str = 'a\\nb';"`);
71+
});
72+
73+
test('escapes escape characters', () => {
74+
const ast = load('const str = "a\\\\nb"');
75+
clean(ast);
76+
const code = print(ast).code;
77+
78+
expect(code).toMatchInlineSnapshot(`"const str = 'a\\\\nb';"`);
79+
});
80+
81+
test('does not escape already-escaped single quotes', () => {
82+
const ast = load(`const str = 'a\\'b'`);
83+
clean(ast);
84+
const code = print(ast).code;
85+
86+
expect(code).toMatchInlineSnapshot(`"const str = 'a\\'b';"`);
87+
});
88+
89+
test('does not escape already-escaped double quotes', () => {
90+
const ast = load('const str = "a\\"b"');
91+
clean(ast);
92+
const code = print(ast).code;
93+
94+
expect(code).toMatchInlineSnapshot(`"const str = 'a"b';"`);
95+
});

0 commit comments

Comments
 (0)