From aa51526739e04b67a07a9a50c60e72660c476968 Mon Sep 17 00:00:00 2001 From: Plastic-time <247457381+Plastic-time@users.noreply.github.com> Date: Tue, 20 Oct 2026 14:33:16 -0400 Subject: [PATCH] fix: treat ignored s as a literal character --- src/lib/isAlpha.js | 2 +- src/lib/isAlphanumeric.js | 2 +- test/literal-ignore.test.js | 27 +++++++++++++++++++++++++++ 3 files changed, 29 insertions(+), 2 deletions(-) create mode 100644 test/literal-ignore.test.js diff --git a/src/lib/isAlpha.js b/src/lib/isAlpha.js index e961e64eb..aeb5d8747 100644 --- a/src/lib/isAlpha.js +++ b/src/lib/isAlpha.js @@ -11,7 +11,7 @@ export default function isAlpha(_str, locale = 'en-US', options = {}) { if (ignore instanceof RegExp) { str = str.replace(ignore, ''); } else if (typeof ignore === 'string') { - str = str.replace(new RegExp(`[${ignore.replace(/[-[\]{}()*+?.,\\^$|#\\s]/g, '\\$&')}]`, 'g'), ''); // escape regex for ignore + str = str.replace(new RegExp(`[${ignore.replace(/[-[\]{}()*+?.,\\^$|#]/g, '\\$&')}]`, 'g'), ''); // escape regex for ignore } else { throw new Error('ignore should be instance of a String or RegExp'); } diff --git a/src/lib/isAlphanumeric.js b/src/lib/isAlphanumeric.js index b259ab908..6382b31a1 100644 --- a/src/lib/isAlphanumeric.js +++ b/src/lib/isAlphanumeric.js @@ -11,7 +11,7 @@ export default function isAlphanumeric(_str, locale = 'en-US', options = {}) { if (ignore instanceof RegExp) { str = str.replace(ignore, ''); } else if (typeof ignore === 'string') { - str = str.replace(new RegExp(`[${ignore.replace(/[-[\]{}()*+?.,\\^$|#\\s]/g, '\\$&')}]`, 'g'), ''); // escape regex for ignore + str = str.replace(new RegExp(`[${ignore.replace(/[-[\]{}()*+?.,\\^$|#]/g, '\\$&')}]`, 'g'), ''); // escape regex for ignore } else { throw new Error('ignore should be instance of a String or RegExp'); } diff --git a/test/literal-ignore.test.js b/test/literal-ignore.test.js new file mode 100644 index 000000000..cffe5268d --- /dev/null +++ b/test/literal-ignore.test.js @@ -0,0 +1,27 @@ +import assert from 'assert'; +import validator from '../index'; + +['isAlpha', 'isAlphanumeric'].forEach((method) => { + describe(`${method} literal ignored characters`, () => { + it('does not treat an ignored s as whitespace', () => { + [' ', '\t', '\n', '\r', '\u00a0'].forEach((space) => { + assert.strictEqual(validator[method](`ab${space}cd`, 'en-US', { ignore: 's' }), false); + }); + }); + + it('removes a literal s outside the selected alphabet', () => { + assert.strictEqual(validator[method]('\u0430s\u0431', 'ru-RU', { ignore: 's' }), true); + }); + + it('continues to escape regular expression metacharacters', () => { + const ignore = '-[]{}()*+?.,\\^$|#'; + assert.strictEqual(validator[method](`ab${ignore}cd`, 'en-US', { ignore }), true); + }); + + it('only ignores whitespace when explicitly requested', () => { + assert.strictEqual(validator[method]('ab cd', 'en-US', { ignore: ' ' }), true); + assert.strictEqual(validator[method]('ab\tcd', 'en-US', { ignore: ' ' }), false); + assert.strictEqual(validator[method]('ab\tcd', 'en-US', { ignore: /\s/g }), true); + }); + }); +});