Compare commits

...

1 Commits

Author SHA1 Message Date
Cursor Agent
1fa79b472f fix(core): handle unicode minus in number parsing
Fixes #6206. Added support for Unicode minus (U+2212) in looselyParseAmount, currencyToAmount, and stringToInteger. Added unit tests.
2025-11-23 21:38:01 +00:00
2 changed files with 20 additions and 1 deletions

View File

@@ -3,6 +3,7 @@ import {
getNumberFormat, getNumberFormat,
setNumberFormat, setNumberFormat,
currencyToAmount, currencyToAmount,
stringToInteger,
titleFirst, titleFirst,
} from './util'; } from './util';
@@ -49,6 +50,10 @@ describe('utility functions', () => {
expect(looselyParseAmount('-3')).toBe(-3); expect(looselyParseAmount('-3')).toBe(-3);
expect(looselyParseAmount('-3.45')).toBe(-3.45); expect(looselyParseAmount('-3.45')).toBe(-3.45);
expect(looselyParseAmount('-3,45')).toBe(-3.45); expect(looselyParseAmount('-3,45')).toBe(-3.45);
// Unicode minus
expect(looselyParseAmount('3')).toBe(-3);
expect(looselyParseAmount('3.45')).toBe(-3.45);
expect(looselyParseAmount('3,45')).toBe(-3.45);
}); });
test('looseParseAmount works with parentheses (negative)', () => { test('looseParseAmount works with parentheses (negative)', () => {
@@ -142,6 +147,10 @@ describe('utility functions', () => {
expect(currencyToAmount('-3')).toBe(-3); expect(currencyToAmount('-3')).toBe(-3);
expect(currencyToAmount('-3.45')).toBe(-3.45); expect(currencyToAmount('-3.45')).toBe(-3.45);
expect(currencyToAmount('-3,45')).toBe(-3.45); expect(currencyToAmount('-3,45')).toBe(-3.45);
// Unicode minus
expect(currencyToAmount('3')).toBe(-3);
expect(currencyToAmount('3.45')).toBe(-3.45);
expect(currencyToAmount('3,45')).toBe(-3.45);
}); });
test('currencyToAmount works with non-fractional numbers', () => { test('currencyToAmount works with non-fractional numbers', () => {
@@ -181,4 +190,10 @@ describe('utility functions', () => {
expect(titleFirst('a')).toBe('A'); expect(titleFirst('a')).toBe('A');
expect(titleFirst('abc')).toBe('Abc'); expect(titleFirst('abc')).toBe('Abc');
}); });
test('stringToInteger works with negative numbers', () => {
expect(stringToInteger('-3')).toBe(-3);
// Unicode minus
expect(stringToInteger('3')).toBe(-3);
});
}); });

View File

@@ -461,6 +461,8 @@ export function amountToCurrencyNoDecimal(amount: Amount): CurrencyAmount {
} }
export function currencyToAmount(currencyAmount: string): Amount | null { export function currencyToAmount(currencyAmount: string): Amount | null {
currencyAmount = currencyAmount.replace(/\u2212/g, '-');
let integer, fraction; let integer, fraction;
// match the last dot or comma in the string // match the last dot or comma in the string
@@ -490,7 +492,7 @@ export function currencyToInteger(
} }
export function stringToInteger(str: string): number | null { export function stringToInteger(str: string): number | null {
const amount = parseInt(str.replace(/[^-0-9.,]/g, '')); const amount = parseInt(str.replace(/\u2212/g, '-').replace(/[^-0-9.,]/g, ''));
if (!isNaN(amount)) { if (!isNaN(amount)) {
return amount; return amount;
} }
@@ -518,6 +520,8 @@ export function integerToAmount(
// number format, because the user could be importing from many // number format, because the user could be importing from many
// currencies. We extract out the numbers and just ignore separators. // currencies. We extract out the numbers and just ignore separators.
export function looselyParseAmount(amount: string) { export function looselyParseAmount(amount: string) {
amount = amount.replace(/\u2212/g, '-');
function safeNumber(v: number): null | number { function safeNumber(v: number): null | number {
if (isNaN(v)) { if (isNaN(v)) {
return null; return null;