From 408d2a086d795207b1967eace782d5f08159e0c0 Mon Sep 17 00:00:00 2001 From: David Sherret Date: Fri, 1 Mar 2024 13:37:28 -0500 Subject: [PATCH] fix: handle escapes better in .quote() (#46) --- utils/string_utils.test.ts | 24 +++++++++--------------- utils/string_utils.ts | 21 +++++++++------------ 2 files changed, 18 insertions(+), 27 deletions(-) diff --git a/utils/string_utils.test.ts b/utils/string_utils.test.ts index 4e60648..b3a9033 100644 --- a/utils/string_utils.test.ts +++ b/utils/string_utils.test.ts @@ -1,5 +1,5 @@ import { describe, expect, it } from "../_test.deps.ts"; -import { escapeChar, escapeForWithinString, getStringFromStrOrFunc } from "./string_utils.ts"; +import { escapeForWithinString, getStringFromStrOrFunc } from "./string_utils.ts"; describe("escapeForWithinString", () => { function doTest(input: string, expected: string) { @@ -9,27 +9,21 @@ describe("escapeForWithinString", () => { it("should escape the quotes and newline", () => { doTest(`"testing\n this out"`, `\\"testing\\\n this out\\"`); }); -}); -describe("escapeChar", () => { - function doTest(input: string, char: string, expected: string) { - expect(escapeChar(input, char)).to.equal(expected); + function doQuoteTest(input: string, quote: string, expected: string) { + expect(escapeForWithinString(input, quote)).to.equal(expected); } - it("should throw when specifying a char length > 1", () => { - expect(() => escapeChar("", "ab")).to.throw(); - }); - - it("should throw when specifying a char length < 1", () => { - expect(() => escapeChar("", "")).to.throw(); - }); - it("should escape the single quotes when specified", () => { - doTest(`'testing "this" out'`, `'`, `\\'testing "this" out\\'`); + doQuoteTest(`'testing "this" out'`, `'`, `\\'testing "this" out\\'`); }); it("should escape regardless of if the character is already escaped", () => { - doTest(`"testing \\"this\\" out"`, `"`, `\\"testing \\\\"this\\\\" out\\"`); + doQuoteTest(`"testing \\"this\\" out"`, `"`, `\\"testing \\\\\\"this\\\\\\" out\\"`); + }); + + it("should escape unicode escape sequences", () => { + doQuoteTest(`\\u0009`, `"`, `\\\\u0009`); }); }); diff --git a/utils/string_utils.ts b/utils/string_utils.ts index 8fd241c..ba561e8 100644 --- a/utils/string_utils.ts +++ b/utils/string_utils.ts @@ -1,19 +1,16 @@ -const newlineRegex = /(\r?\n)/g; - /** @internal */ export function escapeForWithinString(str: string, quoteKind: string) { - return escapeChar(str, quoteKind).replace(newlineRegex, "\\$1"); -} - -/** @internal */ -export function escapeChar(str: string, char: string) { - if (char.length !== 1) { - throw new Error(`Specified char must be one character long.`); - } - let result = ""; + // todo: reduce appends (don't go char by char) for (let i = 0; i < str.length; i++) { - if (str[i] === char) { + if (str[i] === quoteKind) { + result += "\\"; + } else if (str[i] === "\r" && str[i + 1] === "\n") { + result += "\\"; + i++; // skip the \r + } else if (str[i] === "\n") { + result += "\\"; + } else if (str[i] === "\\") { result += "\\"; } result += str[i];