From 8963548974550463e62f88531b412ca56c6ea899 Mon Sep 17 00:00:00 2001 From: Murat Aslan Date: Wed, 24 Dec 2025 21:54:54 +0300 Subject: [PATCH 1/4] fix(text): only strip single trailing newline in dedent Fixes #6831 The dedent function was using `.trimEnd()` which removes ALL trailing whitespace including multiple newlines. This is inconsistent with npm:string-dedent which only removes a single trailing newline. Changes: - Replace `.trimEnd()` with `.replace(/\n[\t ]*$/, "")` to only strip a single trailing newline (with any preceding whitespace on that line) - Updated documentation to reflect the new behavior Before: ```ts dedent\` a \` // returns 'a' (all trailing newlines stripped) ``` After: ```ts dedent\` a \` // returns 'a\n' (only one trailing newline stripped) ``` --- text/unstable_dedent.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/text/unstable_dedent.ts b/text/unstable_dedent.ts index 7d09673d670b..f5815fe870c5 100644 --- a/text/unstable_dedent.ts +++ b/text/unstable_dedent.ts @@ -16,7 +16,7 @@ const WHITE_SPACE_ONLY_LINE_REGEXP = new RegExp( * Removes indentation from multiline strings. * * - Removes leading newline - * - Removes trailing whitespace, including newlines + * - Removes a single trailing newline (with any preceding whitespace on that line) * - Replaces whitespace-only lines with empty lines * - Finds the minimum indentation among remaining lines and removes that much indentation from all of them * @@ -44,7 +44,7 @@ export function dedent(input: string): string; * Removes indentation from multiline strings. * * - Removes leading newline - * - Removes trailing whitespace, including newlines + * - Removes a single trailing newline (with any preceding whitespace on that line) * - Replaces whitespace-only lines with empty lines * - Finds the minimum indentation among remaining lines and removes that much indentation from all of them * @@ -76,7 +76,7 @@ export function dedent( // Substitute nonempty placeholder so multiline substitutions do not affect indent width. const joinedTemplate = typeof input === "string" ? input : input.join("x"); const ignoreFirstUnindented = !joinedTemplate.startsWith("\n"); - const trimmedTemplate = joinedTemplate.replace(/^\n/, "").trimEnd(); + const trimmedTemplate = joinedTemplate.replace(/^\n/, "").replace(/\n[\t ]*$/, ""); const lines = trimmedTemplate.split("\n"); const linesToCheck = lines.slice( @@ -90,7 +90,7 @@ export function dedent( const inputString = typeof input === "string" ? input : String.raw({ raw: input }, ...values); - const trimmedInput = inputString.replace(/^\n/, "").trimEnd(); + const trimmedInput = inputString.replace(/^\n/, "").replace(/\n[\t ]*$/, ""); // No lines to indent if (!indent) return trimmedInput; From 1e75a94964d993a07fe1912cee649637814f6c2c Mon Sep 17 00:00:00 2001 From: Murat Aslan Date: Thu, 25 Dec 2025 23:54:54 +0300 Subject: [PATCH 2/4] style: format with deno fmt and add test for #6831 --- text/unstable_dedent.ts | 5 ++++- text/unstable_dedent_test.ts | 23 +++++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/text/unstable_dedent.ts b/text/unstable_dedent.ts index f5815fe870c5..5262826c4720 100644 --- a/text/unstable_dedent.ts +++ b/text/unstable_dedent.ts @@ -76,7 +76,10 @@ export function dedent( // Substitute nonempty placeholder so multiline substitutions do not affect indent width. const joinedTemplate = typeof input === "string" ? input : input.join("x"); const ignoreFirstUnindented = !joinedTemplate.startsWith("\n"); - const trimmedTemplate = joinedTemplate.replace(/^\n/, "").replace(/\n[\t ]*$/, ""); + const trimmedTemplate = joinedTemplate.replace(/^\n/, "").replace( + /\n[\t ]*$/, + "", + ); const lines = trimmedTemplate.split("\n"); const linesToCheck = lines.slice( diff --git a/text/unstable_dedent_test.ts b/text/unstable_dedent_test.ts index 54274971137a..54a6e65ef2fe 100644 --- a/text/unstable_dedent_test.ts +++ b/text/unstable_dedent_test.ts @@ -22,6 +22,29 @@ Deno.test("dedent() handles example 2", () => { ); }); +// Test case for issue #6831: only strip single trailing newline, not all +Deno.test("dedent() only strips single trailing newline (issue #6831)", async (t) => { + await t.step( + "preserves content newline when template ends with single newline", + () => { + // Template: `\n a\n ` -> should result in 'a\n' (matching npm:string-dedent) + const result = dedent` + a + `; + assertEquals(result, "a"); + }, + ); + + await t.step("preserves multiple trailing newlines except one", () => { + // When content has intentional trailing newlines, only the template's trailing newline is stripped + const result = dedent` + a + + `; + assertEquals(result, "a\n"); + }); +}); + Deno.test("dedent() handles empty lines", () => { assertEquals( dedent(` From ebd3ed52c46117f9e9ac0689281bc387c6794d9b Mon Sep 17 00:00:00 2001 From: Yoshiya Hinosawa Date: Fri, 26 Dec 2025 10:26:58 +0900 Subject: [PATCH 3/4] simplify test case --- text/unstable_dedent_test.ts | 24 +++++------------------- 1 file changed, 5 insertions(+), 19 deletions(-) diff --git a/text/unstable_dedent_test.ts b/text/unstable_dedent_test.ts index 54a6e65ef2fe..9d2256b27be5 100644 --- a/text/unstable_dedent_test.ts +++ b/text/unstable_dedent_test.ts @@ -22,34 +22,20 @@ Deno.test("dedent() handles example 2", () => { ); }); -// Test case for issue #6831: only strip single trailing newline, not all -Deno.test("dedent() only strips single trailing newline (issue #6831)", async (t) => { - await t.step( - "preserves content newline when template ends with single newline", - () => { - // Template: `\n a\n ` -> should result in 'a\n' (matching npm:string-dedent) - const result = dedent` - a - `; - assertEquals(result, "a"); - }, - ); - - await t.step("preserves multiple trailing newlines except one", () => { - // When content has intentional trailing newlines, only the template's trailing newline is stripped - const result = dedent` +// Test case for issue #6831 +Deno.test("dedent() only strips single trailing newline", () => { + const result = dedent` a `; - assertEquals(result, "a\n"); - }); + assertEquals(result, "a\n"); }); Deno.test("dedent() handles empty lines", () => { assertEquals( dedent(` a - + b \t\t\t c From 415aff7ea4b7cbb2a77a6fe1e314fbeedfcd258d Mon Sep 17 00:00:00 2001 From: Yoshiya Hinosawa Date: Fri, 26 Dec 2025 10:28:32 +0900 Subject: [PATCH 4/4] fix --- text/unstable_dedent_test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/unstable_dedent_test.ts b/text/unstable_dedent_test.ts index 9d2256b27be5..8d8f716be1a7 100644 --- a/text/unstable_dedent_test.ts +++ b/text/unstable_dedent_test.ts @@ -35,7 +35,7 @@ Deno.test("dedent() handles empty lines", () => { assertEquals( dedent(` a - + b \t\t\t c