From d40474d47e0b5ded963df2c4e76c6911de63dbca Mon Sep 17 00:00:00 2001 From: Pieter Vander Vennet Date: Sat, 27 Apr 2024 01:47:51 +0200 Subject: [PATCH] Themes: add currency type which does some reformatting --- src/UI/InputElement/Validators.ts | 3 + .../Validators/CurrencyValidator.ts | 73 +++++++++++++++++++ 2 files changed, 76 insertions(+) create mode 100644 src/UI/InputElement/Validators/CurrencyValidator.ts diff --git a/src/UI/InputElement/Validators.ts b/src/UI/InputElement/Validators.ts index 555443b05..fd3e87075 100644 --- a/src/UI/InputElement/Validators.ts +++ b/src/UI/InputElement/Validators.ts @@ -28,6 +28,7 @@ import TagValidator from "./Validators/TagValidator" import IdValidator from "./Validators/IdValidator" import SlopeValidator from "./Validators/SlopeValidator" import VeloparkValidator from "./Validators/VeloparkValidator" +import CurrencyValidator from "./Validators/CurrencyValidator" export type ValidatorType = (typeof Validators.availableTypes)[number] @@ -60,6 +61,7 @@ export default class Validators { "id", "slope", "velopark", + "currency" ] as const public static readonly AllValidators: ReadonlyArray = [ @@ -89,6 +91,7 @@ export default class Validators { new IdValidator(), new SlopeValidator(), new VeloparkValidator(), + new CurrencyValidator() ] private static _byType = Validators._byTypeConstructor() diff --git a/src/UI/InputElement/Validators/CurrencyValidator.ts b/src/UI/InputElement/Validators/CurrencyValidator.ts new file mode 100644 index 000000000..9a82205ea --- /dev/null +++ b/src/UI/InputElement/Validators/CurrencyValidator.ts @@ -0,0 +1,73 @@ +import { Validator } from "../Validator" +import { Utils } from "../../../Utils" + +export default class CurrencyValidator extends Validator { + private readonly segmenter: Intl.Segmenter + private readonly symbolToCurrencyMapping: Map + private readonly supportedCurrencies: Set + + constructor() { + super("currency", "Validates monetary amounts") + if (Intl.Segmenter === undefined || Utils.runningFromConsole) { + // Librewolf doesn't support this + return + } + let locale = "en-US" + if(!Utils.runningFromConsole){ + locale??= navigator.language + } + this.segmenter = new Intl.Segmenter(locale, { + granularity: "word" + }) + + const mapping: Map = new Map() + const supportedCurrencies: Set = new Set(Intl.supportedValuesOf("currency")) + this.supportedCurrencies = supportedCurrencies + for (const currency of supportedCurrencies) { + const symbol = (0).toLocaleString( + locale, + { + style: "currency", + currency: currency, + minimumFractionDigits: 0, + maximumFractionDigits: 0 + } + ).replace(/\d/g, "").trim() + + mapping.set(symbol.toLowerCase(), currency) + } + this.symbolToCurrencyMapping = mapping + } + + reformat(s: string): string { + if (!this.segmenter) { + return s + } + + const parts = Array.from(this.segmenter.segment(s)).map(i => i.segment).filter(part => part.trim().length > 0) + if(parts.length !== 2){ + return s + } + const mapping = this.symbolToCurrencyMapping + let currency: string = undefined + let amount = undefined + for (const part of parts) { + const lc = part.toLowerCase() + if (this.supportedCurrencies.has(part.toUpperCase())) { + currency = part.toUpperCase() + continue + } + + if (mapping.has(lc)) { + currency = mapping.get(lc) + continue + } + amount = part + } + if(amount === undefined || currency === undefined){ + return s + } + + return amount+" "+currency + } +}