smart-unit 1.0.5 → 2.1.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.
@@ -0,0 +1,55 @@
1
+ import type Decimal from 'decimal.js';
2
+ import type { FormattedValue, FractionDigits, InputNumber, SmartUnitOptions } from './utils';
3
+ export declare abstract class SmartUnitBase<U extends string = string, D extends boolean = false> {
4
+ readonly threshold: number;
5
+ readonly separator: string;
6
+ readonly fractionDigits?: FractionDigits;
7
+ readonly unitNames: U[];
8
+ readonly unitDigits: number[];
9
+ _accumulatedDigits?: number[];
10
+ /** Accumulated digits for unit conversion */
11
+ get accumulatedDigits(): number[];
12
+ _sortedUnitNames?: U[];
13
+ /** Sorted unit names by length for efficient lookup */
14
+ get sortedUnitNames(): U[];
15
+ /** Unit conversion function */
16
+ convert?: (str: U) => string;
17
+ constructor(units: (U | number)[], option?: SmartUnitOptions);
18
+ withConvert(convert: (str: U) => string): this;
19
+ protected createAccumulatedDigits(): void;
20
+ protected createSortedUnitNames(): void;
21
+ /**
22
+ * Formats the decimal places of a number
23
+ *
24
+ * @param value - The value to format
25
+ * @param fractionDigits - Decimal precision configuration
26
+ * @returns The formatted string representation of the number
27
+ */
28
+ formatNumber(value: number | Decimal, fractionDigits?: FractionDigits): string;
29
+ abstract getUnit(num: InputNumber, fractionDigits?: FractionDigits): FormattedValue<U>;
30
+ protected _format(numStr: string, unit: U): string;
31
+ abstract format(num: InputNumber, fractionDigits?: FractionDigits): string;
32
+ abstract getChainUnit(num: InputNumber): FormattedValue<U>[];
33
+ protected _formatChain(chain: FormattedValue<U>[], separator?: string): string;
34
+ formatChain(num: InputNumber, separator?: string): string;
35
+ abstract toBase(num: InputNumber, unit: U): D extends true ? Decimal : number;
36
+ /**
37
+ * Splits a string into its numeric part and unit
38
+ *
39
+ * @param str - Input string containing a number followed by a unit
40
+ * @returns An object containing the numeric value, unit, and Decimal instance
41
+ * @throws An error if no predefined unit is matched
42
+ */
43
+ splitUnit(str: string): FormattedValue<U>;
44
+ /**
45
+ * Splits a string into its numeric part and unit
46
+ *
47
+ * @param str - Input string containing a number followed by a unit
48
+ * @returns An object containing the numeric value, unit, and Decimal instance
49
+ * @throws An error if no predefined unit is matched
50
+ */
51
+ splitChainUnit(str: string, separator?: string): FormattedValue<U>[];
52
+ abstract parse(str: string): D extends true ? Decimal : number;
53
+ abstract parseChain(str: string): D extends true ? Decimal : number;
54
+ abstract fromUnitFormat(num: InputNumber, unit: U, fractionDigits?: FractionDigits): string;
55
+ }
@@ -0,0 +1,97 @@
1
+ import { type Decimal } from 'decimal.js';
2
+ import { SmartUnitBase } from './SmartUnitBase';
3
+ import { type FormattedValue, type FractionDigits, type InputNumber, type SmartUnitOptions } from './utils';
4
+ export type DecimalOptions = Decimal.Config;
5
+ export type NumPrecision = InputNumber | string | bigint | Decimal;
6
+ export interface FormattedValuePrecision<U extends string> extends FormattedValue<U> {
7
+ decimal: Decimal;
8
+ }
9
+ export interface SmartUnitPrecisionOptions extends SmartUnitOptions {
10
+ /**
11
+ * Decimal.js configuration options
12
+ * - Creates an isolated Decimal class for this SmartUnit instance only
13
+ * - Used to customize precision and other parameters
14
+ */
15
+ decimalOptions?: DecimalOptions;
16
+ }
17
+ export declare class SmartUnitPrecision<U extends string = string> extends SmartUnitBase<U, true> {
18
+ private DecimalClass;
19
+ constructor(units: (U | number)[], option?: SmartUnitPrecisionOptions);
20
+ /**
21
+ * Gets the appropriate unit and adjusted value for the input number
22
+ *
23
+ * @param num - The input NumPrecision to determine the unit for
24
+ * @param fractionDigits - Decimal precision configuration
25
+ * @returns The FormattedValue object containing the number, unit, and decimal instance
26
+ */
27
+ getUnit(num: NumPrecision): FormattedValuePrecision<U>;
28
+ /**
29
+ * Formats a number as a string with unit and optional decimal place configuration
30
+ *
31
+ * @param num - The input number to format
32
+ * @param fractionDigits - Decimal precision configuration
33
+ * @returns The formatted string with number and unit
34
+ */
35
+ format(num: NumPrecision, fractionDigits?: FractionDigits): string;
36
+ /**
37
+ * Gets the chain of units for the input number
38
+ *
39
+ * @param num - The input number to determine the chain for
40
+ * @returns An array of FormattedValue objects representing the chain of units
41
+ */
42
+ getChainUnit(num: NumPrecision): FormattedValuePrecision<U>[];
43
+ /**
44
+ * Formats a number as a chain of units string
45
+ *
46
+ * @param num - The input number to format
47
+ * @returns The formatted chain string
48
+ */
49
+ formatChain(num: NumPrecision, separator?: string): string;
50
+ /**
51
+ * Converts a value from the specified unit to the base unit
52
+ *
53
+ * @param num - The number to convert
54
+ * @param unit - The original unit of the number
55
+ * @returns The converted value in base unit
56
+ */
57
+ toBase(num: NumPrecision, unit: U): Decimal;
58
+ /**
59
+ * Splits a string into its numeric part and unit
60
+ *
61
+ * @param str - Input string containing a number followed by a unit
62
+ * @returns An object containing the numeric value, unit, and Decimal instance
63
+ * @throws An error if no predefined unit is matched
64
+ */
65
+ splitUnit(str: string): FormattedValuePrecision<U>;
66
+ /**
67
+ * Splits a string into its numeric part and unit
68
+ *
69
+ * @param str - Input string containing a number followed by a unit
70
+ * @returns An object containing the numeric value, unit, and Decimal instance
71
+ * @throws An error if no predefined unit is matched
72
+ */
73
+ splitChainUnit(str: string, separator?: string): FormattedValuePrecision<U>[];
74
+ /**
75
+ * Parses a string with unit into a base unit numeric value
76
+ *
77
+ * @param str - Input string containing a number and unit
78
+ * @returns The value converted to base unit
79
+ */
80
+ parse(str: string): Decimal;
81
+ /**
82
+ * Parses a string with chain units into a base unit numeric value
83
+ *
84
+ * @param str - Input string containing a number and unit
85
+ * @returns The value converted to base unit
86
+ */
87
+ parseChain(str: string): Decimal;
88
+ /**
89
+ * Converts a value from the original unit to the optimal unit with optional decimal precision
90
+ *
91
+ * @param num - The number to convert
92
+ * @param unit - The original unit
93
+ * @param fractionDigits - Optional decimal places for formatting output
94
+ * @returns The converted number as a formatted string
95
+ */
96
+ fromUnitFormat(num: NumPrecision, unit: U, fractionDigits?: FractionDigits): string;
97
+ }
@@ -0,0 +1,9 @@
1
+ /*!
2
+ * smart-unit
3
+ * Copyright (c) [2026] [flycran]
4
+ * MIT License. See LICENSE for details.
5
+ */
6
+ export * from './SmartUnit';
7
+ export * from './utils';
8
+ import { SmartUnit } from './SmartUnit';
9
+ export default SmartUnit;
@@ -0,0 +1,9 @@
1
+ /*!
2
+ * smart-unit
3
+ * Copyright (c) [2026] [flycran]
4
+ * MIT License. See LICENSE for details.
5
+ */
6
+ export * from './SmartUnitPrecision';
7
+ export * from './utils';
8
+ import { SmartUnitPrecision } from './SmartUnitPrecision';
9
+ export default SmartUnitPrecision;
@@ -0,0 +1,32 @@
1
+ import type { SmartUnitBase } from 'SmartUnitBase';
2
+ export type FractionDigits = number | `-${number}` | `${number}-` | `${number}-${number}` | undefined;
3
+ export interface SmartUnitOptions {
4
+ /** Base digit for auto-generating unit conversions */
5
+ baseDigit?: number;
6
+ /**
7
+ * Threshold for unit switching
8
+ * The comparison value is multiplied by this threshold
9
+ */
10
+ threshold?: number;
11
+ /**
12
+ * Number of decimal places to preserve in the result
13
+ * Can be a fixed number or a range like "min-max"
14
+ */
15
+ fractionDigits?: FractionDigits;
16
+ /**
17
+ * The separator for chain formatting
18
+ * - Default is an empty string
19
+ */
20
+ separator?: string;
21
+ }
22
+ export interface FormattedValue<U extends string> {
23
+ /** The numeric value */
24
+ num: number;
25
+ /** The unit string */
26
+ unit: U;
27
+ /** The number string with decimal places applied */
28
+ numStr: string;
29
+ }
30
+ export type InputNumber = number;
31
+ export type GetUnitNames<SU extends SmartUnitBase<any>> = SU extends SmartUnitBase<infer U> ? U : never;
32
+ export declare const ERROR_NAN_INPUT = "Accepting NaN as an argument may be unintentional and could lead to invalid results.";
@@ -0,0 +1,181 @@
1
+ 'use strict';
2
+
3
+ class SmartUnitBase {
4
+ /** Accumulated digits for unit conversion */
5
+ get accumulatedDigits() {
6
+ if (!this._accumulatedDigits)
7
+ this.createAccumulatedDigits();
8
+ return this._accumulatedDigits;
9
+ }
10
+ /** Sorted unit names by length for efficient lookup */
11
+ get sortedUnitNames() {
12
+ if (!this._sortedUnitNames)
13
+ this.createSortedUnitNames();
14
+ return this._sortedUnitNames;
15
+ }
16
+ constructor(units, option = {}) {
17
+ this.unitNames = [];
18
+ this.unitDigits = [];
19
+ // Initialize
20
+ if (!units.length)
21
+ throw new Error('units is empty.');
22
+ this.threshold = option.threshold || 1;
23
+ this.fractionDigits = option.fractionDigits;
24
+ this.separator = option.separator || '';
25
+ if (option.baseDigit) {
26
+ for (let i = 0; i < units.length; i++) {
27
+ const name = units[i];
28
+ if (typeof name !== 'string')
29
+ throw new Error(`The unit setting is incorrect; the element at index [${i}] should be of string type.`);
30
+ }
31
+ this.unitNames = units;
32
+ this.unitDigits = Array(units.length - 1).fill(option.baseDigit);
33
+ }
34
+ else {
35
+ for (let i = 1; i < units.length; i += 2) {
36
+ const digit = units[i];
37
+ if (typeof digit !== 'number')
38
+ throw new Error(`The unit setting is incorrect; the element at index [${i}] should be of numeric type.`);
39
+ this.unitDigits.push(units[i]);
40
+ const name = units[i - 1];
41
+ if (typeof name !== 'string')
42
+ throw new Error(`The unit setting is incorrect; the element at index [${i - 1}] should be of string type.`);
43
+ this.unitNames.push(name);
44
+ }
45
+ this.unitNames.push(units[units.length - 1]);
46
+ }
47
+ }
48
+ withConvert(convert) {
49
+ const su = Object.create(this);
50
+ su.convert = convert;
51
+ return su;
52
+ }
53
+ // 累积比例
54
+ createAccumulatedDigits() {
55
+ const accumulatedDigits = [];
56
+ this.unitDigits.forEach((digit, index) => {
57
+ if (index === 0) {
58
+ accumulatedDigits.push(digit);
59
+ }
60
+ else {
61
+ accumulatedDigits.push(accumulatedDigits[index - 1] * digit);
62
+ }
63
+ });
64
+ this._accumulatedDigits = accumulatedDigits;
65
+ }
66
+ // 长度排序后的单位名称
67
+ createSortedUnitNames() {
68
+ const sortedUnits = [...this.unitNames].sort((a, b) => b.length - a.length);
69
+ this._sortedUnitNames = sortedUnits;
70
+ }
71
+ // 格式化数字的小数位数
72
+ /**
73
+ * Formats the decimal places of a number
74
+ *
75
+ * @param value - The value to format
76
+ * @param fractionDigits - Decimal precision configuration
77
+ * @returns The formatted string representation of the number
78
+ */
79
+ formatNumber(value, fractionDigits = this.fractionDigits) {
80
+ if (typeof fractionDigits === 'number') {
81
+ return value.toFixed(fractionDigits);
82
+ }
83
+ else if (typeof fractionDigits === 'string') {
84
+ const [dp1, dp2] = fractionDigits.split('-');
85
+ const ndp = (value.toString().split('.')[1] || '').length;
86
+ const minDp = dp1 ? +dp1 : -Infinity;
87
+ const maxDp = dp2 ? +dp2 : Infinity;
88
+ if (ndp < minDp) {
89
+ return value.toFixed(minDp);
90
+ }
91
+ else if (ndp > maxDp) {
92
+ return value.toFixed(maxDp);
93
+ }
94
+ else {
95
+ return value.toString();
96
+ }
97
+ }
98
+ else {
99
+ return value.toString();
100
+ }
101
+ }
102
+ // format抽象方法
103
+ _format(numStr, unit) {
104
+ return `${numStr}${this.convert ? this.convert(unit) : unit}`;
105
+ }
106
+ _formatChain(chain, separator = this.separator) {
107
+ return chain.map(({ numStr, unit }) => this._format(numStr, unit)).join(separator);
108
+ }
109
+ // 将数字格式化为链式单位字符串
110
+ formatChain(num, separator = this.separator) {
111
+ const chain = this.getChainUnit(num);
112
+ return this._formatChain(chain, separator);
113
+ }
114
+ // 从给定字符串中分离出数字部分和单位
115
+ /**
116
+ * Splits a string into its numeric part and unit
117
+ *
118
+ * @param str - Input string containing a number followed by a unit
119
+ * @returns An object containing the numeric value, unit, and Decimal instance
120
+ * @throws An error if no predefined unit is matched
121
+ */
122
+ splitUnit(str) {
123
+ const sortedUnits = this.sortedUnitNames;
124
+ for (const unit of sortedUnits) {
125
+ const matchUnit = this.convert ? this.convert(unit) : unit;
126
+ if (str.endsWith(matchUnit)) {
127
+ const numStr = str.slice(0, -matchUnit.length);
128
+ const num = +numStr;
129
+ if (Number.isNaN(num))
130
+ throw new Error(`Invalid number: "${numStr}".`);
131
+ return {
132
+ num,
133
+ unit,
134
+ numStr,
135
+ };
136
+ }
137
+ }
138
+ throw new Error(`Undefined unit: "${str}".`);
139
+ }
140
+ // 从给定链式单位字符串中分离出数字部分和单位
141
+ /**
142
+ * Splits a string into its numeric part and unit
143
+ *
144
+ * @param str - Input string containing a number followed by a unit
145
+ * @returns An object containing the numeric value, unit, and Decimal instance
146
+ * @throws An error if no predefined unit is matched
147
+ */
148
+ splitChainUnit(str, separator = this.separator) {
149
+ const results = [];
150
+ const sortedUnits = this.sortedUnitNames;
151
+ const strLen = str.length;
152
+ let start = 0;
153
+ for (let i = 0; i < strLen; i++) {
154
+ for (const unit of sortedUnits) {
155
+ const matchUnit = this.convert ? this.convert(unit) : unit;
156
+ if (str.slice(i, i + matchUnit.length) === matchUnit) {
157
+ const numStr = str.slice(start, i);
158
+ const num = +numStr;
159
+ if (Number.isNaN(num))
160
+ throw new Error(`Invalid number: "${numStr}".`);
161
+ results.push({
162
+ num,
163
+ unit,
164
+ numStr,
165
+ });
166
+ i += matchUnit.length + separator.length;
167
+ start = i;
168
+ break;
169
+ }
170
+ }
171
+ }
172
+ if (results.length > 0)
173
+ return results;
174
+ throw new Error(`Undefined unit: "${str}".`);
175
+ }
176
+ }
177
+
178
+ const ERROR_NAN_INPUT = 'Accepting NaN as an argument may be unintentional and could lead to invalid results.';
179
+
180
+ exports.ERROR_NAN_INPUT = ERROR_NAN_INPUT;
181
+ exports.SmartUnitBase = SmartUnitBase;
@@ -0,0 +1,178 @@
1
+ class SmartUnitBase {
2
+ /** Accumulated digits for unit conversion */
3
+ get accumulatedDigits() {
4
+ if (!this._accumulatedDigits)
5
+ this.createAccumulatedDigits();
6
+ return this._accumulatedDigits;
7
+ }
8
+ /** Sorted unit names by length for efficient lookup */
9
+ get sortedUnitNames() {
10
+ if (!this._sortedUnitNames)
11
+ this.createSortedUnitNames();
12
+ return this._sortedUnitNames;
13
+ }
14
+ constructor(units, option = {}) {
15
+ this.unitNames = [];
16
+ this.unitDigits = [];
17
+ // Initialize
18
+ if (!units.length)
19
+ throw new Error('units is empty.');
20
+ this.threshold = option.threshold || 1;
21
+ this.fractionDigits = option.fractionDigits;
22
+ this.separator = option.separator || '';
23
+ if (option.baseDigit) {
24
+ for (let i = 0; i < units.length; i++) {
25
+ const name = units[i];
26
+ if (typeof name !== 'string')
27
+ throw new Error(`The unit setting is incorrect; the element at index [${i}] should be of string type.`);
28
+ }
29
+ this.unitNames = units;
30
+ this.unitDigits = Array(units.length - 1).fill(option.baseDigit);
31
+ }
32
+ else {
33
+ for (let i = 1; i < units.length; i += 2) {
34
+ const digit = units[i];
35
+ if (typeof digit !== 'number')
36
+ throw new Error(`The unit setting is incorrect; the element at index [${i}] should be of numeric type.`);
37
+ this.unitDigits.push(units[i]);
38
+ const name = units[i - 1];
39
+ if (typeof name !== 'string')
40
+ throw new Error(`The unit setting is incorrect; the element at index [${i - 1}] should be of string type.`);
41
+ this.unitNames.push(name);
42
+ }
43
+ this.unitNames.push(units[units.length - 1]);
44
+ }
45
+ }
46
+ withConvert(convert) {
47
+ const su = Object.create(this);
48
+ su.convert = convert;
49
+ return su;
50
+ }
51
+ // 累积比例
52
+ createAccumulatedDigits() {
53
+ const accumulatedDigits = [];
54
+ this.unitDigits.forEach((digit, index) => {
55
+ if (index === 0) {
56
+ accumulatedDigits.push(digit);
57
+ }
58
+ else {
59
+ accumulatedDigits.push(accumulatedDigits[index - 1] * digit);
60
+ }
61
+ });
62
+ this._accumulatedDigits = accumulatedDigits;
63
+ }
64
+ // 长度排序后的单位名称
65
+ createSortedUnitNames() {
66
+ const sortedUnits = [...this.unitNames].sort((a, b) => b.length - a.length);
67
+ this._sortedUnitNames = sortedUnits;
68
+ }
69
+ // 格式化数字的小数位数
70
+ /**
71
+ * Formats the decimal places of a number
72
+ *
73
+ * @param value - The value to format
74
+ * @param fractionDigits - Decimal precision configuration
75
+ * @returns The formatted string representation of the number
76
+ */
77
+ formatNumber(value, fractionDigits = this.fractionDigits) {
78
+ if (typeof fractionDigits === 'number') {
79
+ return value.toFixed(fractionDigits);
80
+ }
81
+ else if (typeof fractionDigits === 'string') {
82
+ const [dp1, dp2] = fractionDigits.split('-');
83
+ const ndp = (value.toString().split('.')[1] || '').length;
84
+ const minDp = dp1 ? +dp1 : -Infinity;
85
+ const maxDp = dp2 ? +dp2 : Infinity;
86
+ if (ndp < minDp) {
87
+ return value.toFixed(minDp);
88
+ }
89
+ else if (ndp > maxDp) {
90
+ return value.toFixed(maxDp);
91
+ }
92
+ else {
93
+ return value.toString();
94
+ }
95
+ }
96
+ else {
97
+ return value.toString();
98
+ }
99
+ }
100
+ // format抽象方法
101
+ _format(numStr, unit) {
102
+ return `${numStr}${this.convert ? this.convert(unit) : unit}`;
103
+ }
104
+ _formatChain(chain, separator = this.separator) {
105
+ return chain.map(({ numStr, unit }) => this._format(numStr, unit)).join(separator);
106
+ }
107
+ // 将数字格式化为链式单位字符串
108
+ formatChain(num, separator = this.separator) {
109
+ const chain = this.getChainUnit(num);
110
+ return this._formatChain(chain, separator);
111
+ }
112
+ // 从给定字符串中分离出数字部分和单位
113
+ /**
114
+ * Splits a string into its numeric part and unit
115
+ *
116
+ * @param str - Input string containing a number followed by a unit
117
+ * @returns An object containing the numeric value, unit, and Decimal instance
118
+ * @throws An error if no predefined unit is matched
119
+ */
120
+ splitUnit(str) {
121
+ const sortedUnits = this.sortedUnitNames;
122
+ for (const unit of sortedUnits) {
123
+ const matchUnit = this.convert ? this.convert(unit) : unit;
124
+ if (str.endsWith(matchUnit)) {
125
+ const numStr = str.slice(0, -matchUnit.length);
126
+ const num = +numStr;
127
+ if (Number.isNaN(num))
128
+ throw new Error(`Invalid number: "${numStr}".`);
129
+ return {
130
+ num,
131
+ unit,
132
+ numStr,
133
+ };
134
+ }
135
+ }
136
+ throw new Error(`Undefined unit: "${str}".`);
137
+ }
138
+ // 从给定链式单位字符串中分离出数字部分和单位
139
+ /**
140
+ * Splits a string into its numeric part and unit
141
+ *
142
+ * @param str - Input string containing a number followed by a unit
143
+ * @returns An object containing the numeric value, unit, and Decimal instance
144
+ * @throws An error if no predefined unit is matched
145
+ */
146
+ splitChainUnit(str, separator = this.separator) {
147
+ const results = [];
148
+ const sortedUnits = this.sortedUnitNames;
149
+ const strLen = str.length;
150
+ let start = 0;
151
+ for (let i = 0; i < strLen; i++) {
152
+ for (const unit of sortedUnits) {
153
+ const matchUnit = this.convert ? this.convert(unit) : unit;
154
+ if (str.slice(i, i + matchUnit.length) === matchUnit) {
155
+ const numStr = str.slice(start, i);
156
+ const num = +numStr;
157
+ if (Number.isNaN(num))
158
+ throw new Error(`Invalid number: "${numStr}".`);
159
+ results.push({
160
+ num,
161
+ unit,
162
+ numStr,
163
+ });
164
+ i += matchUnit.length + separator.length;
165
+ start = i;
166
+ break;
167
+ }
168
+ }
169
+ }
170
+ if (results.length > 0)
171
+ return results;
172
+ throw new Error(`Undefined unit: "${str}".`);
173
+ }
174
+ }
175
+
176
+ const ERROR_NAN_INPUT = 'Accepting NaN as an argument may be unintentional and could lead to invalid results.';
177
+
178
+ export { ERROR_NAN_INPUT as E, SmartUnitBase as S };
package/package.json CHANGED
@@ -1,48 +1,59 @@
1
1
  {
2
2
  "name": "smart-unit",
3
- "version": "1.0.5",
4
- "description": "Elegant unit conversion utility with automatic unit selection and high-precision support",
5
- "main": "dist/index.js",
6
- "module": "dist/index.esm.js",
7
- "exports": {
8
- ".": {
9
- "import": "./dist/index.esm.js",
10
- "require": "./dist/index.js",
11
- "types": "./dist/index.d.ts"
12
- }
3
+ "type": "module",
4
+ "version": "2.1.0",
5
+ "author": "flycran",
6
+ "scripts": {
7
+ "build": "rollup -c",
8
+ "test": "vitest run",
9
+ "test:watch": "vitest",
10
+ "test:performance": "node scripts/src/performance.ts",
11
+ "format": "biome format --fix .",
12
+ "docs:dev": "vitepress dev docs",
13
+ "docs:build": "vitepress build docs",
14
+ "docs:preview": "vitepress preview docs"
13
15
  },
14
- "types": "dist/index.d.ts",
15
16
  "repository": {
16
17
  "type": "git",
17
18
  "url": "https://github.com/flycran/smart-unit.git"
18
19
  },
19
- "homepage": "https://github.com/flycran/smart-unit#readme",
20
- "bugs": {
21
- "url": "https://github.com/flycran/smart-unit/issues"
22
- },
20
+ "main": "dist/index.cjs",
21
+ "module": "dist/index.mjs",
23
22
  "devDependencies": {
24
23
  "@biomejs/biome": "2.4.7",
25
24
  "@rollup/plugin-commonjs": "^28.0.3",
26
25
  "@rollup/plugin-node-resolve": "^16.0.1",
27
- "@rollup/plugin-typescript": "^12.1.2",
26
+ "@rollup/plugin-typescript": "^12.3.0",
28
27
  "rollup": "~4.30.1",
29
- "rollup-plugin-terser": "^7.0.2",
30
- "terser": "^5.39.0",
31
- "ts-node": "^10.9.1",
32
- "tslib": "^2.8.1",
33
28
  "typescript": "^5.8.3",
29
+ "vitepress": "^1.6.4",
34
30
  "vitest": "^4.1.0"
35
31
  },
32
+ "peerDependencies": {
33
+ "decimal.js": "^10.5.0"
34
+ },
35
+ "exports": {
36
+ ".": {
37
+ "types": "./dist/index.d.ts",
38
+ "import": "./dist/index.mjs",
39
+ "require": "./dist/index.cjs"
40
+ },
41
+ "./precision": {
42
+ "types": "./dist/precision.d.ts",
43
+ "import": "./dist/precision.mjs",
44
+ "require": "./dist/precision.cjs"
45
+ }
46
+ },
47
+ "bugs": {
48
+ "url": "https://github.com/flycran/smart-unit/issues"
49
+ },
50
+ "description": "Elegant unit conversion utility with automatic unit selection and high-precision support",
36
51
  "files": [
37
52
  "dist",
38
53
  "README.md",
39
54
  "README.zh-CN.md"
40
55
  ],
41
- "scripts": {
42
- "build": "rollup -c --configPlugin typescript",
43
- "test": "vitest run",
44
- "test:watch": "vitest"
45
- },
56
+ "homepage": "https://github.com/flycran/smart-unit#readme",
46
57
  "keywords": [
47
58
  "unit",
48
59
  "unit-conversion",
@@ -54,9 +65,6 @@
54
65
  "bigint",
55
66
  "typescript"
56
67
  ],
57
- "author": "flycran",
58
68
  "license": "MIT",
59
- "dependencies": {
60
- "decimal.js": "^10.5.0"
61
- }
62
- }
69
+ "types": "dist/index.d.ts"
70
+ }