diff --git a/src/baseTranspiler.ts b/src/baseTranspiler.ts index c2d7de3..0db41db 100644 --- a/src/baseTranspiler.ts +++ b/src/baseTranspiler.ts @@ -962,13 +962,16 @@ class BaseTranspiler { if (text in this.StringLiteralReplacements) { return this.StringLiteralReplacements[text]; } + // trick to preserve valid backslashes (e.g. \n, \t) + const backslashPlaceholder = "\x00"; + text = text.replaceAll("\\", backslashPlaceholder); text = text.replaceAll("\b", "\\b"); text = text.replaceAll("\f", "\\f"); text = text.replaceAll("\n", "\\n"); text = text.replaceAll("\r", "\\r"); text = text.replaceAll("\t", "\\t"); + text = text.replaceAll(backslashPlaceholder, "\\\\"); if (token === "'") { - text = text.replaceAll("\\\"", "\""); // unscape double quotes text = text.replaceAll("'", "\\'"); // escape single quotes } else if (token === "\"") { text = text.replaceAll("\"", "\\\""); // escape double quotes diff --git a/src/goTranspiler.ts b/src/goTranspiler.ts index ef8bd77..38128e1 100644 --- a/src/goTranspiler.ts +++ b/src/goTranspiler.ts @@ -169,9 +169,17 @@ export class GoTranspiler extends BaseTranspiler { if (text in this.StringLiteralReplacements) { return this.StringLiteralReplacements[text]; } - text = text.replaceAll("'", "\\\\" + "'"); - text = text.replaceAll("\"", "\\" + "\""); + // Preserve real backslashes + const backslashPlaceholder = "\x00"; + text = text.replaceAll("\\", backslashPlaceholder); + text = text.replaceAll("\b", "\\b"); + text = text.replaceAll("\f", "\\f"); text = text.replaceAll("\n", "\\n"); + text = text.replaceAll("\r", "\\r"); + text = text.replaceAll("\t", "\\t"); + text = text.replaceAll(backslashPlaceholder, "\\\\"); + text = text.replaceAll("'", "\\'"); + text = text.replaceAll("\"", "\\\""); return token + text + token; } diff --git a/src/rustTranspiler.ts b/src/rustTranspiler.ts index fc31ca2..715d5cc 100644 --- a/src/rustTranspiler.ts +++ b/src/rustTranspiler.ts @@ -161,11 +161,16 @@ export class RustTranspiler extends BaseTranspiler { if (text in this.StringLiteralReplacements) { return this.StringLiteralReplacements[text]; } - text = text.replaceAll('\\', '\\\\'); + // Preserve real backslashes + const backslashPlaceholder = "\x00"; + text = text.replaceAll("\\", backslashPlaceholder); + text = text.replaceAll("\b", "\\b"); + text = text.replaceAll("\f", "\\f"); + text = text.replaceAll("\n", "\\n"); + text = text.replaceAll("\r", "\\r"); + text = text.replaceAll("\t", "\\t"); + text = text.replaceAll(backslashPlaceholder, "\\\\"); text = text.replaceAll('"', '\\"'); - text = text.replaceAll('\n', '\\n'); - text = text.replaceAll('\r', '\\r'); - text = text.replaceAll('\t', '\\t'); return `Value::Str("${text}".to_string())`; } diff --git a/tests/pythonTranspiler.test.ts b/tests/pythonTranspiler.test.ts index bbcd5e1..37a9aac 100644 --- a/tests/pythonTranspiler.test.ts +++ b/tests/pythonTranspiler.test.ts @@ -812,6 +812,12 @@ describe('python tests', () => { const output = transpiler.transpilePython(ts).content; expect(output).toBe(python); }); + test('string literal with backslash escapes', () => { + const ts = "const string2 = '{\"k\":123.1,\"k2\":\"{\\\\\"k3\\\\\":456}\"}';"; + const python = "string2 = '{\"k\":123.1,\"k2\":\"{\\\\\"k3\\\\\":456}\"}'"; + const output = transpiler.transpilePython(ts).content; + expect(output).toBe(python); + }); test('should convert isArray', () => { const ts = "Array.isArray(x)"; const result = "isinstance(x, list)";