From ff155783ce72e9d7bfadc40011a4274fa875c5d7 Mon Sep 17 00:00:00 2001 From: Nikita Barsukov Date: Tue, 9 Jan 2024 13:32:20 +0300 Subject: [PATCH] fix(kit): `maskitoParseNumber` cannot parse prefix/postfix with points (#874) --- .../lib/masks/number/utils/parse-number.ts | 7 +++- .../number/utils/tests/parse-number.spec.ts | 32 +++++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/projects/kit/src/lib/masks/number/utils/parse-number.ts b/projects/kit/src/lib/masks/number/utils/parse-number.ts index 989f734f3..c6a4feb08 100644 --- a/projects/kit/src/lib/masks/number/utils/parse-number.ts +++ b/projects/kit/src/lib/masks/number/utils/parse-number.ts @@ -8,8 +8,13 @@ export function maskitoParseNumber( const hasNegativeSign = !!maskedNumber.match( new RegExp(`^\\D*[${CHAR_MINUS}\\${CHAR_HYPHEN}${CHAR_EN_DASH}${CHAR_EM_DASH}]`), ); + const escapedDecimalSeparator = escapeRegExp(decimalSeparator); + const unmaskedNumber = maskedNumber - .replace(new RegExp(`[^\\d${escapeRegExp(decimalSeparator)}]`, 'g'), '') + // drop all decimal separators not followed by a digit + .replace(new RegExp(`${escapedDecimalSeparator}(?!\\d)`, 'g'), '') + // drop all non-digit characters except decimal separator + .replace(new RegExp(`[^\\d${escapedDecimalSeparator}]`, 'g'), '') .replace(decimalSeparator, '.'); return unmaskedNumber diff --git a/projects/kit/src/lib/masks/number/utils/tests/parse-number.spec.ts b/projects/kit/src/lib/masks/number/utils/tests/parse-number.spec.ts index 1cc4f3ecb..9413efc50 100644 --- a/projects/kit/src/lib/masks/number/utils/tests/parse-number.spec.ts +++ b/projects/kit/src/lib/masks/number/utils/tests/parse-number.spec.ts @@ -91,6 +91,38 @@ describe('maskitoParseNumber', () => { expect(maskitoParseNumber('>-42')).toBe(-42); expect(maskitoParseNumber('> -42')).toBe(-42); }); + + describe('prefix/postfix includes point and space', () => { + it('parses INTEGER number with postfix " lbs."', () => { + expect(maskitoParseNumber('42 lbs.')).toBe(42); + expect(maskitoParseNumber('1 000 lbs.')).toBe(1000); + expect(maskitoParseNumber('1 000 lbs.')).toBe(1000); + }); + + it('parses DECIMAL number with postfix " lbs."', () => { + expect(maskitoParseNumber('0.42 lbs.')).toBe(0.42); + expect(maskitoParseNumber('.42 lbs.')).toBe(0.42); + expect(maskitoParseNumber('1 000.42 lbs.')).toBe(1000.42); + expect(maskitoParseNumber('1 000. lbs.')).toBe(1000); + }); + + it('parses INTEGER number with prefix "lbs. "', () => { + expect(maskitoParseNumber('lbs. 42')).toBe(42); + expect(maskitoParseNumber('lbs. 1 000')).toBe(1000); + expect(maskitoParseNumber('lbs. 1 000')).toBe(1000); + }); + + it('parses DECIMAL number with prefix "lbs. "', () => { + expect(maskitoParseNumber('lbs. 0.42')).toBe(0.42); + expect(maskitoParseNumber('lbs. .42')).toBe(0.42); + expect(maskitoParseNumber('lbs. 1 000.42')).toBe(1000.42); + expect(maskitoParseNumber('lbs. 1 000.42')).toBe(1000.42); + + const zeroWidthSpace = '\u200B'; + + expect(maskitoParseNumber(`lbs.${zeroWidthSpace}1 000.42`)).toBe(1000.42); + }); + }); }); describe('NaN', () => {