Skip to content

Commit 7a6a54c

Browse files
Leonabcd123Miodec
andauthored
impr(custom text): replace control character improvements (@Leonabcd123) (monkeytypegame#6909)
### Description Made it so all \t are converted to tab characters. ### Closes Fixes monkeytypegame#6906 --------- Co-authored-by: Miodec <[email protected]>
1 parent c2cee8b commit 7a6a54c

File tree

3 files changed

+74
-5
lines changed

3 files changed

+74
-5
lines changed

frontend/__tests__/utils/strings.spec.ts

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,60 @@ describe("string utils", () => {
1010
expect(Strings.splitIntoCharacters("t𐑩e")).toEqual(["t", "𐑩", "e"]);
1111
});
1212
});
13+
describe("replaceControlCharacters", () => {
14+
it.each([
15+
// Basic tab conversions
16+
["\\t", "\t", "single tab"],
17+
["\\t\\t\\t", "\t\t\t", "multiple tabs"],
18+
["hello\\tworld", "hello\tworld", "tab between words"],
19+
["\\tstart", "\tstart", "tab at start"],
20+
["end\\t", "end\t", "tab at end"],
21+
22+
// Basic newline conversions
23+
["\\n", " \n", "single newline with space prefix"],
24+
["hello\\nworld", "hello \nworld", "newline between words with space"],
25+
["\\nstart", " \nstart", "newline at start with space"],
26+
["end\\n", "end \n", "newline at end with space"],
27+
28+
// Complex newline handling (after first two regexes)
29+
["a\\n", "a \n", "single char followed by newline gets space prefix"],
30+
["hello\\n", "hello \n", "word followed by newline gets space prefix"],
31+
32+
// Double-escaped sequences (should become single-escaped)
33+
["\\\\t", "\\t", "double-escaped tab becomes single-escaped"],
34+
[
35+
"\\\\n",
36+
"\\ \n",
37+
"double-escaped newline becomes backslash + space + newline",
38+
],
39+
["\\\\t\\\\n", "\\t\\ \n", "multiple double-escaped sequences"],
40+
41+
// Mixed scenarios
42+
[
43+
"\\t\\n\\\\t",
44+
"\t \n\\t",
45+
"mix of tab, newline, and double-escaped tab",
46+
],
47+
[
48+
"hello\\tworld\\ntest\\\\t",
49+
"hello\tworld \ntest\\t",
50+
"complex mixed scenario",
51+
],
52+
53+
// Edge cases
54+
["", "", "empty string"],
55+
["no escapes", "no escapes", "string with no escape sequences"],
56+
["\\", "\\", "single backslash"],
57+
["\\x", "\\x", "backslash with non-control character"],
58+
59+
// Escaped backslashes that don't precede control chars
60+
["\\\\", "\\\\", "double backslash not followed by control char"],
61+
["\\\\x", "\\\\x", "double backslash followed by non-control char"],
62+
])(
63+
"should convert %s to %s (%s)",
64+
(input: string, expected: string, _description: string) => {
65+
expect(Strings.replaceControlCharacters(input)).toBe(expected);
66+
}
67+
);
68+
});
1369
});

frontend/src/ts/modals/custom-text.ts

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -279,11 +279,7 @@ function cleanUpText(): string[] {
279279
}
280280

281281
if (state.replaceControlCharactersEnabled) {
282-
text = text.replace(/([^\\]|^)\\t/gm, "$1\t");
283-
text = text.replace(/\\n/g, " \n");
284-
text = text.replace(/([^\\]|^)\\n/gm, "$1\n");
285-
text = text.replace(/\\\\t/gm, "\\t");
286-
text = text.replace(/\\\\n/gm, "\\n");
282+
text = Strings.replaceControlCharacters(text);
287283
}
288284

289285
text = text.replace(/ +/gm, " ");

frontend/src/ts/utils/strings.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,3 +167,20 @@ export function splitIntoCharacters(s: string): string[] {
167167

168168
return result;
169169
}
170+
171+
/**
172+
* Replaces escaped control characters with their literal equivalents.
173+
* Converts \t to tab characters, \n to newlines (with a space prefix),
174+
* and handles double-escaped sequences (\\t, \\n) by converting them back to single escaped versions.
175+
* @param textToClear The input string containing escaped control characters.
176+
* @returns A new string with control characters properly converted.
177+
*/
178+
export function replaceControlCharacters(textToClear: string): string {
179+
textToClear = textToClear.replace(/(?<!\\)\\t/g, "\t");
180+
textToClear = textToClear.replace(/\\n/g, " \n");
181+
textToClear = textToClear.replace(/([^\\]|^)\\n/gm, "$1\n");
182+
textToClear = textToClear.replace(/\\\\t/gm, "\\t");
183+
textToClear = textToClear.replace(/\\\\n/gm, "\\n");
184+
185+
return textToClear;
186+
}

0 commit comments

Comments
 (0)