From 7b4f6fc0d0c135c1f94524c0a007b77d757cc47a Mon Sep 17 00:00:00 2001 From: Talha Shafeeq <51529912+TalhaHunter101@users.noreply.github.com> Date: Fri, 2 Oct 2026 03:55:18 +0500 Subject: [PATCH] fix(compat/truncate): escape string separator in RegExp (#2129) --- src/compat/string/truncate.spec.ts | 11 +++++++++++ src/compat/string/truncate.ts | 3 ++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/compat/string/truncate.spec.ts b/src/compat/string/truncate.spec.ts index e64dafad3..621eb3b7e 100644 --- a/src/compat/string/truncate.spec.ts +++ b/src/compat/string/truncate.spec.ts @@ -121,4 +121,15 @@ describe('truncate', () => { it('should return base string with omission when separator is not found in truncated string', () => { expect(truncate('hello world test', { length: 10, separator: 'xyz' })).toEqual('hello w...'); }); + + it('should support string separators containing RegExp special characters', () => { + expect(truncate('hello world? how are you doing?', { length: 20, separator: '?' })).toBe('hello world...'); + expect(truncate('section [1] details and notes', { length: 20, separator: '[' })).toBe('section ...'); + expect(truncate('part (A) overview notes', { length: 20, separator: '(' })).toBe('part ...'); + expect(truncate('a + b + c + d + e', { length: 12, separator: '+' })).toBe('a + b ...'); + expect(truncate('one*two*three*four', { length: 12, separator: '*' })).toBe('one*two...'); + expect(truncate('hello.world.foo.bar', { length: 15, separator: '.' })).toBe('hello.world...'); + expect(truncate('hello world foo bar', { length: 15, separator: '.' })).toBe('hello world ...'); + expect(truncate('path\\to\\nested\\file', { length: 15, separator: '\\' })).toBe('path\\to...'); + }); }); diff --git a/src/compat/string/truncate.ts b/src/compat/string/truncate.ts index 9ff6ac886..4fe57b977 100644 --- a/src/compat/string/truncate.ts +++ b/src/compat/string/truncate.ts @@ -1,3 +1,4 @@ +import { escapeRegExp } from '../../string/escapeRegExp.ts'; import { regexMultiByte } from '../_internal/regexMultiByte.ts'; import { isObject } from '../predicate/isObject.ts'; @@ -81,7 +82,7 @@ export function truncate(string?: string, options?: TruncateOptions): string { } // Further truncate the string to the last separator using unicode regex - const search = separator instanceof RegExp ? separator.source : separator; + const search = separator instanceof RegExp ? separator.source : escapeRegExp(separator); const flags = 'u' + (separator instanceof RegExp ? separator.flags.replace('u', '') : ''); const withoutSeparator = new RegExp(`(?.*(?:(?!${search}).))(?:${search})`, flags).exec(base);