@tstdl/base 0.90.11 → 0.90.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,18 @@
1
+ export declare class NumberParser {
2
+ private readonly group;
3
+ private readonly decimal;
4
+ private readonly numeral;
5
+ private readonly loosePattern;
6
+ private readonly numeralIndex;
7
+ private readonly numeralReplacer;
8
+ readonly locale: string;
9
+ constructor(locale: string);
10
+ /**
11
+ * Parse a string
12
+ * @param value Value to parse
13
+ * @param loose Try to parse an invalid string by removing unsupported characters. Might produce incorrect results, depending on input
14
+ */
15
+ parse(value: string, loose?: boolean): number;
16
+ }
17
+ export declare const getNumberParser: (locale: string) => NumberParser;
18
+ export declare function parseNumber(locale: string, value: string, loose?: boolean): number;
@@ -0,0 +1,41 @@
1
+ import { createArray } from '../utils/array/array.js';
2
+ import { memoizeClassSingle } from '../utils/function/memoize.js';
3
+ export class NumberParser {
4
+ group;
5
+ decimal;
6
+ numeral;
7
+ loosePattern;
8
+ numeralIndex;
9
+ numeralReplacer;
10
+ locale;
11
+ constructor(locale) {
12
+ this.locale = locale;
13
+ const format = new Intl.NumberFormat(locale);
14
+ const parts = format.formatToParts(12345.6);
15
+ const numerals = createArray(10, (i) => format.format(i));
16
+ const numeralPattern = `[${numerals.join('')}]`;
17
+ this.numeralIndex = new Map(numerals.map((d, i) => [d, i.toString()]));
18
+ this.group = parts.find((part) => part.type == 'group').value;
19
+ this.decimal = parts.find((part) => part.type == 'decimal').value;
20
+ this.numeral = new RegExp(numeralPattern, 'ug');
21
+ this.loosePattern = new RegExp(`[^${numerals.join()}${this.group}${this.decimal}]`, 'ug');
22
+ this.numeralReplacer = (numeral) => this.numeralIndex.get(numeral);
23
+ }
24
+ /**
25
+ * Parse a string
26
+ * @param value Value to parse
27
+ * @param loose Try to parse an invalid string by removing unsupported characters. Might produce incorrect results, depending on input
28
+ */
29
+ parse(value, loose = false) {
30
+ const source = loose ? value.replaceAll(this.loosePattern, '') : value;
31
+ const normalized = source.trim()
32
+ .replaceAll(this.group, '')
33
+ .replaceAll(this.decimal, '.')
34
+ .replaceAll(this.numeral, this.numeralReplacer);
35
+ return Number(normalized);
36
+ }
37
+ }
38
+ export const getNumberParser = memoizeClassSingle(NumberParser);
39
+ export function parseNumber(locale, value, loose) {
40
+ return getNumberParser(locale).parse(value, loose);
41
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tstdl/base",
3
- "version": "0.90.11",
3
+ "version": "0.90.12",
4
4
  "author": "Patrick Hein",
5
5
  "publishConfig": {
6
6
  "access": "public"
package/types.d.ts CHANGED
@@ -60,8 +60,8 @@ export type EnumerationEntries<T extends EnumerationObject = EnumerationObject>
60
60
  export type Type<T = any, Arguments extends any[] = any> = Constructor<T, Arguments> & {
61
61
  prototype: T;
62
62
  };
63
- export type Constructor<T = any, Arguments extends any[] = any> = new (...args: Arguments) => T;
64
- export type AbstractType<T = any, Arguments extends any[] = any> = AbstractConstructor<T, Arguments> & {
63
+ export type Constructor<T = any, Arguments extends any[] = any[]> = new (...args: Arguments) => T;
64
+ export type AbstractType<T = any, Arguments extends any[] = any[]> = AbstractConstructor<T, Arguments> & {
65
65
  prototype: T;
66
66
  };
67
67
  export type AbstractConstructor<T = any, Arguments extends any[] = any> = abstract new (...args: Arguments) => T;
@@ -1,3 +1,4 @@
1
+ import type { Constructor } from '../../types.js';
1
2
  export type MemoizeOptions = {
2
3
  /** Use WeakMap instead of Map for caching. Can be used with object parameters only */
3
4
  weak?: boolean;
@@ -13,3 +14,5 @@ export type MemoizeOptions = {
13
14
  * @returns memoized function
14
15
  */
15
16
  export declare function memoizeSingle<Fn extends (parameter: any) => any>(fn: Fn, options?: MemoizeOptions): Fn;
17
+ export declare function memoizeClass<T extends Constructor>(type: T, options?: MemoizeOptions): (...parameters: ConstructorParameters<T>) => InstanceType<T>;
18
+ export declare function memoizeClassSingle<T extends Constructor<any, [any]>>(type: T, options?: MemoizeOptions): (...parameters: ConstructorParameters<T>) => InstanceType<T>;
@@ -37,6 +37,12 @@ export function memoizeSingle(fn, options = {}) {
37
37
  }
38
38
  }[name];
39
39
  }
40
+ export function memoizeClass(type, options = {}) {
41
+ return memoize((...parameters) => new type(...parameters), options);
42
+ }
43
+ export function memoizeClassSingle(type, options = {}) {
44
+ return memoizeSingle((parameter) => new type(parameter), options);
45
+ }
40
46
  function getMemoizedName(fn) {
41
47
  return `memoized${fn.name[0]?.toUpperCase() ?? ''}${fn.name.slice(1)}`;
42
48
  }