From ce7411d37b480ca62b8e12274304f9bfa7734e79 Mon Sep 17 00:00:00 2001 From: Dominic Baur Date: Tue, 26 Aug 2025 10:25:15 +0200 Subject: [PATCH 1/9] Add string utility functions: splitLine --- src/lib/string.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/lib/string.ts b/src/lib/string.ts index c0666b3..40f03d7 100644 --- a/src/lib/string.ts +++ b/src/lib/string.ts @@ -64,3 +64,12 @@ export function truncate(value: string | undefined, maxLength: number, suffix = return `${value.slice(0, maxLength)}${suffix}`; } + +/** + * Splits the string at line breaks + * @param str the string to split + * @returns the individual lines as an array + */ +export function splitLine(str: string): string[] { + return str.split(/\r\n|\r|\n/); +} From 19887e52caaf9fe18d0b1196d019348f3d0641ee Mon Sep 17 00:00:00 2001 From: Dominic Baur Date: Tue, 26 Aug 2025 10:27:03 +0200 Subject: [PATCH 2/9] Add tests for string utility functions: splitLine --- src/lib/string.spec.ts | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/lib/string.spec.ts b/src/lib/string.spec.ts index 94fc71e..9461b74 100644 --- a/src/lib/string.spec.ts +++ b/src/lib/string.spec.ts @@ -1,4 +1,4 @@ -import { isNullOrEmpty, isNullOrWhitespace, capitalize, uncapitalize, truncate } from "./string"; +import { isNullOrEmpty, isNullOrWhitespace, capitalize, uncapitalize, truncate, splitLine } from "./string"; describe("string tests", () => { test.each([ @@ -120,4 +120,21 @@ describe("string tests", () => { ])("truncate without suffix parameter", (value, maxLength, expected) => { expect(truncate(value, maxLength)).toBe(expected); }); + + test.each([["hello world", ["hello world"]]])("splitLine with single line", (str, expected) => { + expect(splitLine(str)).toStrictEqual(expected); + }); + + test.each([ + ["hello world", ["hello world"]], + ["hello world\nhello world\nhello world", ["hello world", "hello world", "hello world"]], + ["hello world\rhello world\rhello world", ["hello world", "hello world", "hello world"]], + ["hello world\r\nhello world\r\nhello world", ["hello world", "hello world", "hello world"]], + ])("splitLine", (str, expected) => { + expect(splitLine(str)).toStrictEqual(expected); + }); + + test.each([["", [""]]])("splitLine with empty strings", (str, expected) => { + expect(splitLine(str)).toStrictEqual(expected); + }); }); From 745b0488706dc289a610ff5872531c8d16468fca Mon Sep 17 00:00:00 2001 From: Dominic Baur Date: Tue, 26 Aug 2025 14:59:12 +0200 Subject: [PATCH 3/9] Fix Changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c15e1c6..01eebb8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Added + +- `splitLine` string utility function + ## [2.0.0] - 2025-07-29 ### Added From 2d9524ba1b2e3ba2cca51d756e325857e924c397 Mon Sep 17 00:00:00 2001 From: Dominic Baur Date: Tue, 26 Aug 2025 16:56:06 +0200 Subject: [PATCH 4/9] Add check for parameters with a value of null or undefined --- src/lib/string.spec.ts | 14 +++++++++++++- src/lib/string.ts | 10 +++++++++- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/lib/string.spec.ts b/src/lib/string.spec.ts index 9461b74..e152134 100644 --- a/src/lib/string.spec.ts +++ b/src/lib/string.spec.ts @@ -134,7 +134,19 @@ describe("string tests", () => { expect(splitLine(str)).toStrictEqual(expected); }); - test.each([["", [""]]])("splitLine with empty strings", (str, expected) => { + test.each([ + ["", []], + [null as unknown as string, []], + [undefined as unknown as string, []], + ])("splitLine with empty strings", (str, expected) => { expect(splitLine(str)).toStrictEqual(expected); }); + + test.each([ + [null as unknown as string, []], + [undefined as unknown as string, []], + ["hello world\n", ["hello world"]], + ])("splitLine with the option to remove empty entries", (str, expected) => { + expect(splitLine(str, true)).toEqual(expected); + }); }); diff --git a/src/lib/string.ts b/src/lib/string.ts index 40f03d7..20dd633 100644 --- a/src/lib/string.ts +++ b/src/lib/string.ts @@ -68,8 +68,16 @@ export function truncate(value: string | undefined, maxLength: number, suffix = /** * Splits the string at line breaks * @param str the string to split + * @param removeEmptyEntries the option to remove empty entries * @returns the individual lines as an array */ -export function splitLine(str: string): string[] { +export function splitLine(str: string, removeEmptyEntries: boolean = false): string[] { + if (isNullOrEmpty(str)) { + return []; + } + + if (removeEmptyEntries) { + return str.split(/\r\n|\r|\n/).filter((line) => !isNullOrWhitespace(line)); + } return str.split(/\r\n|\r|\n/); } From 58fd387b728d7ace51bd054bd58a698011db9c71 Mon Sep 17 00:00:00 2001 From: Dominic Baur Date: Wed, 27 Aug 2025 14:52:13 +0200 Subject: [PATCH 5/9] Changed return statement --- src/lib/string.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/lib/string.ts b/src/lib/string.ts index 20dd633..980d8ca 100644 --- a/src/lib/string.ts +++ b/src/lib/string.ts @@ -76,8 +76,6 @@ export function splitLine(str: string, removeEmptyEntries: boolean = false): str return []; } - if (removeEmptyEntries) { - return str.split(/\r\n|\r|\n/).filter((line) => !isNullOrWhitespace(line)); - } - return str.split(/\r\n|\r|\n/); + const splitted = str.split(/\r\n|\r|\n/); + return removeEmptyEntries ? splitted.filter((line) => !isNullOrWhitespace(line)) : splitted; } From 207c774e8530579e92e8aeb2daff8e36fddf6fbb Mon Sep 17 00:00:00 2001 From: Dominic Baur Date: Thu, 4 Sep 2025 10:35:04 +0200 Subject: [PATCH 6/9] Improved the tests --- src/lib/string.spec.ts | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/lib/string.spec.ts b/src/lib/string.spec.ts index e85dd59..ca9bf8b 100644 --- a/src/lib/string.spec.ts +++ b/src/lib/string.spec.ts @@ -130,8 +130,11 @@ describe("string tests", () => { expect(truncate(value, maxLength)).toBe(expected); }); - test.each([["hello world", ["hello world"]]])("splitLine with single line", (str, expected) => { - expect(splitLine(str)).toStrictEqual(expected); + test.each([ + ["", []], + ["hello world\n", ["hello world", ""]], + ])("splitLine without the parameter to remove the empty entries", (str, expected) => { + expect(splitLine(str)).toEqual(expected); }); test.each([ @@ -143,8 +146,8 @@ describe("string tests", () => { ["hello world\nhello world\nhello world", ["hello world", "hello world", "hello world"]], ["hello world\rhello world\rhello world", ["hello world", "hello world", "hello world"]], ["hello world\r\nhello world\r\nhello world", ["hello world", "hello world", "hello world"]], - ])("splitLine", (str, expected) => { - expect(splitLine(str)).toStrictEqual(expected); + ])("splitLine with the parameter to remove empty entries", (str, expected) => { + expect(splitLine(str, true)).toEqual(expected); }); test.each([ From fc0e2b3210ba402d96816ec0a3bffc33c7399205 Mon Sep 17 00:00:00 2001 From: Dominic Baur Date: Thu, 4 Sep 2025 11:11:25 +0200 Subject: [PATCH 7/9] Improved tests --- src/lib/string.spec.ts | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/lib/string.spec.ts b/src/lib/string.spec.ts index ca9bf8b..e8971d1 100644 --- a/src/lib/string.spec.ts +++ b/src/lib/string.spec.ts @@ -132,7 +132,11 @@ describe("string tests", () => { test.each([ ["", []], + ["hello world", ["hello world"]], ["hello world\n", ["hello world", ""]], + ["hello world\n\n", ["hello world", "", ""]], + ["hello world\r\r", ["hello world", "", ""]], + ["hello world\r\n\r\n", ["hello world", "", ""]], ])("splitLine without the parameter to remove the empty entries", (str, expected) => { expect(splitLine(str)).toEqual(expected); }); @@ -143,9 +147,14 @@ describe("string tests", () => { [undefined as unknown as string, []], ["hello world", ["hello world"]], ["hello world\n", ["hello world"]], - ["hello world\nhello world\nhello world", ["hello world", "hello world", "hello world"]], - ["hello world\rhello world\rhello world", ["hello world", "hello world", "hello world"]], - ["hello world\r\nhello world\r\nhello world", ["hello world", "hello world", "hello world"]], + ["hello world\n\n", ["hello world"]], + ["hello world\r\r", ["hello world"]], + ["hello world\r\n\r\n", ["hello world"]], + ["hello world 1\nhello world 2\nhello world 3", ["hello world 1", "hello world 2", "hello world 3"]], + ["hello world 1\nhello world 2\rhello world 3", ["hello world 1", "hello world 2", "hello world 3"]], + ["hello world 1\rhello world 2\rhello world 3", ["hello world 1", "hello world 2", "hello world 3"]], + ["hello world 1\r\nhello world 2\r\nhello world 3", ["hello world 1", "hello world 2", "hello world 3"]], + ["hello world 1\r\nhello world 2\nhello world 3\rhello world 4", ["hello world 1", "hello world 2", "hello world 3", "hello world 4"]], ])("splitLine with the parameter to remove empty entries", (str, expected) => { expect(splitLine(str, true)).toEqual(expected); }); From 184c78f8477faf6bf85af559053169781bf30e93 Mon Sep 17 00:00:00 2001 From: Dominic Baur Date: Mon, 8 Sep 2025 16:13:55 +0200 Subject: [PATCH 8/9] Changed name from splitLine to splitLines --- CHANGELOG.md | 2 +- src/lib/string.spec.ts | 6 +++--- src/lib/string.ts | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a4dac89..3703841 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added -- `splitLine` string utility function +- `splitLines` string utility function ### Changed diff --git a/src/lib/string.spec.ts b/src/lib/string.spec.ts index f522aa9..d4801fe 100644 --- a/src/lib/string.spec.ts +++ b/src/lib/string.spec.ts @@ -1,4 +1,4 @@ -import { isNullOrEmpty, isNullOrWhitespace, capitalize, uncapitalize, truncate, splitLine } from "./string"; +import { isNullOrEmpty, isNullOrWhitespace, capitalize, uncapitalize, truncate, splitLines } from "./string"; describe("string tests", () => { test.each([ @@ -129,7 +129,7 @@ describe("string tests", () => { ["hello world\r\r", ["hello world", "", ""]], ["hello world\r\n\r\n", ["hello world", "", ""]], ])("splitLine without the parameter to remove the empty entries", (str, expected) => { - expect(splitLine(str)).toEqual(expected); + expect(splitLines(str)).toEqual(expected); }); test.each([ @@ -147,6 +147,6 @@ describe("string tests", () => { ["hello world 1\r\nhello world 2\r\nhello world 3", ["hello world 1", "hello world 2", "hello world 3"]], ["hello world 1\r\nhello world 2\nhello world 3\rhello world 4", ["hello world 1", "hello world 2", "hello world 3", "hello world 4"]], ])("splitLine with the parameter to remove empty entries", (str, expected) => { - expect(splitLine(str, true)).toEqual(expected); + expect(splitLines(str, true)).toEqual(expected); }); }); diff --git a/src/lib/string.ts b/src/lib/string.ts index 980d8ca..cb1d324 100644 --- a/src/lib/string.ts +++ b/src/lib/string.ts @@ -71,7 +71,7 @@ export function truncate(value: string | undefined, maxLength: number, suffix = * @param removeEmptyEntries the option to remove empty entries * @returns the individual lines as an array */ -export function splitLine(str: string, removeEmptyEntries: boolean = false): string[] { +export function splitLines(str: string, removeEmptyEntries: boolean = false): string[] { if (isNullOrEmpty(str)) { return []; } From 60438e579729044e23cd5093a0a6680899739994 Mon Sep 17 00:00:00 2001 From: Dominic Baur Date: Tue, 9 Sep 2025 09:56:56 +0200 Subject: [PATCH 9/9] Added trimEntries parameter --- src/lib/string.spec.ts | 48 ++++++++++++++++++++++++------------------ src/lib/string.ts | 16 +++++++++++--- 2 files changed, 41 insertions(+), 23 deletions(-) diff --git a/src/lib/string.spec.ts b/src/lib/string.spec.ts index d4801fe..f9bb4ce 100644 --- a/src/lib/string.spec.ts +++ b/src/lib/string.spec.ts @@ -122,31 +122,39 @@ describe("string tests", () => { }); test.each([ - ["", []], - ["hello world", ["hello world"]], - ["hello world\n", ["hello world", ""]], - ["hello world\n\n", ["hello world", "", ""]], - ["hello world\r\r", ["hello world", "", ""]], - ["hello world\r\n\r\n", ["hello world", "", ""]], - ])("splitLine without the parameter to remove the empty entries", (str, expected) => { - expect(splitLines(str)).toEqual(expected); + ["", false, false, []], + [null as unknown as string, false, false, []], + [undefined as unknown as string, false, false, []], + [" aaaa \n\nbbbb \n \ncccc", false, false, [" aaaa ", "", "bbbb ", " ", "cccc"]], + [" aaaa \r\rbbbb \r \rcccc", false, false, [" aaaa ", "", "bbbb ", " ", "cccc"]], + [" aaaa \r\rbbbb \n \r\ncccc", false, false, [" aaaa ", "", "bbbb ", " ", "cccc"]], + [" aaaa \r\n\r\nbbbb \r\n \r\ncccc", false, false, [" aaaa ", "", "bbbb ", " ", "cccc"]], + + [" aaaa \n\nbbbb \n \ncccc", true, false, [" aaaa ", "bbbb ", " ", "cccc"]], + [" aaaa \r\rbbbb \r \rcccc", true, false, [" aaaa ", "bbbb ", " ", "cccc"]], + [" aaaa \r\rbbbb \n \r\ncccc", true, false, [" aaaa ", "bbbb ", " ", "cccc"]], + [" aaaa \r\n\r\nbbbb \r\n \r\ncccc", true, false, [" aaaa ", "bbbb ", " ", "cccc"]], + + [" aaaa \n\nbbbb \n \ncccc", false, true, ["aaaa", "", "bbbb", "", "cccc"]], + [" aaaa \r\rbbbb \r \rcccc", false, true, ["aaaa", "", "bbbb", "", "cccc"]], + [" aaaa \r\rbbbb \n \r\ncccc", false, true, ["aaaa", "", "bbbb", "", "cccc"]], + [" aaaa \r\n\r\nbbbb \r\n \r\ncccc", false, true, ["aaaa", "", "bbbb", "", "cccc"]], + + [" aaaa \n\nbbbb \n \ncccc", true, true, ["aaaa", "bbbb", "cccc"]], + [" aaaa \r\rbbbb \r \rcccc", true, true, ["aaaa", "bbbb", "cccc"]], + [" aaaa \r\rbbbb \n \r\ncccc", true, true, ["aaaa", "bbbb", "cccc"]], + ])("splitLines with parameter removeEmptyEntries and trimEntries", (str, removeEmptyEntries, trimEntries, expected) => { + expect(splitLines(str, removeEmptyEntries, trimEntries)).toEqual(expected); }); test.each([ ["", []], [null as unknown as string, []], [undefined as unknown as string, []], - ["hello world", ["hello world"]], - ["hello world\n", ["hello world"]], - ["hello world\n\n", ["hello world"]], - ["hello world\r\r", ["hello world"]], - ["hello world\r\n\r\n", ["hello world"]], - ["hello world 1\nhello world 2\nhello world 3", ["hello world 1", "hello world 2", "hello world 3"]], - ["hello world 1\nhello world 2\rhello world 3", ["hello world 1", "hello world 2", "hello world 3"]], - ["hello world 1\rhello world 2\rhello world 3", ["hello world 1", "hello world 2", "hello world 3"]], - ["hello world 1\r\nhello world 2\r\nhello world 3", ["hello world 1", "hello world 2", "hello world 3"]], - ["hello world 1\r\nhello world 2\nhello world 3\rhello world 4", ["hello world 1", "hello world 2", "hello world 3", "hello world 4"]], - ])("splitLine with the parameter to remove empty entries", (str, expected) => { - expect(splitLines(str, true)).toEqual(expected); + [" aaaa \n\nbbbb \n \ncccc", [" aaaa ", "", "bbbb ", " ", "cccc"]], + [" aaaa \r\rbbbb \r \rcccc", [" aaaa ", "", "bbbb ", " ", "cccc"]], + [" aaaa \r\n\nbbbb \r\n \r\ncccc", [" aaaa ", "", "bbbb ", " ", "cccc"]], + ])("splitLines with just the string as a parameter", (str, expected) => { + expect(splitLines(str)).toEqual(expected); }); }); diff --git a/src/lib/string.ts b/src/lib/string.ts index cb1d324..3b9e07e 100644 --- a/src/lib/string.ts +++ b/src/lib/string.ts @@ -69,13 +69,23 @@ export function truncate(value: string | undefined, maxLength: number, suffix = * Splits the string at line breaks * @param str the string to split * @param removeEmptyEntries the option to remove empty entries + * @param trimEntries the option to trim the entries * @returns the individual lines as an array */ -export function splitLines(str: string, removeEmptyEntries: boolean = false): string[] { +export function splitLines(str: string, removeEmptyEntries: boolean = false, trimEntries: boolean = false): string[] { if (isNullOrEmpty(str)) { return []; } - const splitted = str.split(/\r\n|\r|\n/); - return removeEmptyEntries ? splitted.filter((line) => !isNullOrWhitespace(line)) : splitted; + let splitted = str.split(/\r\n|\r|\n/); + + if (trimEntries) { + splitted = splitted.map((x) => x.trim()); + } + + if (removeEmptyEntries) { + splitted = splitted.filter((line) => line.length > 0); + } + + return splitted; }