From b90402c340c92dabaec91ed2d397860761df66ff Mon Sep 17 00:00:00 2001 From: Wizmaster Date: Sat, 27 Apr 2024 00:42:04 +0200 Subject: [PATCH] Make comma's and period interchangeable when entering figures - Only allowed for formats not using period or comma as a thousand separator --- packages/loot-core/src/shared/arithmetic.ts | 23 +++-------------- packages/loot-core/src/shared/util.ts | 28 +++++++++++++++------ upcoming-release-notes/2672.md | 6 +++++ 3 files changed, 30 insertions(+), 27 deletions(-) create mode 100644 upcoming-release-notes/2672.md diff --git a/packages/loot-core/src/shared/arithmetic.ts b/packages/loot-core/src/shared/arithmetic.ts index ac8227864a..f69543b1d5 100644 --- a/packages/loot-core/src/shared/arithmetic.ts +++ b/packages/loot-core/src/shared/arithmetic.ts @@ -1,5 +1,5 @@ // @ts-strict-ignore -import { getNumberFormat } from './util'; +import { currencyToAmount } from './util'; function fail(state, msg) { throw new Error( @@ -37,31 +37,16 @@ function parsePrimary(state) { next(state); } - if (/\p{Sc}/u.test(char(state))) { - next(state); - } - - // TODO: The regex should probably respect the number format better, - // and we should do more strict parsing let numberStr = ''; - while (char(state) && char(state).match(/[0-9,.]/)) { - const thousandsSep = getNumberFormat().separator === ',' ? '.' : ','; - - // Don't include the thousands separator - if (char(state) === thousandsSep) { - next(state); - } else { - numberStr += next(state); - } + while (char(state) && char(state).match(/[0-9,. ]|\p{Sc}/u)) { + numberStr += next(state); } if (numberStr === '') { fail(state, 'Unexpected character'); } - const number = parseFloat( - numberStr.replace(getNumberFormat().separator, '.'), - ); + const number = currencyToAmount(numberStr); return isNegative ? -number : number; } diff --git a/packages/loot-core/src/shared/util.ts b/packages/loot-core/src/shared/util.ts index ac2680712d..7429e58ef1 100644 --- a/packages/loot-core/src/shared/util.ts +++ b/packages/loot-core/src/shared/util.ts @@ -255,13 +255,14 @@ export function getNumberFormat({ format?: NumberFormats; hideFraction: boolean; } = numberFormatConfig) { - let locale, regex, separator; + let locale, regex, separator, separatorRegex; switch (format) { case 'space-comma': locale = 'en-SE'; - regex = /[^-0-9,]/g; + regex = /[^-0-9,.]/g; separator = ','; + separatorRegex = /[,.]/g; break; case 'dot-comma': locale = 'de-DE'; @@ -270,8 +271,9 @@ export function getNumberFormat({ break; case 'space-dot': locale = 'dje'; - regex = /[^-0-9.]/g; + regex = /[^-0-9,.]/g; separator = '.'; + separatorRegex = /[,.]/g; break; case 'comma-dot-in': locale = 'en-IN'; @@ -293,6 +295,7 @@ export function getNumberFormat({ maximumFractionDigits: hideFraction ? 0 : 2, }), regex, + separatorRegex, }; } @@ -342,11 +345,20 @@ export function amountToCurrencyNoDecimal(n) { } export function currencyToAmount(str: string) { - const amount = parseFloat( - str - .replace(getNumberFormat().regex, '') - .replace(getNumberFormat().separator, '.'), - ); + let amount; + if (getNumberFormat().separatorRegex) { + amount = parseFloat( + str + .replace(getNumberFormat().regex, '') + .replace(getNumberFormat().separatorRegex, '.'), + ); + } else { + amount = parseFloat( + str + .replace(getNumberFormat().regex, '') + .replace(getNumberFormat().separator, '.'), + ); + } return isNaN(amount) ? null : amount; } diff --git a/upcoming-release-notes/2672.md b/upcoming-release-notes/2672.md new file mode 100644 index 0000000000..6940f9cd92 --- /dev/null +++ b/upcoming-release-notes/2672.md @@ -0,0 +1,6 @@ +--- +category: Enhancements +authors: [Wizmaster] +--- + +Comma and period decimal separator can both be used for number format not using those as thousand separator.