Skip to content

Commit 256fda4

Browse files
dom-baurneoscieCopilot
authored
Add string utility functions: trimStart, trimEnd, trim (#74)
Add features ltrim, rtrim and trim for issue #29 --------- Co-authored-by: Sandro C. <sc@neolution.ch> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
1 parent 2e765c2 commit 256fda4

File tree

3 files changed

+96
-1
lines changed

3 files changed

+96
-1
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1010
### Added
1111

1212
- `splitLines` string utility function
13+
- `trimStart`, `trimEnd` and `trim` string type utility functions
1314

1415
### Changed
1516

src/lib/string.spec.ts

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { isNullOrEmpty, isNullOrWhitespace, capitalize, uncapitalize, truncate, splitLines } from "./string";
1+
import { isNullOrEmpty, isNullOrWhitespace, capitalize, uncapitalize, truncate, splitLines, trimStart, trimEnd, trim } from "./string";
22

33
describe("string tests", () => {
44
test.each([
@@ -121,6 +121,42 @@ describe("string tests", () => {
121121
expect(truncate(value, maxLength)).toBe(expected);
122122
});
123123

124+
test.each([
125+
[null as unknown as string, " ", null as unknown as string],
126+
[undefined as unknown as string, " ", undefined as unknown as string],
127+
["hello world", "hello world", ""],
128+
["hello world", " ", "hello world"],
129+
[" hello world", " ", "hello world"],
130+
["hello world hello world", "hello world", " hello world"],
131+
["hello worldhello world", "hello world", ""],
132+
])("left trim", (haystack, needle, expected) => {
133+
expect(trimStart(haystack, needle)).toBe(expected);
134+
});
135+
136+
test.each([
137+
[null as unknown as string, " ", null as unknown as string],
138+
[undefined as unknown as string, " ", undefined as unknown as string],
139+
["hello world", "hello world", ""],
140+
["hello world ", " ", "hello world"],
141+
["hello world", " ", "hello world"],
142+
["hello world hello world", "hello world", "hello world "],
143+
["hello worldhello world", "hello world", ""],
144+
])("right trim", (haystack, needle, expected) => {
145+
expect(trimEnd(haystack, needle)).toBe(expected);
146+
});
147+
148+
test.each([
149+
[null as unknown as string, " ", null as unknown as string],
150+
[undefined as unknown as string, " ", undefined as unknown as string],
151+
["hello world", "", "hello world"],
152+
[" hello world ", " ", "hello world"],
153+
["hello world ", " ", "hello world"],
154+
[" hello world", " ", "hello world"],
155+
["hello worldhello world", "hello world", ""],
156+
])("trim", (haystack, needle, expected) => {
157+
expect(trim(haystack, needle)).toBe(expected);
158+
});
159+
124160
test.each([
125161
["", false, false, []],
126162
[null as unknown as string, false, false, []],

src/lib/string.ts

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,64 @@ export function truncate(value: string | undefined, maxLength: number, suffix =
6565
return `${value.slice(0, maxLength)}${suffix}`;
6666
}
6767

68+
/**
69+
* Removes all occurrences of needle from the start of haystack
70+
* @param haystack string to trim
71+
* @param needle the thing to trim
72+
* @returns the string trimmed from the left side
73+
*/
74+
export function trimStart(haystack: string, needle: string): string {
75+
if (isNullOrEmpty(haystack) || isNullOrEmpty(needle)) {
76+
return haystack;
77+
}
78+
79+
let offset = 0;
80+
81+
while (haystack.indexOf(needle, offset) === offset) {
82+
offset = offset + needle.length;
83+
}
84+
return haystack.slice(offset);
85+
}
86+
87+
/**
88+
* Removes all occurrences of needle from the end of haystack
89+
* @param haystack string to trim
90+
* @param needle the thing to trim
91+
* @returns the string trimmed from the right side
92+
*/
93+
export function trimEnd(haystack: string, needle: string): string {
94+
if (isNullOrEmpty(haystack) || isNullOrEmpty(needle)) {
95+
return haystack;
96+
}
97+
98+
let offset = haystack.length,
99+
idx = -1;
100+
101+
while (true) {
102+
idx = haystack.lastIndexOf(needle, offset - 1);
103+
if (idx === -1 || idx + needle.length !== offset) {
104+
break;
105+
}
106+
if (idx === 0) {
107+
return "";
108+
}
109+
offset = idx;
110+
}
111+
112+
return haystack.slice(0, offset);
113+
}
114+
115+
/**
116+
* Removes all occurrences of needle from the start and the end of haystack
117+
* @param haystack string to trim
118+
* @param needle the thing to trim
119+
* @returns the string trimmed from the right and left side
120+
*/
121+
export function trim(haystack: string, needle: string): string {
122+
const trimmed = trimStart(haystack, needle);
123+
return trimEnd(trimmed, needle);
124+
}
125+
68126
/**
69127
* Splits the string at line breaks
70128
* @param str the string to split

0 commit comments

Comments
 (0)