@peter-present/format-number 0.0.1
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/README.md +116 -0
- package/dist/compact.d.ts +2 -0
- package/dist/format.d.ts +8 -0
- package/dist/index.cjs +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +125 -0
- package/dist/round.d.ts +3 -0
- package/dist/types.d.ts +14 -0
- package/dist/utils.d.ts +2 -0
- package/package.json +66 -0
package/README.md
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# format-number
|
|
2
|
+
|
|
3
|
+
A lightweight, high-precision JavaScript/TypeScript library for rounding and formatting numbers. It handles everything from large financial figures and crypto balances to extremely small fractions with scientific subscripts.
|
|
4
|
+
|
|
5
|
+
Designed for precision-critical applications where numbers often exceed safe integer limits.
|
|
6
|
+
|
|
7
|
+
For detailed documentation and advanced usage, visit: [here](https://blog.peter-present.xyz/format-number)
|
|
8
|
+
|
|
9
|
+
## Key Features
|
|
10
|
+
|
|
11
|
+
- **High Precision**: Native support for `string`, `number`, and `bigint` without loss of precision.
|
|
12
|
+
- **Multiple Rounding Modes**: 5 different strategies to handle rounding exactly how you need.
|
|
13
|
+
- **Compact Formatting**: Automatically shorten large numbers with suffixes (K, M, B, T, Q).
|
|
14
|
+
- **Small Number Notation**: Smart formatting for tiny numbers using subscript zeros (e.g., `0.0₃5`).
|
|
15
|
+
- **Flexible Metadata**: Easily add prefixes and suffixes (e.g., Currency symbols, Units).
|
|
16
|
+
- **Fluent API**: Chained operations for cleaner, more readable code.
|
|
17
|
+
- **Zero Dependencies**: Keeps your bundle size minimal.
|
|
18
|
+
|
|
19
|
+
## Installation
|
|
20
|
+
|
|
21
|
+
```shell
|
|
22
|
+
# npm
|
|
23
|
+
npm install format-number
|
|
24
|
+
|
|
25
|
+
# yarn
|
|
26
|
+
yarn add format-number
|
|
27
|
+
|
|
28
|
+
# bun
|
|
29
|
+
bun install format-number
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Core Functions
|
|
33
|
+
|
|
34
|
+
### Rounding: `round()`
|
|
35
|
+
|
|
36
|
+
Round numbers using specific strategies and precision.
|
|
37
|
+
|
|
38
|
+
```typescript
|
|
39
|
+
import { round } from 'format-number';
|
|
40
|
+
|
|
41
|
+
round(123.456, { precision: 2 }); // '123.46'
|
|
42
|
+
round(-123.45, { mode: 'up', precision: 1 }); // '-123.4' (Towards +Infinity)
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### Compact Formatting: `compact()`
|
|
46
|
+
|
|
47
|
+
Format large numbers with readable suffixes.
|
|
48
|
+
|
|
49
|
+
```typescript
|
|
50
|
+
import { compact } from 'format-number';
|
|
51
|
+
|
|
52
|
+
compact(1500); // '1.5K'
|
|
53
|
+
compact(1200000, { precision: 1 }); // '1.2M'
|
|
54
|
+
compact('1000000000000'); // '1T'
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### Advanced Formatting: `formatNumber()`
|
|
58
|
+
|
|
59
|
+
A comprehensive function combining rounding, compacting, and metadata.
|
|
60
|
+
|
|
61
|
+
```typescript
|
|
62
|
+
import { formatNumber } from 'format-number';
|
|
63
|
+
|
|
64
|
+
// Currency formatting
|
|
65
|
+
formatNumber(1234.56, { prefix: '$', precision: 1 }); // '$1234.6'
|
|
66
|
+
|
|
67
|
+
// Compact with metadata
|
|
68
|
+
formatNumber(1500000, { isCompact: true, suffix: ' units' }); // '1.5M units'
|
|
69
|
+
|
|
70
|
+
// Small number subscript notation
|
|
71
|
+
formatNumber(0.00005, { isSmall: true }); // '0.0₄5'
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Fluent / Chained API: `FN()`
|
|
75
|
+
|
|
76
|
+
Perform multiple operations in a readable chain.
|
|
77
|
+
|
|
78
|
+
```typescript
|
|
79
|
+
import { FN } from 'format-number';
|
|
80
|
+
|
|
81
|
+
const result = FN('1234567.89')
|
|
82
|
+
.round({ precision: 0 })
|
|
83
|
+
.format({ prefix: 'Total: ', suffix: ' tokens' });
|
|
84
|
+
|
|
85
|
+
console.log(result); // 'Total: 1234568 tokens'
|
|
86
|
+
|
|
87
|
+
// Compact chaining
|
|
88
|
+
FN(1000000).compact({ precision: 0 }); // '1M'
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## API Reference
|
|
92
|
+
|
|
93
|
+
### Rounding Modes (`RoundingMode`)
|
|
94
|
+
|
|
95
|
+
| Mode | Description |
|
|
96
|
+
| :--------- | :------------------------------------------------------------------- |
|
|
97
|
+
| `half` | Round to the nearest neighbor. If equidistant, round away from zero. |
|
|
98
|
+
| `up` | Round towards Positive Infinity. |
|
|
99
|
+
| `down` | Round towards Negative Infinity. |
|
|
100
|
+
| `truncate` | Round towards Zero. |
|
|
101
|
+
| `banker` | Round to the nearest even neighbor (Statistical rounding). |
|
|
102
|
+
|
|
103
|
+
### Configuration Options
|
|
104
|
+
|
|
105
|
+
| Option | Type | Description |
|
|
106
|
+
| :---------- | :------------- | :----------------------------------------------- |
|
|
107
|
+
| `precision` | `number` | Number of decimal places (default: `0`). |
|
|
108
|
+
| `mode` | `RoundingMode` | Rounding strategy (default: `'half'`). |
|
|
109
|
+
| `prefix` | `string` | Text to prepend to the result. |
|
|
110
|
+
| `suffix` | `string` | Text to append to the result. |
|
|
111
|
+
| `isCompact` | `boolean` | If `true`, uses K/M/B/T suffixes. |
|
|
112
|
+
| `isSmall` | `boolean` | If `true`, formats tiny numbers with subscripts. |
|
|
113
|
+
|
|
114
|
+
## License
|
|
115
|
+
|
|
116
|
+
ISC
|
package/dist/format.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { MetadataType, NumberType, OtherMetadataType, RoundingConfigType } from './types';
|
|
2
|
+
export declare function formatNumber(value: NumberType, options?: MetadataType): string;
|
|
3
|
+
export declare function FN(value: NumberType): {
|
|
4
|
+
round(options?: RoundingConfigType): any;
|
|
5
|
+
compact(options?: RoundingConfigType): string;
|
|
6
|
+
format(options?: OtherMetadataType): string;
|
|
7
|
+
toString(): string;
|
|
8
|
+
};
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});function f(s){const r=s.startsWith("-")?"-":"",t=r?s.slice(1):s;let e=0,n=t.length-1;for(;t[e]=="0"&&e<t.length;)e++;if(s.indexOf(".")>=0)for(;t[n]=="0"&&n>=0;)n--;const u=t.slice(e,n+1);return u==""||u=="."?"0":r+u}function g(s){let r=f(s);r=(r.startsWith("-")?"-":"")?r.slice(1):r;const[e,n=""]=r.split("."),i=n.match(/^0+/)?.[0]?.length||0,u=i.toString().split("").map(o=>String.fromCharCode(8320+parseInt(o))).join(""),c=n.slice(i);return`${e}.0${u}${c}`}function l(s){let r="",t=s.length-1,e="1";for(;t>=0;){const n=s[t];let i=Number(n)+(e?1:0);i>=10?(e="1",i-=10):e="",r=i.toString()+r,t--}return{result:e+r,remaining:e}}function S(s,r=0){const[t,e=""]=s.split(".");if(r===0)return e&&Number(e[0])>=5?l(t).result:t;if(r>=e.length)return t+(e?`.${e}`:"");const n=e.slice(0,r),i=e.slice(r);if(Number(i[0])>=5){const u=l(n);return u.remaining?l(t).result:t+"."+u.result}else return t+"."+n}function d(s,r=0){const[t,e=""]=s.split(".");if(r===0)return e?l(t).result:t;if(r>=e.length)return t+"."+e;const n=l(e.slice(0,r));return n.remaining?l(t).result:t+"."+n.result}function m(s,r=0){const[t,e=""]=s.split(".");if(r===0)return t;let n=e.slice(0,r),i=n.length-1;for(;i>=0&&n[i]=="0";)i--;return n=n.slice(0,i+1),t+(n?`.${n}`:"")}function $(s,r=0){const[t,e=""]=s.split(".");if(r===0)return e&&Number(e[0])>=5?Number(t[0])/2==0?t:l(t).result:t;if(r>=e.length)return t+(e?`.${e}`:"");const n=e.slice(0,r),i=e.slice(r);if(i[0]=="5"){if(Number(n[n.length-1])%2==0)return t+"."+n;{const u=l(n);return u.remaining?l(t).result:t+"."+u.result}}else if(Number(i[0])>5){const u=l(n);return u.remaining?l(t).result:t+"."+u.result}else return t+"."+n}function a(s,r={}){const t=r.mode||"half",e=r.precision||0;let n=f(String(s)),i="";switch(n.startsWith("-")&&(n=n.slice(1),i="-"),t){case"half":return i+S(n,e);case"up":return i==""?d(n,e):"-"+m(n,e);case"down":return i==""?m(n,e):"-"+d(n,e);case"truncate":return i+m(n,e);case"banker":return i+$(n,e)}}const b=["K","M","B","T","Q"];function P(s,r={}){let t=f(String(s)),e="";t.startsWith("-")&&(t=t.slice(1),e="-");let[n,i=""]=t.split("."),u=n.length,c=-1;for(;u>3&&c<4;){const o=n.slice(0,u-3);i=n.slice(u-3)+i,n=o,u-=3,c++}return a(`${e}${n}.${i}`,r)+(c>=0?b[c]:"")}function N(s,r){let t=String(s);r.isCompact==!0?t=P(t,r):r.isSmall||(t=a(t,r));const e=r.prefix||"",n=r.suffix||"",i=r.isSmall||!1;return`${e}${i?g(t):t}${n}`}function h(s){return{round(r={}){return h(a(s,r))},compact(r={}){return P(s,r)},format(r={}){const t=r.prefix||"",e=r.suffix||"",n=r.isSmall||!1;return`${t}${n?g(String(s)):s}${e}`},toString(){return String(s)}}}exports.FN=h;exports.compact=P;exports.formatNumber=N;exports.formatSmallNum=g;exports.removeZero=f;exports.round=a;
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
function o(s) {
|
|
2
|
+
const r = s.startsWith("-") ? "-" : "", t = r ? s.slice(1) : s;
|
|
3
|
+
let e = 0, n = t.length - 1;
|
|
4
|
+
for (; t[e] == "0" && e < t.length; ) e++;
|
|
5
|
+
if (s.indexOf(".") >= 0) for (; t[n] == "0" && n >= 0; ) n--;
|
|
6
|
+
const l = t.slice(e, n + 1);
|
|
7
|
+
return l == "" || l == "." ? "0" : r + l;
|
|
8
|
+
}
|
|
9
|
+
function P(s) {
|
|
10
|
+
let r = o(s);
|
|
11
|
+
r = (r.startsWith("-") ? "-" : "") ? r.slice(1) : r;
|
|
12
|
+
const [e, n = ""] = r.split("."), i = n.match(/^0+/)?.[0]?.length || 0, l = i.toString().split("").map((f) => String.fromCharCode(8320 + parseInt(f))).join(""), c = n.slice(i);
|
|
13
|
+
return `${e}.0${l}${c}`;
|
|
14
|
+
}
|
|
15
|
+
function u(s) {
|
|
16
|
+
let r = "", t = s.length - 1, e = "1";
|
|
17
|
+
for (; t >= 0; ) {
|
|
18
|
+
const n = s[t];
|
|
19
|
+
let i = Number(n) + (e ? 1 : 0);
|
|
20
|
+
i >= 10 ? (e = "1", i -= 10) : e = "", r = i.toString() + r, t--;
|
|
21
|
+
}
|
|
22
|
+
return { result: e + r, remaining: e };
|
|
23
|
+
}
|
|
24
|
+
function d(s, r = 0) {
|
|
25
|
+
const [t, e = ""] = s.split(".");
|
|
26
|
+
if (r === 0)
|
|
27
|
+
return e && Number(e[0]) >= 5 ? u(t).result : t;
|
|
28
|
+
if (r >= e.length) return t + (e ? `.${e}` : "");
|
|
29
|
+
const n = e.slice(0, r), i = e.slice(r);
|
|
30
|
+
if (Number(i[0]) >= 5) {
|
|
31
|
+
const l = u(n);
|
|
32
|
+
return l.remaining ? u(t).result : t + "." + l.result;
|
|
33
|
+
} else return t + "." + n;
|
|
34
|
+
}
|
|
35
|
+
function g(s, r = 0) {
|
|
36
|
+
const [t, e = ""] = s.split(".");
|
|
37
|
+
if (r === 0)
|
|
38
|
+
return e ? u(t).result : t;
|
|
39
|
+
if (r >= e.length) return t + "." + e;
|
|
40
|
+
const n = u(e.slice(0, r));
|
|
41
|
+
return n.remaining ? u(t).result : t + "." + n.result;
|
|
42
|
+
}
|
|
43
|
+
function a(s, r = 0) {
|
|
44
|
+
const [t, e = ""] = s.split(".");
|
|
45
|
+
if (r === 0) return t;
|
|
46
|
+
let n = e.slice(0, r), i = n.length - 1;
|
|
47
|
+
for (; i >= 0 && n[i] == "0"; ) i--;
|
|
48
|
+
return n = n.slice(0, i + 1), t + (n ? `.${n}` : "");
|
|
49
|
+
}
|
|
50
|
+
function S(s, r = 0) {
|
|
51
|
+
const [t, e = ""] = s.split(".");
|
|
52
|
+
if (r === 0)
|
|
53
|
+
return e && Number(e[0]) >= 5 ? Number(t[0]) / 2 == 0 ? t : u(t).result : t;
|
|
54
|
+
if (r >= e.length) return t + (e ? `.${e}` : "");
|
|
55
|
+
const n = e.slice(0, r), i = e.slice(r);
|
|
56
|
+
if (i[0] == "5") {
|
|
57
|
+
if (Number(n[n.length - 1]) % 2 == 0)
|
|
58
|
+
return t + "." + n;
|
|
59
|
+
{
|
|
60
|
+
const l = u(n);
|
|
61
|
+
return l.remaining ? u(t).result : t + "." + l.result;
|
|
62
|
+
}
|
|
63
|
+
} else if (Number(i[0]) > 5) {
|
|
64
|
+
const l = u(n);
|
|
65
|
+
return l.remaining ? u(t).result : t + "." + l.result;
|
|
66
|
+
} else return t + "." + n;
|
|
67
|
+
}
|
|
68
|
+
function m(s, r = {}) {
|
|
69
|
+
const t = r.mode || "half", e = r.precision || 0;
|
|
70
|
+
let n = o(String(s)), i = "";
|
|
71
|
+
switch (n.startsWith("-") && (n = n.slice(1), i = "-"), t) {
|
|
72
|
+
case "half":
|
|
73
|
+
return i + d(n, e);
|
|
74
|
+
case "up":
|
|
75
|
+
return i == "" ? g(n, e) : "-" + a(n, e);
|
|
76
|
+
case "down":
|
|
77
|
+
return i == "" ? a(n, e) : "-" + g(n, e);
|
|
78
|
+
case "truncate":
|
|
79
|
+
return i + a(n, e);
|
|
80
|
+
case "banker":
|
|
81
|
+
return i + S(n, e);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
const $ = ["K", "M", "B", "T", "Q"];
|
|
85
|
+
function h(s, r = {}) {
|
|
86
|
+
let t = o(String(s)), e = "";
|
|
87
|
+
t.startsWith("-") && (t = t.slice(1), e = "-");
|
|
88
|
+
let [n, i = ""] = t.split("."), l = n.length, c = -1;
|
|
89
|
+
for (; l > 3 && c < 4; ) {
|
|
90
|
+
const f = n.slice(0, l - 3);
|
|
91
|
+
i = n.slice(l - 3) + i, n = f, l -= 3, c++;
|
|
92
|
+
}
|
|
93
|
+
return m(`${e}${n}.${i}`, r) + (c >= 0 ? $[c] : "");
|
|
94
|
+
}
|
|
95
|
+
function b(s, r) {
|
|
96
|
+
let t = String(s);
|
|
97
|
+
r.isCompact == !0 ? t = h(t, r) : r.isSmall || (t = m(t, r));
|
|
98
|
+
const e = r.prefix || "", n = r.suffix || "", i = r.isSmall || !1;
|
|
99
|
+
return `${e}${i ? P(t) : t}${n}`;
|
|
100
|
+
}
|
|
101
|
+
function x(s) {
|
|
102
|
+
return {
|
|
103
|
+
round(r = {}) {
|
|
104
|
+
return x(m(s, r));
|
|
105
|
+
},
|
|
106
|
+
compact(r = {}) {
|
|
107
|
+
return h(s, r);
|
|
108
|
+
},
|
|
109
|
+
format(r = {}) {
|
|
110
|
+
const t = r.prefix || "", e = r.suffix || "", n = r.isSmall || !1;
|
|
111
|
+
return `${t}${n ? P(String(s)) : s}${e}`;
|
|
112
|
+
},
|
|
113
|
+
toString() {
|
|
114
|
+
return String(s);
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
export {
|
|
119
|
+
x as FN,
|
|
120
|
+
h as compact,
|
|
121
|
+
b as formatNumber,
|
|
122
|
+
P as formatSmallNum,
|
|
123
|
+
o as removeZero,
|
|
124
|
+
m as round
|
|
125
|
+
};
|
package/dist/round.d.ts
ADDED
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export type NumberType = number | string | bigint;
|
|
2
|
+
export type RoundingMode = 'half' | 'up' | 'down' | 'banker' | 'truncate';
|
|
3
|
+
export type RoundingConfigType = Partial<{
|
|
4
|
+
mode: RoundingMode;
|
|
5
|
+
precision: number;
|
|
6
|
+
}>;
|
|
7
|
+
export type OtherMetadataType = Partial<{
|
|
8
|
+
prefix: string;
|
|
9
|
+
suffix: string;
|
|
10
|
+
isSmall: boolean;
|
|
11
|
+
}>;
|
|
12
|
+
export type MetadataType = RoundingConfigType & OtherMetadataType & Partial<{
|
|
13
|
+
isCompact: boolean;
|
|
14
|
+
}>;
|
package/dist/utils.d.ts
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@peter-present/format-number",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "Utility library for number formatting, rounding, and compact display.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.cjs",
|
|
7
|
+
"module": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"files": [
|
|
10
|
+
"dist"
|
|
11
|
+
],
|
|
12
|
+
"scripts": {
|
|
13
|
+
"build": "bun run clear && tsc && vite build",
|
|
14
|
+
"preview": "vite preview",
|
|
15
|
+
"clear": "rm -rf dist",
|
|
16
|
+
"test": "vitest run",
|
|
17
|
+
"prepare": "bun run build",
|
|
18
|
+
"eslint": "eslint --config ./eslint.config.js --cache",
|
|
19
|
+
"format": "prettier --write .",
|
|
20
|
+
"prepublishOnly": "bun run clear && bun run build && bun run test"
|
|
21
|
+
},
|
|
22
|
+
"repository": {
|
|
23
|
+
"type": "git",
|
|
24
|
+
"url": "git+https://github.com/phamhongphuc1999/format-number.git"
|
|
25
|
+
},
|
|
26
|
+
"keywords": [
|
|
27
|
+
"number",
|
|
28
|
+
"format",
|
|
29
|
+
"number-format",
|
|
30
|
+
"compact"
|
|
31
|
+
],
|
|
32
|
+
"author": "phamhongphuc1999",
|
|
33
|
+
"license": "ISC",
|
|
34
|
+
"bugs": {
|
|
35
|
+
"url": "https://github.com/phamhongphuc1999/format-number/issues"
|
|
36
|
+
},
|
|
37
|
+
"homepage": "https://github.com/phamhongphuc1999/format-number#readme",
|
|
38
|
+
"devDependencies": {
|
|
39
|
+
"@eslint/js": "^9.29.0",
|
|
40
|
+
"@types/node": "^20.12.2",
|
|
41
|
+
"eslint": "^9.29.0",
|
|
42
|
+
"eslint-import-resolver-typescript": "^4.4.4",
|
|
43
|
+
"eslint-plugin-import": "^2.32.0",
|
|
44
|
+
"eslint-plugin-prettier": "^5.5.1",
|
|
45
|
+
"eslint-plugin-react-hooks": "^5.2.0",
|
|
46
|
+
"eslint-plugin-react-refresh": "^0.4.20",
|
|
47
|
+
"path": "^0.12.7",
|
|
48
|
+
"tslib": "^2.6.2",
|
|
49
|
+
"typescript": "5.5.3",
|
|
50
|
+
"typescript-eslint": "^8.34.1",
|
|
51
|
+
"vite": "^7.2.7",
|
|
52
|
+
"vite-plugin-dts": "^4.5.4",
|
|
53
|
+
"vitest": "^4.0.15"
|
|
54
|
+
},
|
|
55
|
+
"contributors": [
|
|
56
|
+
{
|
|
57
|
+
"name": "Phạm Hồng Phúc",
|
|
58
|
+
"email": "phamhongphuc12atm1@gmail.com",
|
|
59
|
+
"url": "https://github.com/phamhongphuc1999"
|
|
60
|
+
}
|
|
61
|
+
],
|
|
62
|
+
"engines": {
|
|
63
|
+
"node": ">=16",
|
|
64
|
+
"npm": ">=7"
|
|
65
|
+
}
|
|
66
|
+
}
|