From 10c6156845615f03b89bdec04e811a126120d4ad Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Thu, 9 Jan 2025 17:34:35 -0500 Subject: [PATCH 1/2] fix escaping --- .changeset/shiny-pianos-clean.md | 5 +++++ src/handlers.js | 21 ++++++++++++++++++++- test/quotes.test.js | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 .changeset/shiny-pianos-clean.md diff --git a/.changeset/shiny-pianos-clean.md b/.changeset/shiny-pianos-clean.md new file mode 100644 index 0000000..6eb1a77 --- /dev/null +++ b/.changeset/shiny-pianos-clean.md @@ -0,0 +1,5 @@ +--- +'esrap': patch +--- + +fix: escape newlines when quoting strings diff --git a/src/handlers.js b/src/handlers.js index da0dfdf..13a231b 100644 --- a/src/handlers.js +++ b/src/handlers.js @@ -115,7 +115,26 @@ function prepend_comments(comments, state, newlines) { * @param {'\'' | '"'} char */ function quote(string, char) { - return char + string.replaceAll(char, '\\' + char) + char; + let out = char; + let escaped = false; + + for (const c of string) { + if (escaped) { + out += c; + escaped = false; + } else if (c === '\\') { + out += '\\\\'; + escaped = true; + } else if (c === char) { + out += '\\' + c; + } else if (c === '\n') { + out += '\\n'; + } else { + out += c; + } + } + + return out + char; } const OPERATOR_PRECEDENCE = { diff --git a/test/quotes.test.js b/test/quotes.test.js index a8c8590..c8e1372 100644 --- a/test/quotes.test.js +++ b/test/quotes.test.js @@ -61,3 +61,35 @@ test('escape double quotes if present in string literal', () => { expect(code).toMatchInlineSnapshot(`"const foo = "b\\"ar";"`); }); + +test('escapes new lines', () => { + const ast = load('const str = "a\\nb"'); + clean(ast); + const code = print(ast).code; + + expect(code).toMatchInlineSnapshot(`"const str = 'a\\nb';"`); +}); + +test('escapes escape characters', () => { + const ast = load('const str = "a\\\\nb"'); + clean(ast); + const code = print(ast).code; + + expect(code).toMatchInlineSnapshot(`"const str = 'a\\\\nb';"`); +}); + +test('does not escape already-escaped single quotes', () => { + const ast = load(`const str = 'a\\'b'`); + clean(ast); + const code = print(ast).code; + + expect(code).toMatchInlineSnapshot(`"const str = 'a\\'b';"`); +}); + +test('does not escape already-escaped double quotes', () => { + const ast = load('const str = "a\\"b"'); + clean(ast); + const code = print(ast).code; + + expect(code).toMatchInlineSnapshot(`"const str = 'a"b';"`); +}); From 2ab4b8f5f30b52ec743c02e8eec3cb17422c8114 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 9 Jan 2025 22:39:55 +0000 Subject: [PATCH 2/2] Version Packages --- .changeset/shiny-pianos-clean.md | 5 ----- CHANGELOG.md | 6 ++++++ package.json | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) delete mode 100644 .changeset/shiny-pianos-clean.md diff --git a/.changeset/shiny-pianos-clean.md b/.changeset/shiny-pianos-clean.md deleted file mode 100644 index 6eb1a77..0000000 --- a/.changeset/shiny-pianos-clean.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'esrap': patch ---- - -fix: escape newlines when quoting strings diff --git a/CHANGELOG.md b/CHANGELOG.md index dd49610..5c8f047 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # esrap changelog +## 1.4.1 + +### Patch Changes + +- 10c6156: fix: escape newlines when quoting strings + ## 1.4.0 ### Minor Changes diff --git a/package.json b/package.json index b6d2b8f..fb6cc1c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "esrap", - "version": "1.4.0", + "version": "1.4.1", "description": "Parse in reverse", "repository": { "type": "git",