@edgeandnode/eds-utils 1.0.0
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.
- package/LICENSE +21 -0
- package/README.md +53 -0
- package/dist/bigIntToNumber.d.ts +17 -0
- package/dist/bigIntToNumber.d.ts.map +1 -0
- package/dist/bigIntToNumber.js +25 -0
- package/dist/bigIntToNumber.js.map +1 -0
- package/dist/camelToKebab.d.ts +3 -0
- package/dist/camelToKebab.d.ts.map +1 -0
- package/dist/camelToKebab.js +15 -0
- package/dist/camelToKebab.js.map +1 -0
- package/dist/constants.d.ts +3 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +3 -0
- package/dist/constants.js.map +1 -0
- package/dist/createIdenticon.d.ts +2 -0
- package/dist/createIdenticon.d.ts.map +1 -0
- package/dist/createIdenticon.js +75 -0
- package/dist/createIdenticon.js.map +1 -0
- package/dist/formatAddress.d.ts +14 -0
- package/dist/formatAddress.d.ts.map +1 -0
- package/dist/formatAddress.js +28 -0
- package/dist/formatAddress.js.map +1 -0
- package/dist/formatBigInt.d.ts +23 -0
- package/dist/formatBigInt.d.ts.map +1 -0
- package/dist/formatBigInt.js +38 -0
- package/dist/formatBigInt.js.map +1 -0
- package/dist/getKey.d.ts +14 -0
- package/dist/getKey.d.ts.map +1 -0
- package/dist/getKey.js +36 -0
- package/dist/getKey.js.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +14 -0
- package/dist/index.js.map +1 -0
- package/dist/loremIpsum.d.ts +11 -0
- package/dist/loremIpsum.d.ts.map +1 -0
- package/dist/loremIpsum.js +136 -0
- package/dist/loremIpsum.js.map +1 -0
- package/dist/numberToBigInt.d.ts +18 -0
- package/dist/numberToBigInt.d.ts.map +1 -0
- package/dist/numberToBigInt.js +27 -0
- package/dist/numberToBigInt.js.map +1 -0
- package/dist/parseBigInt.d.ts +25 -0
- package/dist/parseBigInt.d.ts.map +1 -0
- package/dist/parseBigInt.js +35 -0
- package/dist/parseBigInt.js.map +1 -0
- package/dist/parseNumber.d.ts +17 -0
- package/dist/parseNumber.d.ts.map +1 -0
- package/dist/parseNumber.js +18 -0
- package/dist/parseNumber.js.map +1 -0
- package/dist/sliceWrap.d.ts +3 -0
- package/dist/sliceWrap.d.ts.map +1 -0
- package/dist/sliceWrap.js +11 -0
- package/dist/sliceWrap.js.map +1 -0
- package/dist/types.d.ts +6 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +37 -0
- package/src/bigIntToNumber.ts +34 -0
- package/src/camelToKebab.ts +16 -0
- package/src/constants.ts +2 -0
- package/src/createIdenticon.ts +84 -0
- package/src/formatAddress.ts +33 -0
- package/src/formatBigInt.ts +60 -0
- package/src/getKey.ts +37 -0
- package/src/index.ts +13 -0
- package/src/loremIpsum.ts +143 -0
- package/src/numberToBigInt.ts +38 -0
- package/src/parseBigInt.ts +51 -0
- package/src/parseNumber.ts +24 -0
- package/src/sliceWrap.ts +9 -0
- package/src/types.ts +4 -0
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { sliceWrap } from './sliceWrap.js';
|
|
2
|
+
/**
|
|
3
|
+
* Generates lorem ipsum text.
|
|
4
|
+
*
|
|
5
|
+
* @param {number} [count=4] - The number of words, sentences, or paragraphs to generate. Default is
|
|
6
|
+
* `4`
|
|
7
|
+
* @param {'words' | 'sentences' | 'paragraphs'} [units='sentences'] - The units to generate.
|
|
8
|
+
* Default is `'sentences'`
|
|
9
|
+
* @returns {string} The generated text.
|
|
10
|
+
*/
|
|
11
|
+
export function loremIpsum(count = 4, units = 'sentences') {
|
|
12
|
+
switch (units) {
|
|
13
|
+
case 'words':
|
|
14
|
+
return wordsToSentence(sliceWrap(WORDS, 0, count));
|
|
15
|
+
case 'sentences':
|
|
16
|
+
return sliceWrap(SENTENCES, 0, count)
|
|
17
|
+
.map((sentence) => wordsToSentence(sentence.words))
|
|
18
|
+
.join(' ');
|
|
19
|
+
case 'paragraphs':
|
|
20
|
+
return sliceWrap(PARAGRAPHS, 0, count)
|
|
21
|
+
.map((paragraph) => paragraph.sentences.map((sentence) => wordsToSentence(sentence.words)).join(' '))
|
|
22
|
+
.join('\n');
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
function wordsToSentence(words) {
|
|
26
|
+
let sentence = '';
|
|
27
|
+
for (const word of words) {
|
|
28
|
+
if (sentence.length > 0)
|
|
29
|
+
sentence += ' ';
|
|
30
|
+
sentence += word;
|
|
31
|
+
}
|
|
32
|
+
if (sentence.endsWith(',')) {
|
|
33
|
+
sentence = sentence.slice(0, -1);
|
|
34
|
+
}
|
|
35
|
+
if (sentence.length > 0 && !sentence.endsWith('.')) {
|
|
36
|
+
sentence += '.';
|
|
37
|
+
}
|
|
38
|
+
return sentence;
|
|
39
|
+
}
|
|
40
|
+
const LOREM_IPSUM = {
|
|
41
|
+
paragraphs: [
|
|
42
|
+
{
|
|
43
|
+
sentences: [
|
|
44
|
+
{
|
|
45
|
+
words: [
|
|
46
|
+
'Lorem',
|
|
47
|
+
'ipsum',
|
|
48
|
+
'dolor',
|
|
49
|
+
'sit',
|
|
50
|
+
'amet,',
|
|
51
|
+
'consectetur',
|
|
52
|
+
'adipiscing',
|
|
53
|
+
'elit,',
|
|
54
|
+
'sed',
|
|
55
|
+
'do',
|
|
56
|
+
'eiusmod',
|
|
57
|
+
'tempor',
|
|
58
|
+
'incididunt',
|
|
59
|
+
'ut',
|
|
60
|
+
'labore',
|
|
61
|
+
'et',
|
|
62
|
+
'dolore',
|
|
63
|
+
'magna',
|
|
64
|
+
'aliqua.',
|
|
65
|
+
],
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
words: [
|
|
69
|
+
'Ut',
|
|
70
|
+
'enim',
|
|
71
|
+
'ad',
|
|
72
|
+
'minim',
|
|
73
|
+
'veniam,',
|
|
74
|
+
'quis',
|
|
75
|
+
'nostrud',
|
|
76
|
+
'exercitation',
|
|
77
|
+
'ullamco',
|
|
78
|
+
'laboris',
|
|
79
|
+
'nisi',
|
|
80
|
+
'ut',
|
|
81
|
+
'aliquip',
|
|
82
|
+
'ex',
|
|
83
|
+
'ea',
|
|
84
|
+
'commodo',
|
|
85
|
+
'consequat.',
|
|
86
|
+
],
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
words: [
|
|
90
|
+
'Duis',
|
|
91
|
+
'aute',
|
|
92
|
+
'irure',
|
|
93
|
+
'dolor',
|
|
94
|
+
'in',
|
|
95
|
+
'reprehenderit',
|
|
96
|
+
'in',
|
|
97
|
+
'voluptate',
|
|
98
|
+
'velit',
|
|
99
|
+
'esse',
|
|
100
|
+
'cillum',
|
|
101
|
+
'dolore',
|
|
102
|
+
'eu',
|
|
103
|
+
'fugiat',
|
|
104
|
+
'nulla',
|
|
105
|
+
'pariatur.',
|
|
106
|
+
],
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
words: [
|
|
110
|
+
'Excepteur',
|
|
111
|
+
'sint',
|
|
112
|
+
'occaecat',
|
|
113
|
+
'cupidatat',
|
|
114
|
+
'non',
|
|
115
|
+
'proident,',
|
|
116
|
+
'sunt',
|
|
117
|
+
'in',
|
|
118
|
+
'culpa',
|
|
119
|
+
'qui',
|
|
120
|
+
'officia',
|
|
121
|
+
'deserunt',
|
|
122
|
+
'mollit',
|
|
123
|
+
'anim',
|
|
124
|
+
'id',
|
|
125
|
+
'est',
|
|
126
|
+
'laborum.',
|
|
127
|
+
],
|
|
128
|
+
},
|
|
129
|
+
],
|
|
130
|
+
},
|
|
131
|
+
],
|
|
132
|
+
};
|
|
133
|
+
const PARAGRAPHS = LOREM_IPSUM.paragraphs;
|
|
134
|
+
const SENTENCES = PARAGRAPHS.flatMap((paragraph) => paragraph.sentences);
|
|
135
|
+
const WORDS = SENTENCES.flatMap((sentence) => sentence.words);
|
|
136
|
+
//# sourceMappingURL=loremIpsum.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loremIpsum.js","sourceRoot":"","sources":["../src/loremIpsum.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAE1C;;;;;;;;GAQG;AACH,MAAM,UAAU,UAAU,CACxB,KAAK,GAAW,CAAC,EACjB,KAAK,GAAyC,WAAW;IAEzD,QAAQ,KAAK,EAAE,CAAC;QACd,KAAK,OAAO;YACV,OAAO,eAAe,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC,CAAA;QACpD,KAAK,WAAW;YACd,OAAO,SAAS,CAAC,SAAS,EAAE,CAAC,EAAE,KAAK,CAAC;iBAClC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,eAAe,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;iBAClD,IAAI,CAAC,GAAG,CAAC,CAAA;QACd,KAAK,YAAY;YACf,OAAO,SAAS,CAAC,UAAU,EAAE,CAAC,EAAE,KAAK,CAAC;iBACnC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CACjB,SAAS,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,eAAe,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CACjF;iBACA,IAAI,CAAC,IAAI,CAAC,CAAA;IACjB,CAAC;AACH,CAAC;AAED,SAAS,eAAe,CAAC,KAAe;IACtC,IAAI,QAAQ,GAAG,EAAE,CAAA;IACjB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC;YAAE,QAAQ,IAAI,GAAG,CAAA;QACxC,QAAQ,IAAI,IAAI,CAAA;IAClB,CAAC;IACD,IAAI,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QAC3B,QAAQ,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA;IAClC,CAAC;IACD,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QACnD,QAAQ,IAAI,GAAG,CAAA;IACjB,CAAC;IACD,OAAO,QAAQ,CAAA;AACjB,CAAC;AAED,MAAM,WAAW,GAAG;IAClB,UAAU,EAAE;QACV;YACE,SAAS,EAAE;gBACT;oBACE,KAAK,EAAE;wBACL,OAAO;wBACP,OAAO;wBACP,OAAO;wBACP,KAAK;wBACL,OAAO;wBACP,aAAa;wBACb,YAAY;wBACZ,OAAO;wBACP,KAAK;wBACL,IAAI;wBACJ,SAAS;wBACT,QAAQ;wBACR,YAAY;wBACZ,IAAI;wBACJ,QAAQ;wBACR,IAAI;wBACJ,QAAQ;wBACR,OAAO;wBACP,SAAS;qBACV;iBACF;gBACD;oBACE,KAAK,EAAE;wBACL,IAAI;wBACJ,MAAM;wBACN,IAAI;wBACJ,OAAO;wBACP,SAAS;wBACT,MAAM;wBACN,SAAS;wBACT,cAAc;wBACd,SAAS;wBACT,SAAS;wBACT,MAAM;wBACN,IAAI;wBACJ,SAAS;wBACT,IAAI;wBACJ,IAAI;wBACJ,SAAS;wBACT,YAAY;qBACb;iBACF;gBACD;oBACE,KAAK,EAAE;wBACL,MAAM;wBACN,MAAM;wBACN,OAAO;wBACP,OAAO;wBACP,IAAI;wBACJ,eAAe;wBACf,IAAI;wBACJ,WAAW;wBACX,OAAO;wBACP,MAAM;wBACN,QAAQ;wBACR,QAAQ;wBACR,IAAI;wBACJ,QAAQ;wBACR,OAAO;wBACP,WAAW;qBACZ;iBACF;gBACD;oBACE,KAAK,EAAE;wBACL,WAAW;wBACX,MAAM;wBACN,UAAU;wBACV,WAAW;wBACX,KAAK;wBACL,WAAW;wBACX,MAAM;wBACN,IAAI;wBACJ,OAAO;wBACP,KAAK;wBACL,SAAS;wBACT,UAAU;wBACV,QAAQ;wBACR,MAAM;wBACN,IAAI;wBACJ,KAAK;wBACL,UAAU;qBACX;iBACF;aACF;SACF;KACF;CACF,CAAA;AAED,MAAM,UAAU,GAAG,WAAW,CAAC,UAAU,CAAA;AACzC,MAAM,SAAS,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,SAAS,CAAC,CAAA;AACxE,MAAM,KAAK,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export interface NumberToBigIntOptions {
|
|
2
|
+
/**
|
|
3
|
+
* The number of digits starting from the right of the returned bigint to consider as decimal
|
|
4
|
+
* places.
|
|
5
|
+
*
|
|
6
|
+
* @default 18n
|
|
7
|
+
*/
|
|
8
|
+
precision?: bigint | undefined;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Converts a number to a bigint. Decimals to the right of `precision` are truncated.
|
|
12
|
+
*
|
|
13
|
+
* @param value - The number to convert to a bigint.
|
|
14
|
+
* @param options - Conversion options.
|
|
15
|
+
* @returns The bigint representation of `value`
|
|
16
|
+
*/
|
|
17
|
+
export declare function numberToBigInt(value: number, options?: NumberToBigIntOptions): bigint;
|
|
18
|
+
//# sourceMappingURL=numberToBigInt.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"numberToBigInt.d.ts","sourceRoot":"","sources":["../src/numberToBigInt.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,qBAAqB;IACpC;;;;;OAKG;IACH,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CAC/B;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,qBAAqB,GAAG,MAAM,CAkBrF"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { parseBigInt } from './parseBigInt.js';
|
|
2
|
+
/**
|
|
3
|
+
* Converts a number to a bigint. Decimals to the right of `precision` are truncated.
|
|
4
|
+
*
|
|
5
|
+
* @param value - The number to convert to a bigint.
|
|
6
|
+
* @param options - Conversion options.
|
|
7
|
+
* @returns The bigint representation of `value`
|
|
8
|
+
*/
|
|
9
|
+
export function numberToBigInt(value, options) {
|
|
10
|
+
const { precision = 18n } = options ?? {};
|
|
11
|
+
if (precision < 0n) {
|
|
12
|
+
throw new Error(`[numberToBigInt] \`precision\` must be positive, got ${precision}`);
|
|
13
|
+
}
|
|
14
|
+
// If `value` has decimals and `precision` is at least 1, parse it as a string
|
|
15
|
+
if (value % 1 !== 0 && precision >= 1n) {
|
|
16
|
+
const parsedValue = parseBigInt(String(value), { precision });
|
|
17
|
+
if (parsedValue === null) {
|
|
18
|
+
throw new Error(`[numberToBigInt] Failed to parse ${value} as a bigint with precision ${precision}`);
|
|
19
|
+
}
|
|
20
|
+
return parsedValue;
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
const precisionFactor = 10n ** precision;
|
|
24
|
+
return BigInt(Math.trunc(value)) * precisionFactor;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=numberToBigInt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"numberToBigInt.js","sourceRoot":"","sources":["../src/numberToBigInt.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAY9C;;;;;;GAMG;AACH,MAAM,UAAU,cAAc,CAAC,KAAa,EAAE,OAA+B;IAC3E,MAAM,EAAE,SAAS,GAAG,GAAG,EAAE,GAAG,OAAO,IAAI,EAAE,CAAA;IACzC,IAAI,SAAS,GAAG,EAAE,EAAE,CAAC;QACnB,MAAM,IAAI,KAAK,CAAC,wDAAwD,SAAS,EAAE,CAAC,CAAA;IACtF,CAAC;IACD,8EAA8E;IAC9E,IAAI,KAAK,GAAG,CAAC,KAAK,CAAC,IAAI,SAAS,IAAI,EAAE,EAAE,CAAC;QACvC,MAAM,WAAW,GAAG,WAAW,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,EAAE,SAAS,EAAE,CAAC,CAAA;QAC7D,IAAI,WAAW,KAAK,IAAI,EAAE,CAAC;YACzB,MAAM,IAAI,KAAK,CACb,oCAAoC,KAAK,+BAA+B,SAAS,EAAE,CACpF,CAAA;QACH,CAAC;QACD,OAAO,WAAW,CAAA;IACpB,CAAC;SAAM,CAAC;QACN,MAAM,eAAe,GAAG,GAAG,IAAI,SAAS,CAAA;QACxC,OAAO,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,GAAG,eAAe,CAAA;IACpD,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export interface ParseBigIntOptions {
|
|
2
|
+
/**
|
|
3
|
+
* The number of digits starting from the right of the returned bigint to consider as decimal
|
|
4
|
+
* places.
|
|
5
|
+
*
|
|
6
|
+
* @default 18n
|
|
7
|
+
*/
|
|
8
|
+
precision?: bigint | undefined;
|
|
9
|
+
/**
|
|
10
|
+
* If true, requires exact match (no commas, no extra whitespace)
|
|
11
|
+
*
|
|
12
|
+
* @default false
|
|
13
|
+
*/
|
|
14
|
+
strict?: boolean | undefined;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Like `parseNumber()`, but returns a bigint instead of a number. Decimals to the right of
|
|
18
|
+
* `precision` are truncated.
|
|
19
|
+
*
|
|
20
|
+
* @param value - The string to parse as a bigint.
|
|
21
|
+
* @param options - Parsing options.
|
|
22
|
+
* @returns The bigint representation of `value`, or `null` if we failed to parse it.
|
|
23
|
+
*/
|
|
24
|
+
export declare function parseBigInt(value: string, options?: ParseBigIntOptions): bigint | null;
|
|
25
|
+
//# sourceMappingURL=parseBigInt.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parseBigInt.d.ts","sourceRoot":"","sources":["../src/parseBigInt.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,kBAAkB;IACjC;;;;;OAKG;IACH,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC9B;;;;OAIG;IACH,MAAM,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;CAC7B;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,kBAAkB,iBA0BtE"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Like `parseNumber()`, but returns a bigint instead of a number. Decimals to the right of
|
|
3
|
+
* `precision` are truncated.
|
|
4
|
+
*
|
|
5
|
+
* @param value - The string to parse as a bigint.
|
|
6
|
+
* @param options - Parsing options.
|
|
7
|
+
* @returns The bigint representation of `value`, or `null` if we failed to parse it.
|
|
8
|
+
*/
|
|
9
|
+
export function parseBigInt(value, options) {
|
|
10
|
+
const { precision = 18n, strict = false } = options ?? {};
|
|
11
|
+
if (precision < 0n) {
|
|
12
|
+
throw new Error(`[parseBigInt] \`precision\` must be positive, got ${precision}`);
|
|
13
|
+
}
|
|
14
|
+
const originalValue = value;
|
|
15
|
+
const cleanedValue = value.replace(/,/g, '').trim();
|
|
16
|
+
if (strict && cleanedValue !== originalValue)
|
|
17
|
+
return null;
|
|
18
|
+
if (cleanedValue === '' || cleanedValue === '-' || cleanedValue === '.' || cleanedValue === '-.')
|
|
19
|
+
return null;
|
|
20
|
+
const [integerPart, decimalPart = '', somethingAfterDecimalPart] = cleanedValue.split('.');
|
|
21
|
+
if (integerPart.trim() !== integerPart)
|
|
22
|
+
return null;
|
|
23
|
+
if (decimalPart.trim() !== decimalPart)
|
|
24
|
+
return null;
|
|
25
|
+
if (somethingAfterDecimalPart !== undefined)
|
|
26
|
+
return null;
|
|
27
|
+
try {
|
|
28
|
+
const precisionNumber = Number(precision);
|
|
29
|
+
return BigInt(`${integerPart}${decimalPart.slice(0, precisionNumber).padEnd(precisionNumber, '0')}`);
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=parseBigInt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parseBigInt.js","sourceRoot":"","sources":["../src/parseBigInt.ts"],"names":[],"mappings":"AAgBA;;;;;;;GAOG;AACH,MAAM,UAAU,WAAW,CAAC,KAAa,EAAE,OAA4B;IACrE,MAAM,EAAE,SAAS,GAAG,GAAG,EAAE,MAAM,GAAG,KAAK,EAAE,GAAG,OAAO,IAAI,EAAE,CAAA;IACzD,IAAI,SAAS,GAAG,EAAE,EAAE,CAAC;QACnB,MAAM,IAAI,KAAK,CAAC,qDAAqD,SAAS,EAAE,CAAC,CAAA;IACnF,CAAC;IAED,MAAM,aAAa,GAAG,KAAK,CAAA;IAC3B,MAAM,YAAY,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAA;IAEnD,IAAI,MAAM,IAAI,YAAY,KAAK,aAAa;QAAE,OAAO,IAAI,CAAA;IACzD,IAAI,YAAY,KAAK,EAAE,IAAI,YAAY,KAAK,GAAG,IAAI,YAAY,KAAK,GAAG,IAAI,YAAY,KAAK,IAAI;QAC9F,OAAO,IAAI,CAAA;IAEb,MAAM,CAAC,WAAW,EAAE,WAAW,GAAG,EAAE,EAAE,yBAAyB,CAAC,GAAG,YAAY,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;IAC1F,IAAI,WAAY,CAAC,IAAI,EAAE,KAAK,WAAW;QAAE,OAAO,IAAI,CAAA;IACpD,IAAI,WAAW,CAAC,IAAI,EAAE,KAAK,WAAW;QAAE,OAAO,IAAI,CAAA;IACnD,IAAI,yBAAyB,KAAK,SAAS;QAAE,OAAO,IAAI,CAAA;IAExD,IAAI,CAAC;QACH,MAAM,eAAe,GAAG,MAAM,CAAC,SAAS,CAAC,CAAA;QACzC,OAAO,MAAM,CACX,GAAG,WAAW,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC,EAAE,eAAe,CAAC,CAAC,MAAM,CAAC,eAAe,EAAE,GAAG,CAAC,EAAE,CACtF,CAAA;IACH,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAA;IACb,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export interface ParseNumberOptions {
|
|
2
|
+
/**
|
|
3
|
+
* If true, requires exact match (no commas, no extra whitespace)
|
|
4
|
+
*
|
|
5
|
+
* @default false
|
|
6
|
+
*/
|
|
7
|
+
strict?: boolean | undefined;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Parses a string value into a number, with optional strict mode.
|
|
11
|
+
*
|
|
12
|
+
* @param value - The string value to parse.
|
|
13
|
+
* @param options - Parsing options.
|
|
14
|
+
* @returns The parsed number, or null if parsing fails.
|
|
15
|
+
*/
|
|
16
|
+
export declare function parseNumber(value: string, options?: ParseNumberOptions): number | null;
|
|
17
|
+
//# sourceMappingURL=parseNumber.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parseNumber.d.ts","sourceRoot":"","sources":["../src/parseNumber.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,kBAAkB;IACjC;;;;OAIG;IACH,MAAM,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;CAC7B;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,kBAAkB,iBAOtE"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parses a string value into a number, with optional strict mode.
|
|
3
|
+
*
|
|
4
|
+
* @param value - The string value to parse.
|
|
5
|
+
* @param options - Parsing options.
|
|
6
|
+
* @returns The parsed number, or null if parsing fails.
|
|
7
|
+
*/
|
|
8
|
+
export function parseNumber(value, options) {
|
|
9
|
+
const { strict = false } = options ?? {};
|
|
10
|
+
const cleanedValue = value.replace(/,/g, '').trim();
|
|
11
|
+
if (cleanedValue === '' || (cleanedValue !== value && strict))
|
|
12
|
+
return null;
|
|
13
|
+
const number = Number(cleanedValue);
|
|
14
|
+
if (!Number.isFinite(number) || (String(number) !== cleanedValue && strict))
|
|
15
|
+
return null;
|
|
16
|
+
return number;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=parseNumber.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parseNumber.js","sourceRoot":"","sources":["../src/parseNumber.ts"],"names":[],"mappings":"AASA;;;;;;GAMG;AACH,MAAM,UAAU,WAAW,CAAC,KAAa,EAAE,OAA4B;IACrE,MAAM,EAAE,MAAM,GAAG,KAAK,EAAE,GAAG,OAAO,IAAI,EAAE,CAAA;IACxC,MAAM,YAAY,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAA;IACnD,IAAI,YAAY,KAAK,EAAE,IAAI,CAAC,YAAY,KAAK,KAAK,IAAI,MAAM,CAAC;QAAE,OAAO,IAAI,CAAA;IAC1E,MAAM,MAAM,GAAG,MAAM,CAAC,YAAY,CAAC,CAAA;IACnC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,YAAY,IAAI,MAAM,CAAC;QAAE,OAAO,IAAI,CAAA;IACxF,OAAO,MAAM,CAAA;AACf,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sliceWrap.d.ts","sourceRoot":"","sources":["../src/sliceWrap.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,wBAAgB,SAAS,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,OAOlE"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/** Same as `array.slice(start, end)`, but wraps around the end of the array. */
|
|
2
|
+
export function sliceWrap(array, start, end) {
|
|
3
|
+
if (array.length === 0)
|
|
4
|
+
return [];
|
|
5
|
+
const result = [];
|
|
6
|
+
for (let i = start; i < end; i++) {
|
|
7
|
+
result.push(array[i % array.length]);
|
|
8
|
+
}
|
|
9
|
+
return result;
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=sliceWrap.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sliceWrap.js","sourceRoot":"","sources":["../src/sliceWrap.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,MAAM,UAAU,SAAS,CAAI,KAAU,EAAE,KAAa,EAAE,GAAW;IACjE,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAA;IACjC,MAAM,MAAM,GAAiB,EAAE,CAAA;IAC/B,KAAK,IAAI,CAAC,GAAG,KAAK,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;QACjC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,KAAK,CAAC,MAAM,CAAE,CAAC,CAAA;IACvC,CAAC;IACD,OAAO,MAAM,CAAA;AACf,CAAC"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { SetNonNullable, SetRequired } from 'type-fest';
|
|
2
|
+
export type DeepRecord<Value> = {
|
|
3
|
+
[key: string]: Value | DeepRecord<Value>;
|
|
4
|
+
};
|
|
5
|
+
export type SetRequiredNonNullable<T, K extends keyof T> = SetRequired<SetNonNullable<T, K>, K>;
|
|
6
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AAE5D,MAAM,MAAM,UAAU,CAAC,KAAK,IAAI;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,CAAA;CAAE,CAAA;AAC5E,MAAM,MAAM,sBAAsB,CAAC,CAAC,EAAE,CAAC,SAAS,MAAM,CAAC,IAAI,WAAW,CAAC,cAAc,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
package/package.json
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@edgeandnode/eds-utils",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "General utility functions for The Edge Design System",
|
|
5
|
+
"author": "Edge & Node and contributors",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/edgeandnode/eds.git",
|
|
10
|
+
"directory": "packages/utils"
|
|
11
|
+
},
|
|
12
|
+
"homepage": "https://github.com/edgeandnode/eds/tree/main/packages/utils",
|
|
13
|
+
"bugs": "https://github.com/edgeandnode/eds/issues",
|
|
14
|
+
"type": "module",
|
|
15
|
+
"sideEffects": false,
|
|
16
|
+
"exports": {
|
|
17
|
+
".": "./dist/index.js"
|
|
18
|
+
},
|
|
19
|
+
"files": [
|
|
20
|
+
"dist",
|
|
21
|
+
"!dist/**/*.test.*",
|
|
22
|
+
"src",
|
|
23
|
+
"!src/**/*.test.*"
|
|
24
|
+
],
|
|
25
|
+
"dependencies": {
|
|
26
|
+
"md5": "^2.3.0",
|
|
27
|
+
"viem": "^2.56.8"
|
|
28
|
+
},
|
|
29
|
+
"devDependencies": {
|
|
30
|
+
"@types/md5": "^2.3.6"
|
|
31
|
+
},
|
|
32
|
+
"scripts": {
|
|
33
|
+
"build": "tsc --build tsconfig.build.json",
|
|
34
|
+
"test": "vitest run",
|
|
35
|
+
"test:watch": "vitest"
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export interface BigIntToNumberOptions {
|
|
2
|
+
/**
|
|
3
|
+
* The number of digits starting from the right of `value` to consider as decimal places.
|
|
4
|
+
*
|
|
5
|
+
* @default 18n
|
|
6
|
+
*/
|
|
7
|
+
precision?: bigint | undefined
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Converts a bigint to a number.
|
|
12
|
+
*
|
|
13
|
+
* @param value - The bigint to convert to a number.
|
|
14
|
+
* @param options - Conversion options.
|
|
15
|
+
* @returns The number representation of `value`
|
|
16
|
+
*/
|
|
17
|
+
export function bigIntToNumber(value: bigint, options?: BigIntToNumberOptions): number {
|
|
18
|
+
const { precision = 18n } = options ?? {}
|
|
19
|
+
if (precision < 0n) {
|
|
20
|
+
throw new Error(`[bigIntToNumber] \`precision\` must be positive, got ${precision}`)
|
|
21
|
+
}
|
|
22
|
+
if (precision === 0n) {
|
|
23
|
+
return Number(value)
|
|
24
|
+
} else {
|
|
25
|
+
const valueString = String(value)
|
|
26
|
+
const decimalPointIndex = valueString.length - Number(precision)
|
|
27
|
+
if (decimalPointIndex <= 0) {
|
|
28
|
+
return Number(`0.${'0'.repeat(Math.abs(decimalPointIndex))}${valueString}`)
|
|
29
|
+
}
|
|
30
|
+
return Number(
|
|
31
|
+
`${valueString.slice(0, decimalPointIndex)}.${valueString.slice(decimalPointIndex)}`,
|
|
32
|
+
)
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/** Converts a camelCase string to kebab-case. */
|
|
2
|
+
export function camelToKebab(string: string) {
|
|
3
|
+
return (
|
|
4
|
+
string
|
|
5
|
+
// Insert dash between a group of uppercase letters and an uppercase letter followed by lowercase (`HTTPSEncryptionMethod200Success` => `HTTPS-EncryptionMethod200Success`)
|
|
6
|
+
.replace(/([A-Z]+)([A-Z][a-z])/g, '$1-$2')
|
|
7
|
+
// Insert dash between a lowercase letter and an uppercase letter (`HTTPS-EncryptionMethod200Success` => `HTTPS-Encryption-Method200Success`)
|
|
8
|
+
.replace(/([a-z])([A-Z])/g, '$1-$2')
|
|
9
|
+
// Insert dash between a letter and a digit (`HTTPS-Encryption-Method200Success` => `HTTPS-Encryption-Method-200Success`)
|
|
10
|
+
.replace(/([A-Za-z])(\d)/g, '$1-$2')
|
|
11
|
+
// Insert dash between a digit and a letter (`HTTPS-Encryption-Method-200Success` => `HTTPS-Encryption-Method-200-Success`)
|
|
12
|
+
.replace(/(\d)([A-Za-z])/g, '$1-$2')
|
|
13
|
+
// Convert to lowercase (`HTTPS-Encryption-Method-200-Success` => `https-encryption-method-200-success`)
|
|
14
|
+
.toLowerCase()
|
|
15
|
+
)
|
|
16
|
+
}
|
package/src/constants.ts
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import md5 from 'md5'
|
|
2
|
+
|
|
3
|
+
import { sliceWrap } from './sliceWrap.ts'
|
|
4
|
+
|
|
5
|
+
const identiconCache = new Map<string, string>()
|
|
6
|
+
|
|
7
|
+
export function createIdenticon(address: string) {
|
|
8
|
+
const lowercasedAddress = address.toLowerCase()
|
|
9
|
+
|
|
10
|
+
// Check the cache first
|
|
11
|
+
const cachedIdenticon = identiconCache.get(lowercasedAddress)
|
|
12
|
+
if (cachedIdenticon) {
|
|
13
|
+
return cachedIdenticon
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const hash = md5(lowercasedAddress)
|
|
17
|
+
const bytesPerPixel = 3
|
|
18
|
+
const pixels = 5
|
|
19
|
+
const rowPadding = (4 - ((pixels * bytesPerPixel) % 4)) % 4
|
|
20
|
+
const pixelArraySize = pixels * (pixels * bytesPerPixel + rowPadding)
|
|
21
|
+
const fileHeaderSize = 14
|
|
22
|
+
const dibHeaderSize = 40
|
|
23
|
+
const totalHeaderSize = fileHeaderSize + dibHeaderSize
|
|
24
|
+
const bufferSize = totalHeaderSize + pixelArraySize
|
|
25
|
+
const buffer = new Uint8Array(bufferSize)
|
|
26
|
+
|
|
27
|
+
// Set up the bitmap headers
|
|
28
|
+
buffer[0] = 0x42 // 'B'
|
|
29
|
+
buffer[1] = 0x4d // 'M'
|
|
30
|
+
buffer[2] = bufferSize & 0xff
|
|
31
|
+
buffer[3] = (bufferSize >> 8) & 0xff
|
|
32
|
+
buffer[4] = (bufferSize >> 16) & 0xff
|
|
33
|
+
buffer[5] = (bufferSize >> 24) & 0xff
|
|
34
|
+
buffer[10] = totalHeaderSize // Pixel data offset
|
|
35
|
+
buffer[14] = dibHeaderSize
|
|
36
|
+
buffer[18] = pixels & 0xff
|
|
37
|
+
buffer[19] = (pixels >> 8) & 0xff
|
|
38
|
+
buffer[22] = pixels & 0xff
|
|
39
|
+
buffer[23] = (pixels >> 8) & 0xff
|
|
40
|
+
buffer[26] = 1 // Planes
|
|
41
|
+
buffer[28] = 24 // Bits per pixel
|
|
42
|
+
|
|
43
|
+
// Determine the primary color based on the hash
|
|
44
|
+
const match = /#(..)(..)(..)/.exec(`#${hash.slice(0, 6)}`)
|
|
45
|
+
if (!match) throw new Error('[createIdenticon] Invalid color format')
|
|
46
|
+
const [r, g, b] = match.slice(1).map((hex) => parseInt(hex, 16)) as [number, number, number]
|
|
47
|
+
type BGR = [number, number, number]
|
|
48
|
+
const primaryColor: BGR = [b, g, r]
|
|
49
|
+
const backgroundColor: BGR = [255, 255, 255]
|
|
50
|
+
|
|
51
|
+
// Draw the image
|
|
52
|
+
const hashBinary = hash
|
|
53
|
+
.split('')
|
|
54
|
+
.map((el) => parseInt(el, 16))
|
|
55
|
+
.map((num) => (num < 8 ? 0 : 1))
|
|
56
|
+
const hashBinaryMap: (0 | 1)[][] = []
|
|
57
|
+
const columns = Math.ceil(pixels / 2)
|
|
58
|
+
for (let x = 0; x < columns; x++) {
|
|
59
|
+
hashBinaryMap[x] = sliceWrap(hashBinary, x * pixels, (x + 1) * pixels)
|
|
60
|
+
}
|
|
61
|
+
let position = totalHeaderSize
|
|
62
|
+
for (let y = pixels - 1; y >= 0; y--) {
|
|
63
|
+
for (let x = 0; x < pixels; x++) {
|
|
64
|
+
const color: BGR = hashBinaryMap[x > columns - 1 ? pixels - 1 - x : x]?.[y]
|
|
65
|
+
? primaryColor
|
|
66
|
+
: backgroundColor
|
|
67
|
+
buffer[position++] = color[0]
|
|
68
|
+
buffer[position++] = color[1]
|
|
69
|
+
buffer[position++] = color[2]
|
|
70
|
+
}
|
|
71
|
+
position += rowPadding
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Convert the image to a base64 string
|
|
75
|
+
let binary = ''
|
|
76
|
+
for (let i = 0; i < buffer.length; i++) {
|
|
77
|
+
binary += String.fromCharCode(buffer[i]!)
|
|
78
|
+
}
|
|
79
|
+
const identicon = `data:image/bmp;base64,${btoa(binary)}`
|
|
80
|
+
|
|
81
|
+
// Store it in the cache, then return it
|
|
82
|
+
identiconCache.set(lowercasedAddress, identicon)
|
|
83
|
+
return identicon
|
|
84
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { getAddress } from 'viem'
|
|
2
|
+
|
|
3
|
+
import { ZERO_ADDRESS } from './constants.ts'
|
|
4
|
+
|
|
5
|
+
type FormatAddressOptions = {
|
|
6
|
+
/** @default 'short' */
|
|
7
|
+
style?: 'short' | 'full' | undefined
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Formats an EVM wallet address as a string.
|
|
12
|
+
*
|
|
13
|
+
* @param address - The address to format.
|
|
14
|
+
* @param options - Formatting options.
|
|
15
|
+
* @returns The formatted address string.
|
|
16
|
+
*/
|
|
17
|
+
export function formatAddress(address: string, options: FormatAddressOptions = {}): string {
|
|
18
|
+
const { style = 'short' } = options
|
|
19
|
+
|
|
20
|
+
if (!address) address = ZERO_ADDRESS
|
|
21
|
+
try {
|
|
22
|
+
address = address.startsWith('0x') ? getAddress(address) : address
|
|
23
|
+
} catch {}
|
|
24
|
+
|
|
25
|
+
switch (style) {
|
|
26
|
+
case 'short':
|
|
27
|
+
const lengthOnEachSide = 6
|
|
28
|
+
if (address.length <= lengthOnEachSide * 2 + 1) return address
|
|
29
|
+
return `${address.slice(0, lengthOnEachSide)}–${address.slice(-lengthOnEachSide)}`
|
|
30
|
+
case 'full':
|
|
31
|
+
return address
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
export interface BigIntFormatOptions {
|
|
2
|
+
/**
|
|
3
|
+
* The number of digits starting from the right of `value` to consider as decimal places.
|
|
4
|
+
*
|
|
5
|
+
* @default 18n
|
|
6
|
+
*/
|
|
7
|
+
precision?: bigint | undefined
|
|
8
|
+
/** @default 0 */
|
|
9
|
+
minimumFractionDigits?: number | undefined
|
|
10
|
+
/** @default 20 */
|
|
11
|
+
maximumFractionDigits?: number | undefined
|
|
12
|
+
/** @default 'auto' */
|
|
13
|
+
trailingZeroDisplay?: 'auto' | 'stripIfInteger' | undefined
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Formats a bigint as a string.
|
|
18
|
+
*
|
|
19
|
+
* @param value - The bigint to format.
|
|
20
|
+
* @param options - Formatting options.
|
|
21
|
+
* @returns The string representation of `value`
|
|
22
|
+
*/
|
|
23
|
+
export function formatBigInt(value: bigint, options?: BigIntFormatOptions): string {
|
|
24
|
+
const {
|
|
25
|
+
precision = 18n,
|
|
26
|
+
minimumFractionDigits = 0,
|
|
27
|
+
maximumFractionDigits = 20,
|
|
28
|
+
trailingZeroDisplay = 'auto',
|
|
29
|
+
} = options ?? {}
|
|
30
|
+
|
|
31
|
+
if (precision < 0n) {
|
|
32
|
+
throw new Error(`[formatBigInt] \`precision\` must be positive, got ${precision}`)
|
|
33
|
+
}
|
|
34
|
+
if (minimumFractionDigits > maximumFractionDigits) {
|
|
35
|
+
throw new Error(
|
|
36
|
+
`[formatBigInt] \`minimumFractionDigits\` (${minimumFractionDigits}) cannot be greater than \`maximumFractionDigits\` (${maximumFractionDigits})`,
|
|
37
|
+
)
|
|
38
|
+
}
|
|
39
|
+
const isNegative = value < 0n
|
|
40
|
+
const absValue = isNegative ? value * -1n : value
|
|
41
|
+
const precisionFactor = 10n ** precision
|
|
42
|
+
const integerPart = absValue / precisionFactor
|
|
43
|
+
const integerPartString = `${isNegative ? '-' : ''}${integerPart.toLocaleString('en-US')}`
|
|
44
|
+
const decimalPart = absValue % precisionFactor
|
|
45
|
+
let decimalPartString = ''
|
|
46
|
+
if ((decimalPart > 0n || minimumFractionDigits > 0) && maximumFractionDigits > 0) {
|
|
47
|
+
decimalPartString = decimalPart
|
|
48
|
+
.toLocaleString('en-US', {
|
|
49
|
+
useGrouping: false,
|
|
50
|
+
})
|
|
51
|
+
.padStart(Number(precision), '0')
|
|
52
|
+
.replace(/0+$/, '')
|
|
53
|
+
.padEnd(minimumFractionDigits, '0')
|
|
54
|
+
.slice(0, maximumFractionDigits)
|
|
55
|
+
if (trailingZeroDisplay === 'stripIfInteger' && decimalPartString.replace(/0/g, '') === '') {
|
|
56
|
+
decimalPartString = ''
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return `${integerPartString}${decimalPartString ? `.${decimalPartString}` : ''}`
|
|
60
|
+
}
|