smart-unit 1.0.4 → 2.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/dist/index.js DELETED
@@ -1,235 +0,0 @@
1
- 'use strict';
2
-
3
- Object.defineProperty(exports, '__esModule', { value: true });
4
-
5
- var DecimalConstructor = require('decimal.js');
6
-
7
- /*!
8
- * smart-unit
9
- * Copyright (c) [2026] [flycran]
10
- * MIT License. See LICENSE for details.
11
- */
12
- const ERROR_NAN_INPUT = 'Accepting NaN as an argument may be unintentional and could lead to invalid results. If this is intentional, please set `SmartUnit.ignoreNaNInputs` to `true`.';
13
- const ERROR_HIGH_PRECISION_NOT_ENABLED = 'By default, only number input is supported. To enable high-precision calculations, explicitly set the decimalSafety parameter to true.';
14
- class SmartUnit {
15
- constructor(units, option = {}) {
16
- this.units = units;
17
- this.unitsStr = [];
18
- this.DecimalClass = DecimalConstructor;
19
- if (!units.length)
20
- throw new Error('units is empty.');
21
- this.threshold = option.threshold || 1;
22
- this.decimal = option.fractionDigits;
23
- this.highPrecision = option.useDecimal;
24
- if (option.decimalOptions) {
25
- this.DecimalClass = DecimalConstructor.clone(option.decimalOptions);
26
- }
27
- if (option.baseDigit) {
28
- const us = [];
29
- for (let i = 0; i < units.length; i++) {
30
- this.unitsStr.push(units[i].toString());
31
- us.push(units[i], option.baseDigit);
32
- }
33
- this.units = us.slice(0, -1);
34
- }
35
- else {
36
- for (let i = 0; i < units.length; i += 2) {
37
- this.unitsStr.push(units[i].toString());
38
- }
39
- this.units = units;
40
- }
41
- }
42
- // 根据输入数值获取单位和调整后的值
43
- /**
44
- * Gets the appropriate unit and adjusted value for the input number
45
- *
46
- * @param num - The input number to determine the unit for
47
- * @returns An object containing the adjusted number and its corresponding unit
48
- */
49
- getUnit(num) {
50
- if (!SmartUnit.ignoreNaNInputs && Number.isNaN(num))
51
- throw new Error(ERROR_NAN_INPUT);
52
- let i = 1;
53
- if (this.highPrecision) {
54
- const dn = new this.DecimalClass(typeof num === 'bigint' ? num.toString() : num);
55
- const isNegative = dn.isNegative();
56
- let absDn = isNegative ? dn.abs() : dn;
57
- while (i < this.units.length - 1) {
58
- const n = this.units[i];
59
- if (typeof n === 'string')
60
- throw new Error(`The unit setting is incorrect; the element at index [${i}] should be of numeric type.`);
61
- if (absDn.lt(n * this.threshold)) {
62
- break;
63
- }
64
- absDn = absDn.dividedBy(n);
65
- i += 2;
66
- }
67
- const result = isNegative ? absDn.neg() : absDn;
68
- return {
69
- num: result.toNumber(),
70
- decimal: result,
71
- unit: this.units[i - 1].toString(),
72
- };
73
- }
74
- else {
75
- if (typeof num !== 'number')
76
- throw new Error(ERROR_HIGH_PRECISION_NOT_ENABLED);
77
- const isNegative = num < 0;
78
- let absNum = isNegative ? -num : num;
79
- while (i < this.units.length - 1) {
80
- const n = this.units[i];
81
- if (typeof n === 'string')
82
- throw new Error(`The unit setting is incorrect; the element at index [${i}] should be of numeric type.`);
83
- if (absNum < n * this.threshold) {
84
- break;
85
- }
86
- absNum /= n;
87
- i += 2;
88
- }
89
- return {
90
- num: isNegative ? -absNum : absNum,
91
- unit: this.units[i - 1].toString(),
92
- };
93
- }
94
- }
95
- // 将数字转换为字符串表示形式,并可选择配置小数位数
96
- /**
97
- * Formats a number as a string with optional decimal place configuration
98
- *
99
- * @param num - The number to convert to string
100
- * @param decimal - Decimal precision configuration (defaults to instance setting)
101
- * - If a number, defines fixed decimal places
102
- * - If a string in "min-max" format, defines a range of decimal places
103
- * - If omitted, uses the instance's default decimal configuration
104
- * @returns The formatted string representation with unit
105
- */
106
- format(num, decimal = this.decimal) {
107
- const { num: n, unit, decimal: dec, } = this.getUnit(num);
108
- let ns;
109
- if (typeof decimal === 'number') {
110
- ns = (dec !== null && dec !== undefined ? dec : n).toFixed(decimal);
111
- }
112
- else if (typeof decimal === 'string') {
113
- const [dp1, dp2] = decimal
114
- .split('-');
115
- const ndp = (n.toString().split('.')[1] || '').length;
116
- const minDp = dp1 ? +dp1 : -Infinity;
117
- const maxDp = dp2 ? +dp2 : Infinity;
118
- if (ndp < minDp) {
119
- ns = (dec !== null && dec !== undefined ? dec : n).toFixed(minDp);
120
- }
121
- else if (ndp > maxDp) {
122
- ns = (dec !== null && dec !== undefined ? dec : n).toFixed(maxDp);
123
- }
124
- else {
125
- ns = (dec !== null && dec !== undefined ? dec : n).toString();
126
- }
127
- }
128
- else {
129
- ns = (dec !== null && dec !== undefined ? dec : n).toString();
130
- }
131
- return `${ns}${unit}`;
132
- }
133
- // 将给定数值从指定单位转换为基本单位
134
- /**
135
- * Converts a value from the specified unit to the base unit
136
- *
137
- * @param num - The number to convert
138
- * @param unit - The original unit of the number
139
- * @returns The converted value in base unit
140
- * - Returns Decimal if high-precision mode is enabled
141
- */
142
- toBase(num, unit) {
143
- if (!SmartUnit.ignoreNaNInputs && Number.isNaN(num))
144
- throw new Error(ERROR_NAN_INPUT);
145
- let i = 0;
146
- if (this.highPrecision) {
147
- // High-precision calculation
148
- let dn = new this.DecimalClass(typeof num === 'bigint' ? num.toString() : num);
149
- while (i < this.units.length) {
150
- if (this.units[i] === unit) {
151
- return dn;
152
- }
153
- if (typeof this.units[i] === 'undefined') {
154
- break;
155
- }
156
- const cn = this.units[i + 1];
157
- if (typeof cn !== 'number')
158
- throw Error(`The unit setting is incorrect; the element at index [${i}] should be of numeric type.`);
159
- dn = dn.times(cn);
160
- i += 2;
161
- }
162
- }
163
- else {
164
- if (typeof num !== 'number')
165
- throw new Error(ERROR_HIGH_PRECISION_NOT_ENABLED);
166
- let nn = num;
167
- // Normal calculation
168
- while (i < this.units.length) {
169
- if (this.units[i] === unit) {
170
- return nn;
171
- }
172
- if (typeof this.units[i + 1] === 'undefined') {
173
- break;
174
- }
175
- if (typeof this.units[i + 1] !== 'number')
176
- throw Error(`The unit setting is incorrect; the element at index [${i}] should be of numeric type.`);
177
- nn *= this.units[i + 1];
178
- i += 2;
179
- }
180
- }
181
- throw new Error(`Undefined unit: "${unit}".`);
182
- }
183
- // 从给定字符串中分离出数字部分和单位
184
- /**
185
- * Splits a string into its numeric part and unit
186
- *
187
- * @param str - Input string containing a number followed by a unit
188
- * @returns An object containing the numeric value and unit
189
- * Only supports predefined units
190
- * Throws an error if no match is found
191
- */
192
- splitUnit(str) {
193
- const re = new RegExp(`^(\\d+(?:\\.\\d+)?)(${this.unitsStr.map(u => `${u}`).join('|')})`);
194
- const [, num, unit] = str.match(re) || [];
195
- if (num === undefined || unit === undefined) {
196
- throw new Error(`Undefined unit: "${str}".`);
197
- }
198
- return {
199
- num: +num,
200
- unit,
201
- decimal: this.highPrecision ? new this.DecimalClass(num) : undefined,
202
- };
203
- }
204
- // 将带单位的值转换为基础单位的数值
205
- /**
206
- * Parses a string with unit into a base unit numeric value
207
- *
208
- * @param str - Input string containing a number and unit
209
- * @returns The value converted to base unit
210
- * - Returns Decimal if high-precision mode is enabled
211
- */
212
- parse(str) {
213
- const { num, unit, decimal, } = this.splitUnit(str);
214
- return this.toBase((decimal !== null && decimal !== undefined ? decimal : num), unit);
215
- }
216
- // 将给定数值从原单位转换为最佳单位,并可指定小数精度
217
- /**
218
- * Converts a value from the original unit to the optimal unit with optional decimal precision
219
- *
220
- * @param num - The number to convert
221
- * @param unit - The original unit
222
- * @param decimal - Optional decimal places for formatting output
223
- * @returns The converted number as a formatted string
224
- */
225
- fromUnitFormat(num, unit, decimal) {
226
- const nnum = this.toBase(num, unit);
227
- return this.format(nnum, decimal);
228
- }
229
- }
230
- SmartUnit.ignoreNaNInputs = false;
231
-
232
- exports.ERROR_HIGH_PRECISION_NOT_ENABLED = ERROR_HIGH_PRECISION_NOT_ENABLED;
233
- exports.ERROR_NAN_INPUT = ERROR_NAN_INPUT;
234
- exports.SmartUnit = SmartUnit;
235
- exports.default = SmartUnit;