uconvert 0.1.0 → 0.1.2
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 +153 -0
- package/dist/index.d.mts +10 -1
- package/dist/index.d.ts +10 -1
- package/dist/index.js +62 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +61 -0
- package/dist/index.mjs.map +1 -1
- package/package.json +10 -2
package/README.md
ADDED
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
# uconvert
|
|
2
|
+
|
|
3
|
+
Unit conversion utilities.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install uconvert
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
### `convert(value, options)`
|
|
14
|
+
|
|
15
|
+
Converts a numeric value from one unit to another.
|
|
16
|
+
|
|
17
|
+
**Parameters:**
|
|
18
|
+
|
|
19
|
+
- `value` (number) — The value in the source unit.
|
|
20
|
+
- `options` (object):
|
|
21
|
+
- `fromUnits` — Source unit (use `MetricUnits` or `ImperialUnits`).
|
|
22
|
+
- `toUnits` — Target unit. Must be the same dimension as `fromUnits` (e.g. length ↔ length), or an error is thrown.
|
|
23
|
+
- `roundTo` (optional) — Number of decimal places to round the result. Omit to return the unrounded value.
|
|
24
|
+
|
|
25
|
+
**Returns:** The value in the target unit (optionally rounded).
|
|
26
|
+
|
|
27
|
+
**Example:**
|
|
28
|
+
|
|
29
|
+
```ts
|
|
30
|
+
import { convert, MetricUnits, ImperialUnits } from "uconvert";
|
|
31
|
+
|
|
32
|
+
// 5 feet to meters, rounded to 2 decimals
|
|
33
|
+
convert(5, {
|
|
34
|
+
fromUnits: ImperialUnits.FT,
|
|
35
|
+
toUnits: MetricUnits.M,
|
|
36
|
+
roundTo: 2,
|
|
37
|
+
});
|
|
38
|
+
// => 1.52
|
|
39
|
+
|
|
40
|
+
// Same unit: returns value unchanged
|
|
41
|
+
convert(100, { fromUnits: MetricUnits.CM, toUnits: MetricUnits.CM });
|
|
42
|
+
// => 100
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### `round(value, decimalPlaces?)`
|
|
46
|
+
|
|
47
|
+
Rounds a number to a given number of decimal places.
|
|
48
|
+
|
|
49
|
+
**Parameters:**
|
|
50
|
+
|
|
51
|
+
- `value` (number) — The number to round.
|
|
52
|
+
- `decimalPlaces` (optional) — Number of digits after the decimal point. Omit to return the value unchanged.
|
|
53
|
+
|
|
54
|
+
**Returns:** The rounded number (or the original number if `decimalPlaces` is omitted).
|
|
55
|
+
|
|
56
|
+
**Example:**
|
|
57
|
+
|
|
58
|
+
```ts
|
|
59
|
+
import { round } from "uconvert";
|
|
60
|
+
|
|
61
|
+
round(1.2345, 2); // => 1.23
|
|
62
|
+
round(1.2345); // => 1.2345
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Exported types and enums
|
|
66
|
+
|
|
67
|
+
Use these with `convert` for type-safe unit arguments:
|
|
68
|
+
|
|
69
|
+
| Export | Description |
|
|
70
|
+
|--------|-------------|
|
|
71
|
+
| `ConvertOptions` | Options object for `convert`: `{ fromUnits, toUnits, roundTo? }`. |
|
|
72
|
+
| `Units` | Union type: `MetricUnits \| ImperialUnits`. |
|
|
73
|
+
| `MetricUnits` | Enum: `CM`, `M`, `KG`, `KM_H`. |
|
|
74
|
+
| `ImperialUnits` | Enum: `IN`, `FT`, `LB`, `MPH`. |
|
|
75
|
+
| `UnitSystem` | Enum: `METRIC`, `IMPERIAL`. |
|
|
76
|
+
| `Dimension` | Enum: `LENGTH`, `WEIGHT`, `SPEED`. |
|
|
77
|
+
|
|
78
|
+
`fromUnits` and `toUnits` must use the same dimension (e.g. both length, or both weight); otherwise `convert` throws.
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
## Height utility
|
|
83
|
+
|
|
84
|
+
The `height` object provides helpers for converting between centimeters and feet–inches and for parsing feet–inches strings.
|
|
85
|
+
|
|
86
|
+
**Import:**
|
|
87
|
+
|
|
88
|
+
```ts
|
|
89
|
+
import { height } from "uconvert";
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### `height.toFeetInches(valueInCm, roundTo?)`
|
|
93
|
+
|
|
94
|
+
Converts a height in centimeters to feet and inches.
|
|
95
|
+
|
|
96
|
+
**Parameters:**
|
|
97
|
+
|
|
98
|
+
- `valueInCm` (number) — Height in centimeters.
|
|
99
|
+
- `roundTo` (optional) — Number of decimal places for the inches part. Omit for unrounded.
|
|
100
|
+
|
|
101
|
+
**Returns:** A `FeetInches` tuple `[feet, inches]`.
|
|
102
|
+
|
|
103
|
+
**Example:**
|
|
104
|
+
|
|
105
|
+
```ts
|
|
106
|
+
height.toFeetInches(170); // => [5, 6.93...]
|
|
107
|
+
height.toFeetInches(170, 1); // => [5, 6.9]
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### `height.toCentimeters(feetInches)`
|
|
111
|
+
|
|
112
|
+
Converts a feet–inches tuple to centimeters.
|
|
113
|
+
|
|
114
|
+
**Parameters:**
|
|
115
|
+
|
|
116
|
+
- `feetInches` — A `FeetInches` tuple `[feet, inches]` (e.g. from `toFeetInches` or `parseFeetInches`).
|
|
117
|
+
|
|
118
|
+
**Returns:** Height in centimeters (number).
|
|
119
|
+
|
|
120
|
+
**Example:**
|
|
121
|
+
|
|
122
|
+
```ts
|
|
123
|
+
height.toCentimeters([5, 10]); // => 177.8
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### `height.parseFeetInches(input)`
|
|
127
|
+
|
|
128
|
+
Parses a string into a `[feet, inches]` tuple. Accepts formats like `"5 ft 10 in"`, `"5'10\""`, `"5 10"`, and variations with "feet"/"foot"/"inches"/"inch".
|
|
129
|
+
|
|
130
|
+
**Parameters:**
|
|
131
|
+
|
|
132
|
+
- `input` (string) — String to parse.
|
|
133
|
+
|
|
134
|
+
**Returns:** A `FeetInches` tuple `[feet, inches]`. Returns `[0, 0]` if parsing fails or input is not a string.
|
|
135
|
+
|
|
136
|
+
**Example:**
|
|
137
|
+
|
|
138
|
+
```ts
|
|
139
|
+
height.parseFeetInches("5 ft 10 in"); // => [5, 10]
|
|
140
|
+
height.parseFeetInches("5'10\""); // => [5, 10]
|
|
141
|
+
height.parseFeetInches("6 2"); // => [6, 2]
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### `FeetInches` type
|
|
145
|
+
|
|
146
|
+
Tuple type `[number, number]`: first element is feet, second is inches. Use it when passing or receiving values from `toFeetInches`, `toCentimeters`, and `parseFeetInches`.
|
|
147
|
+
|
|
148
|
+
```ts
|
|
149
|
+
import { height, type FeetInches } from "uconvert";
|
|
150
|
+
|
|
151
|
+
const fi: FeetInches = height.toFeetInches(170);
|
|
152
|
+
height.toCentimeters(fi);
|
|
153
|
+
```
|
package/dist/index.d.mts
CHANGED
|
@@ -38,4 +38,13 @@ declare const convert: (value: number, { fromUnits, toUnits, roundTo }: ConvertO
|
|
|
38
38
|
|
|
39
39
|
declare const round: (value: number, decimalPlaces?: number) => number;
|
|
40
40
|
|
|
41
|
-
|
|
41
|
+
type FeetInches = [number, number];
|
|
42
|
+
|
|
43
|
+
declare class Height {
|
|
44
|
+
toFeetInches(valueInCm: number, roundTo?: number): FeetInches;
|
|
45
|
+
toCentimeters([feet, inches]: FeetInches): number;
|
|
46
|
+
parseFeetInches(input: string): FeetInches;
|
|
47
|
+
}
|
|
48
|
+
declare const height: Height;
|
|
49
|
+
|
|
50
|
+
export { type ConvertOptions, Dimension, ImperialUnits, MeasurementType, MetricUnits, UnitSystem, type Units, convert, height, round };
|
package/dist/index.d.ts
CHANGED
|
@@ -38,4 +38,13 @@ declare const convert: (value: number, { fromUnits, toUnits, roundTo }: ConvertO
|
|
|
38
38
|
|
|
39
39
|
declare const round: (value: number, decimalPlaces?: number) => number;
|
|
40
40
|
|
|
41
|
-
|
|
41
|
+
type FeetInches = [number, number];
|
|
42
|
+
|
|
43
|
+
declare class Height {
|
|
44
|
+
toFeetInches(valueInCm: number, roundTo?: number): FeetInches;
|
|
45
|
+
toCentimeters([feet, inches]: FeetInches): number;
|
|
46
|
+
parseFeetInches(input: string): FeetInches;
|
|
47
|
+
}
|
|
48
|
+
declare const height: Height;
|
|
49
|
+
|
|
50
|
+
export { type ConvertOptions, Dimension, ImperialUnits, MeasurementType, MetricUnits, UnitSystem, type Units, convert, height, round };
|
package/dist/index.js
CHANGED
|
@@ -26,6 +26,7 @@ __export(index_exports, {
|
|
|
26
26
|
MetricUnits: () => MetricUnits,
|
|
27
27
|
UnitSystem: () => UnitSystem,
|
|
28
28
|
convert: () => convert,
|
|
29
|
+
height: () => height_default,
|
|
29
30
|
round: () => round
|
|
30
31
|
});
|
|
31
32
|
module.exports = __toCommonJS(index_exports);
|
|
@@ -139,6 +140,66 @@ var convert = (value, { fromUnits, toUnits, roundTo }) => {
|
|
|
139
140
|
const factor = getFactor2(fromUnits, toUnits);
|
|
140
141
|
return round(value * factor, roundTo);
|
|
141
142
|
};
|
|
143
|
+
|
|
144
|
+
// src/services/height/height.utils.ts
|
|
145
|
+
var parseFeetInches = (input) => {
|
|
146
|
+
if (typeof input !== "string") return [0, 0];
|
|
147
|
+
const normalized = input.toLowerCase().replace(/[""]/g, "in").replace(/[''′]+/g, "ft").replace(/(feet|foot)/g, "ft").replace(/(inches|inch)/g, "in").replace(/[\s]+/g, " ").trim();
|
|
148
|
+
const parseNumber = (value) => parseFloat(value || "0");
|
|
149
|
+
const ftMatch = normalized.match(/([\d.]+)\s*ft/);
|
|
150
|
+
const inMatch = normalized.match(/([\d.]+)\s*in/);
|
|
151
|
+
const feet = parseNumber(ftMatch?.[1]);
|
|
152
|
+
const inches = parseNumber(inMatch?.[1]);
|
|
153
|
+
if (ftMatch && inMatch) {
|
|
154
|
+
return [feet, inches];
|
|
155
|
+
}
|
|
156
|
+
const [firstNumberString, secondNumberString] = normalized.match(
|
|
157
|
+
/[\d.]+/g
|
|
158
|
+
) || ["0", "0"];
|
|
159
|
+
const firstNumber = parseNumber(firstNumberString);
|
|
160
|
+
const secondNumber = parseNumber(secondNumberString);
|
|
161
|
+
if (!ftMatch && !inMatch) {
|
|
162
|
+
return [firstNumber, secondNumber];
|
|
163
|
+
}
|
|
164
|
+
if (ftMatch && !inMatch) {
|
|
165
|
+
return [feet, secondNumber];
|
|
166
|
+
}
|
|
167
|
+
if (!ftMatch && inMatch) {
|
|
168
|
+
return [0, inches];
|
|
169
|
+
}
|
|
170
|
+
return [0, 0];
|
|
171
|
+
};
|
|
172
|
+
var heightUtils = {
|
|
173
|
+
parseFeetInches
|
|
174
|
+
};
|
|
175
|
+
var height_utils_default = heightUtils;
|
|
176
|
+
|
|
177
|
+
// src/services/height/height.ts
|
|
178
|
+
var { parseFeetInches: parseFeetInches2 } = height_utils_default;
|
|
179
|
+
var Height = class {
|
|
180
|
+
toFeetInches(valueInCm, roundTo) {
|
|
181
|
+
const totalInches = convert(valueInCm, {
|
|
182
|
+
fromUnits: "cm" /* CM */,
|
|
183
|
+
toUnits: "in" /* IN */,
|
|
184
|
+
roundTo
|
|
185
|
+
});
|
|
186
|
+
const feet = Math.floor(totalInches / 12);
|
|
187
|
+
const inches = round(totalInches - feet * 12, roundTo);
|
|
188
|
+
return [feet, inches];
|
|
189
|
+
}
|
|
190
|
+
toCentimeters([feet, inches]) {
|
|
191
|
+
const totalInches = feet * 12 + inches;
|
|
192
|
+
return convert(totalInches, {
|
|
193
|
+
fromUnits: "in" /* IN */,
|
|
194
|
+
toUnits: "cm" /* CM */
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
parseFeetInches(input) {
|
|
198
|
+
return parseFeetInches2(input);
|
|
199
|
+
}
|
|
200
|
+
};
|
|
201
|
+
var height = new Height();
|
|
202
|
+
var height_default = height;
|
|
142
203
|
// Annotate the CommonJS export names for ESM import in node:
|
|
143
204
|
0 && (module.exports = {
|
|
144
205
|
Dimension,
|
|
@@ -147,6 +208,7 @@ var convert = (value, { fromUnits, toUnits, roundTo }) => {
|
|
|
147
208
|
MetricUnits,
|
|
148
209
|
UnitSystem,
|
|
149
210
|
convert,
|
|
211
|
+
height,
|
|
150
212
|
round
|
|
151
213
|
});
|
|
152
214
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/constants/common/common.constants.ts","../src/utils/math/math.ts","../src/constants/conversion/conversion.constants.ts","../src/constants/strings/strings.ts","../src/utils/strings/strings.utils.ts","../src/utils/convert/convert.utils.ts","../src/utils/convert/convert.ts"],"sourcesContent":["export * from \"./constants/common/common.constants\";\nexport * from \"./utils/convert/convert\";\nexport * from \"./utils/math/math\";\n","export enum UnitSystem {\n METRIC = \"Si\",\n IMPERIAL = \"Imperial\",\n}\n\nexport enum Dimension {\n LENGTH = \"length\",\n WEIGHT = \"weight\",\n SPEED = \"speed\",\n}\n\nexport enum MeasurementType {\n LENGTH = \"length\",\n WEIGHT = \"weight\",\n SPEED = \"speed\",\n HEIGHT = \"height\",\n LENGTH_FEET = \"length_feet\",\n}\n\nexport enum MetricUnits {\n CM = \"cm\",\n M = \"m\",\n KG = \"kg\",\n KM_H = \"km/h\",\n}\n\nexport enum ImperialUnits {\n IN = \"in\",\n FT = \"ft\",\n LB = \"lb\",\n MPH = \"mph\",\n}\n\nexport type Units = MetricUnits | ImperialUnits;\n","export const round = (value: number, decimalPlaces?: number) => {\n if (decimalPlaces === undefined) return value;\n\n return parseFloat(value.toFixed(decimalPlaces));\n};\n","import {\n Dimension,\n ImperialUnits,\n MetricUnits,\n Units,\n} from \"../common/common.constants\";\n\n/** Factor to multiply value by to get value in canonical unit for that dimension. */\nexport const UNIT_TO_CANONICAL: Record<Units, number> = {\n [MetricUnits.CM]: 1,\n [MetricUnits.M]: 100,\n [ImperialUnits.IN]: 2.54,\n [ImperialUnits.FT]: 30.48,\n [MetricUnits.KG]: 1,\n [ImperialUnits.LB]: 0.45359237,\n [MetricUnits.KM_H]: 1,\n [ImperialUnits.MPH]: 1.609344,\n};\n\nexport const UNIT_DIMENSION: Record<Units, Dimension> = {\n [MetricUnits.CM]: Dimension.LENGTH,\n [MetricUnits.M]: Dimension.LENGTH,\n [ImperialUnits.IN]: Dimension.LENGTH,\n [ImperialUnits.FT]: Dimension.LENGTH,\n [MetricUnits.KG]: Dimension.WEIGHT,\n [ImperialUnits.LB]: Dimension.WEIGHT,\n [MetricUnits.KM_H]: Dimension.SPEED,\n [ImperialUnits.MPH]: Dimension.SPEED,\n};\n","const strings = {\n convertDimensionMismatch:\n \"Cannot convert between different dimensions: {0} ({1}) and {2} ({3})\",\n};\n\nexport default strings;\n","export const formatMessage = (message: string, ...args: any[]) =>\n message.replace(/{(\\d+)}/g, (match, number) =>\n args[number] !== undefined ? args[number] : match,\n );\n","import { Units } from \"../../constants/common/common.constants\";\nimport {\n UNIT_DIMENSION,\n UNIT_TO_CANONICAL,\n} from \"../../constants/conversion/conversion.constants\";\nimport strings from \"../../constants/strings/strings\";\nimport { round } from \"../math/math\";\nimport { formatMessage } from \"../strings/strings.utils\";\nimport { ConvertOptions } from \"./convert.types\";\n\nconst throwConversionError = ({ fromUnits, toUnits }: ConvertOptions) => {\n const fromDim = UNIT_DIMENSION[fromUnits];\n const toDim = UNIT_DIMENSION[toUnits];\n\n throw new Error(\n formatMessage(\n strings.convertDimensionMismatch,\n fromUnits,\n fromDim,\n toUnits,\n toDim,\n ),\n );\n};\n\nconst getFactor = (fromUnits: Units, toUnits: Units) => {\n if (fromUnits === toUnits) return 1;\n\n const fromDim = UNIT_DIMENSION[fromUnits];\n const toDim = UNIT_DIMENSION[toUnits];\n\n if (fromDim !== toDim) throwConversionError({ fromUnits, toUnits });\n\n const toCanonicalFrom = UNIT_TO_CANONICAL[fromUnits];\n const toCanonicalTo = UNIT_TO_CANONICAL[toUnits];\n return toCanonicalFrom / toCanonicalTo;\n};\n\nconst convertUtils = {\n getFactor,\n};\n\nexport default convertUtils;\n","import { round } from \"../math/math\";\nimport { ConvertOptions } from \"./convert.types\";\nimport utils from \"./convert.utils\";\n\nconst { getFactor } = utils;\n\nexport const convert = (\n value: number,\n { fromUnits, toUnits, roundTo }: ConvertOptions,\n) => {\n const factor = getFactor(fromUnits, toUnits);\n\n return round(value * factor, roundTo);\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAO,IAAK,aAAL,kBAAKA,gBAAL;AACL,EAAAA,YAAA,YAAS;AACT,EAAAA,YAAA,cAAW;AAFD,SAAAA;AAAA,GAAA;AAKL,IAAK,YAAL,kBAAKC,eAAL;AACL,EAAAA,WAAA,YAAS;AACT,EAAAA,WAAA,YAAS;AACT,EAAAA,WAAA,WAAQ;AAHE,SAAAA;AAAA,GAAA;AAML,IAAK,kBAAL,kBAAKC,qBAAL;AACL,EAAAA,iBAAA,YAAS;AACT,EAAAA,iBAAA,YAAS;AACT,EAAAA,iBAAA,WAAQ;AACR,EAAAA,iBAAA,YAAS;AACT,EAAAA,iBAAA,iBAAc;AALJ,SAAAA;AAAA,GAAA;AAQL,IAAK,cAAL,kBAAKC,iBAAL;AACL,EAAAA,aAAA,QAAK;AACL,EAAAA,aAAA,OAAI;AACJ,EAAAA,aAAA,QAAK;AACL,EAAAA,aAAA,UAAO;AAJG,SAAAA;AAAA,GAAA;AAOL,IAAK,gBAAL,kBAAKC,mBAAL;AACL,EAAAA,eAAA,QAAK;AACL,EAAAA,eAAA,QAAK;AACL,EAAAA,eAAA,QAAK;AACL,EAAAA,eAAA,SAAM;AAJI,SAAAA;AAAA,GAAA;;;AC1BL,IAAM,QAAQ,CAAC,OAAe,kBAA2B;AAC9D,MAAI,kBAAkB,OAAW,QAAO;AAExC,SAAO,WAAW,MAAM,QAAQ,aAAa,CAAC;AAChD;;;ACIO,IAAM,oBAA2C;AAAA,EACtD,cAAe,GAAG;AAAA,EAClB,YAAc,GAAG;AAAA,EACjB,cAAiB,GAAG;AAAA,EACpB,cAAiB,GAAG;AAAA,EACpB,cAAe,GAAG;AAAA,EAClB,cAAiB,GAAG;AAAA,EACpB,kBAAiB,GAAG;AAAA,EACpB,gBAAkB,GAAG;AACvB;AAEO,IAAM,iBAA2C;AAAA,EACtD,cAAe;AAAA,EACf,YAAc;AAAA,EACd,cAAiB;AAAA,EACjB,cAAiB;AAAA,EACjB,cAAe;AAAA,EACf,cAAiB;AAAA,EACjB,kBAAiB;AAAA,EACjB,gBAAkB;AACpB;;;AC5BA,IAAM,UAAU;AAAA,EACd,0BACE;AACJ;AAEA,IAAO,kBAAQ;;;ACLR,IAAM,gBAAgB,CAAC,YAAoB,SAChD,QAAQ;AAAA,EAAQ;AAAA,EAAY,CAAC,OAAO,WAClC,KAAK,MAAM,MAAM,SAAY,KAAK,MAAM,IAAI;AAC9C;;;ACOF,IAAM,uBAAuB,CAAC,EAAE,WAAW,QAAQ,MAAsB;AACvE,QAAM,UAAU,eAAe,SAAS;AACxC,QAAM,QAAQ,eAAe,OAAO;AAEpC,QAAM,IAAI;AAAA,IACR;AAAA,MACE,gBAAQ;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;AAEA,IAAM,YAAY,CAAC,WAAkB,YAAmB;AACtD,MAAI,cAAc,QAAS,QAAO;AAElC,QAAM,UAAU,eAAe,SAAS;AACxC,QAAM,QAAQ,eAAe,OAAO;AAEpC,MAAI,YAAY,MAAO,sBAAqB,EAAE,WAAW,QAAQ,CAAC;AAElE,QAAM,kBAAkB,kBAAkB,SAAS;AACnD,QAAM,gBAAgB,kBAAkB,OAAO;AAC/C,SAAO,kBAAkB;AAC3B;AAEA,IAAM,eAAe;AAAA,EACnB;AACF;AAEA,IAAO,wBAAQ;;;ACtCf,IAAM,EAAE,WAAAC,WAAU,IAAI;AAEf,IAAM,UAAU,CACrB,OACA,EAAE,WAAW,SAAS,QAAQ,MAC3B;AACH,QAAM,SAASA,WAAU,WAAW,OAAO;AAE3C,SAAO,MAAM,QAAQ,QAAQ,OAAO;AACtC;","names":["UnitSystem","Dimension","MeasurementType","MetricUnits","ImperialUnits","getFactor"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/constants/common/common.constants.ts","../src/utils/math/math.ts","../src/constants/conversion/conversion.constants.ts","../src/constants/strings/strings.ts","../src/utils/strings/strings.utils.ts","../src/utils/convert/convert.utils.ts","../src/utils/convert/convert.ts","../src/services/height/height.utils.ts","../src/services/height/height.ts"],"sourcesContent":["export * from \"./constants/common/common.constants\";\nexport * from \"./utils/convert/convert\";\nexport * from \"./utils/convert/convert.types\";\nexport * from \"./utils/math/math\";\n\nexport { default as height } from \"./services/height/height\";\n","export enum UnitSystem {\n METRIC = \"Si\",\n IMPERIAL = \"Imperial\",\n}\n\nexport enum Dimension {\n LENGTH = \"length\",\n WEIGHT = \"weight\",\n SPEED = \"speed\",\n}\n\nexport enum MeasurementType {\n LENGTH = \"length\",\n WEIGHT = \"weight\",\n SPEED = \"speed\",\n HEIGHT = \"height\",\n LENGTH_FEET = \"length_feet\",\n}\n\nexport enum MetricUnits {\n CM = \"cm\",\n M = \"m\",\n KG = \"kg\",\n KM_H = \"km/h\",\n}\n\nexport enum ImperialUnits {\n IN = \"in\",\n FT = \"ft\",\n LB = \"lb\",\n MPH = \"mph\",\n}\n\nexport type Units = MetricUnits | ImperialUnits;\n","export const round = (value: number, decimalPlaces?: number) => {\n if (decimalPlaces === undefined) return value;\n\n return parseFloat(value.toFixed(decimalPlaces));\n};\n","import {\n Dimension,\n ImperialUnits,\n MetricUnits,\n Units,\n} from \"../common/common.constants\";\n\n/** Factor to multiply value by to get value in canonical unit for that dimension. */\nexport const UNIT_TO_CANONICAL: Record<Units, number> = {\n [MetricUnits.CM]: 1,\n [MetricUnits.M]: 100,\n [ImperialUnits.IN]: 2.54,\n [ImperialUnits.FT]: 30.48,\n [MetricUnits.KG]: 1,\n [ImperialUnits.LB]: 0.45359237,\n [MetricUnits.KM_H]: 1,\n [ImperialUnits.MPH]: 1.609344,\n};\n\nexport const UNIT_DIMENSION: Record<Units, Dimension> = {\n [MetricUnits.CM]: Dimension.LENGTH,\n [MetricUnits.M]: Dimension.LENGTH,\n [ImperialUnits.IN]: Dimension.LENGTH,\n [ImperialUnits.FT]: Dimension.LENGTH,\n [MetricUnits.KG]: Dimension.WEIGHT,\n [ImperialUnits.LB]: Dimension.WEIGHT,\n [MetricUnits.KM_H]: Dimension.SPEED,\n [ImperialUnits.MPH]: Dimension.SPEED,\n};\n","const strings = {\n convertDimensionMismatch:\n \"Cannot convert between different dimensions: {0} ({1}) and {2} ({3})\",\n};\n\nexport default strings;\n","export const formatMessage = (message: string, ...args: any[]) =>\n message.replace(/{(\\d+)}/g, (match, number) =>\n args[number] !== undefined ? args[number] : match,\n );\n","import { Units } from \"../../constants/common/common.constants\";\nimport {\n UNIT_DIMENSION,\n UNIT_TO_CANONICAL,\n} from \"../../constants/conversion/conversion.constants\";\nimport strings from \"../../constants/strings/strings\";\nimport { round } from \"../math/math\";\nimport { formatMessage } from \"../strings/strings.utils\";\nimport { ConvertOptions } from \"./convert.types\";\n\nconst throwConversionError = ({ fromUnits, toUnits }: ConvertOptions) => {\n const fromDim = UNIT_DIMENSION[fromUnits];\n const toDim = UNIT_DIMENSION[toUnits];\n\n throw new Error(\n formatMessage(\n strings.convertDimensionMismatch,\n fromUnits,\n fromDim,\n toUnits,\n toDim,\n ),\n );\n};\n\nconst getFactor = (fromUnits: Units, toUnits: Units) => {\n if (fromUnits === toUnits) return 1;\n\n const fromDim = UNIT_DIMENSION[fromUnits];\n const toDim = UNIT_DIMENSION[toUnits];\n\n if (fromDim !== toDim) throwConversionError({ fromUnits, toUnits });\n\n const toCanonicalFrom = UNIT_TO_CANONICAL[fromUnits];\n const toCanonicalTo = UNIT_TO_CANONICAL[toUnits];\n return toCanonicalFrom / toCanonicalTo;\n};\n\nconst convertUtils = {\n getFactor,\n};\n\nexport default convertUtils;\n","import { round } from \"../math/math\";\nimport { ConvertOptions } from \"./convert.types\";\nimport utils from \"./convert.utils\";\n\nconst { getFactor } = utils;\n\nexport const convert = (\n value: number,\n { fromUnits, toUnits, roundTo }: ConvertOptions,\n) => {\n const factor = getFactor(fromUnits, toUnits);\n\n return round(value * factor, roundTo);\n};\n","import { FeetInches } from \"./height.types\";\n\nconst parseFeetInches = (input: string): FeetInches => {\n // NOTE: this function is AI generated, but it's well tested and works as expected. And it's covered by unit tests.\n if (typeof input !== \"string\") return [0, 0];\n\n const normalized = input\n .toLowerCase()\n .replace(/[\"\"]/g, \"in\")\n .replace(/[''′]+/g, \"ft\")\n .replace(/(feet|foot)/g, \"ft\")\n .replace(/(inches|inch)/g, \"in\")\n .replace(/[\\s]+/g, \" \")\n .trim();\n\n const parseNumber = (value: string | undefined): number =>\n parseFloat(value || \"0\");\n\n const ftMatch = normalized.match(/([\\d.]+)\\s*ft/);\n const inMatch = normalized.match(/([\\d.]+)\\s*in/);\n\n const feet = parseNumber(ftMatch?.[1]);\n const inches = parseNumber(inMatch?.[1]);\n\n if (ftMatch && inMatch) {\n return [feet, inches];\n }\n\n const [firstNumberString, secondNumberString] = normalized.match(\n /[\\d.]+/g,\n ) || [\"0\", \"0\"];\n\n const firstNumber = parseNumber(firstNumberString);\n const secondNumber = parseNumber(secondNumberString);\n\n if (!ftMatch && !inMatch) {\n return [firstNumber, secondNumber];\n }\n\n if (ftMatch && !inMatch) {\n return [feet, secondNumber];\n }\n\n if (!ftMatch && inMatch) {\n return [0, inches];\n }\n\n return [0, 0];\n};\n\nconst heightUtils = {\n parseFeetInches,\n};\n\nexport default heightUtils;\n","import {\n ImperialUnits,\n MetricUnits,\n} from \"../../constants/common/common.constants\";\nimport { convert } from \"../../utils/convert/convert\";\nimport { round } from \"../../utils/math/math\";\nimport { FeetInches } from \"./height.types\";\nimport utils from \"./height.utils\";\n\nconst { parseFeetInches } = utils;\n\nclass Height {\n toFeetInches(valueInCm: number, roundTo?: number): FeetInches {\n const totalInches = convert(valueInCm, {\n fromUnits: MetricUnits.CM,\n toUnits: ImperialUnits.IN,\n roundTo,\n });\n\n const feet = Math.floor(totalInches / 12);\n const inches = round(totalInches - feet * 12, roundTo);\n\n return [feet, inches];\n }\n\n toCentimeters([feet, inches]: FeetInches): number {\n const totalInches = feet * 12 + inches;\n\n return convert(totalInches, {\n fromUnits: ImperialUnits.IN,\n toUnits: MetricUnits.CM,\n });\n }\n\n parseFeetInches(input: string): FeetInches {\n return parseFeetInches(input);\n }\n}\n\nconst height = new Height();\n\nexport default height;\n"],"mappings":"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","names":["UnitSystem","Dimension","MeasurementType","MetricUnits","ImperialUnits","getFactor","parseFeetInches"]}
|
package/dist/index.mjs
CHANGED
|
@@ -107,6 +107,66 @@ var convert = (value, { fromUnits, toUnits, roundTo }) => {
|
|
|
107
107
|
const factor = getFactor2(fromUnits, toUnits);
|
|
108
108
|
return round(value * factor, roundTo);
|
|
109
109
|
};
|
|
110
|
+
|
|
111
|
+
// src/services/height/height.utils.ts
|
|
112
|
+
var parseFeetInches = (input) => {
|
|
113
|
+
if (typeof input !== "string") return [0, 0];
|
|
114
|
+
const normalized = input.toLowerCase().replace(/[""]/g, "in").replace(/[''′]+/g, "ft").replace(/(feet|foot)/g, "ft").replace(/(inches|inch)/g, "in").replace(/[\s]+/g, " ").trim();
|
|
115
|
+
const parseNumber = (value) => parseFloat(value || "0");
|
|
116
|
+
const ftMatch = normalized.match(/([\d.]+)\s*ft/);
|
|
117
|
+
const inMatch = normalized.match(/([\d.]+)\s*in/);
|
|
118
|
+
const feet = parseNumber(ftMatch?.[1]);
|
|
119
|
+
const inches = parseNumber(inMatch?.[1]);
|
|
120
|
+
if (ftMatch && inMatch) {
|
|
121
|
+
return [feet, inches];
|
|
122
|
+
}
|
|
123
|
+
const [firstNumberString, secondNumberString] = normalized.match(
|
|
124
|
+
/[\d.]+/g
|
|
125
|
+
) || ["0", "0"];
|
|
126
|
+
const firstNumber = parseNumber(firstNumberString);
|
|
127
|
+
const secondNumber = parseNumber(secondNumberString);
|
|
128
|
+
if (!ftMatch && !inMatch) {
|
|
129
|
+
return [firstNumber, secondNumber];
|
|
130
|
+
}
|
|
131
|
+
if (ftMatch && !inMatch) {
|
|
132
|
+
return [feet, secondNumber];
|
|
133
|
+
}
|
|
134
|
+
if (!ftMatch && inMatch) {
|
|
135
|
+
return [0, inches];
|
|
136
|
+
}
|
|
137
|
+
return [0, 0];
|
|
138
|
+
};
|
|
139
|
+
var heightUtils = {
|
|
140
|
+
parseFeetInches
|
|
141
|
+
};
|
|
142
|
+
var height_utils_default = heightUtils;
|
|
143
|
+
|
|
144
|
+
// src/services/height/height.ts
|
|
145
|
+
var { parseFeetInches: parseFeetInches2 } = height_utils_default;
|
|
146
|
+
var Height = class {
|
|
147
|
+
toFeetInches(valueInCm, roundTo) {
|
|
148
|
+
const totalInches = convert(valueInCm, {
|
|
149
|
+
fromUnits: "cm" /* CM */,
|
|
150
|
+
toUnits: "in" /* IN */,
|
|
151
|
+
roundTo
|
|
152
|
+
});
|
|
153
|
+
const feet = Math.floor(totalInches / 12);
|
|
154
|
+
const inches = round(totalInches - feet * 12, roundTo);
|
|
155
|
+
return [feet, inches];
|
|
156
|
+
}
|
|
157
|
+
toCentimeters([feet, inches]) {
|
|
158
|
+
const totalInches = feet * 12 + inches;
|
|
159
|
+
return convert(totalInches, {
|
|
160
|
+
fromUnits: "in" /* IN */,
|
|
161
|
+
toUnits: "cm" /* CM */
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
parseFeetInches(input) {
|
|
165
|
+
return parseFeetInches2(input);
|
|
166
|
+
}
|
|
167
|
+
};
|
|
168
|
+
var height = new Height();
|
|
169
|
+
var height_default = height;
|
|
110
170
|
export {
|
|
111
171
|
Dimension,
|
|
112
172
|
ImperialUnits,
|
|
@@ -114,6 +174,7 @@ export {
|
|
|
114
174
|
MetricUnits,
|
|
115
175
|
UnitSystem,
|
|
116
176
|
convert,
|
|
177
|
+
height_default as height,
|
|
117
178
|
round
|
|
118
179
|
};
|
|
119
180
|
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/constants/common/common.constants.ts","../src/utils/math/math.ts","../src/constants/conversion/conversion.constants.ts","../src/constants/strings/strings.ts","../src/utils/strings/strings.utils.ts","../src/utils/convert/convert.utils.ts","../src/utils/convert/convert.ts"],"sourcesContent":["export enum UnitSystem {\n METRIC = \"Si\",\n IMPERIAL = \"Imperial\",\n}\n\nexport enum Dimension {\n LENGTH = \"length\",\n WEIGHT = \"weight\",\n SPEED = \"speed\",\n}\n\nexport enum MeasurementType {\n LENGTH = \"length\",\n WEIGHT = \"weight\",\n SPEED = \"speed\",\n HEIGHT = \"height\",\n LENGTH_FEET = \"length_feet\",\n}\n\nexport enum MetricUnits {\n CM = \"cm\",\n M = \"m\",\n KG = \"kg\",\n KM_H = \"km/h\",\n}\n\nexport enum ImperialUnits {\n IN = \"in\",\n FT = \"ft\",\n LB = \"lb\",\n MPH = \"mph\",\n}\n\nexport type Units = MetricUnits | ImperialUnits;\n","export const round = (value: number, decimalPlaces?: number) => {\n if (decimalPlaces === undefined) return value;\n\n return parseFloat(value.toFixed(decimalPlaces));\n};\n","import {\n Dimension,\n ImperialUnits,\n MetricUnits,\n Units,\n} from \"../common/common.constants\";\n\n/** Factor to multiply value by to get value in canonical unit for that dimension. */\nexport const UNIT_TO_CANONICAL: Record<Units, number> = {\n [MetricUnits.CM]: 1,\n [MetricUnits.M]: 100,\n [ImperialUnits.IN]: 2.54,\n [ImperialUnits.FT]: 30.48,\n [MetricUnits.KG]: 1,\n [ImperialUnits.LB]: 0.45359237,\n [MetricUnits.KM_H]: 1,\n [ImperialUnits.MPH]: 1.609344,\n};\n\nexport const UNIT_DIMENSION: Record<Units, Dimension> = {\n [MetricUnits.CM]: Dimension.LENGTH,\n [MetricUnits.M]: Dimension.LENGTH,\n [ImperialUnits.IN]: Dimension.LENGTH,\n [ImperialUnits.FT]: Dimension.LENGTH,\n [MetricUnits.KG]: Dimension.WEIGHT,\n [ImperialUnits.LB]: Dimension.WEIGHT,\n [MetricUnits.KM_H]: Dimension.SPEED,\n [ImperialUnits.MPH]: Dimension.SPEED,\n};\n","const strings = {\n convertDimensionMismatch:\n \"Cannot convert between different dimensions: {0} ({1}) and {2} ({3})\",\n};\n\nexport default strings;\n","export const formatMessage = (message: string, ...args: any[]) =>\n message.replace(/{(\\d+)}/g, (match, number) =>\n args[number] !== undefined ? args[number] : match,\n );\n","import { Units } from \"../../constants/common/common.constants\";\nimport {\n UNIT_DIMENSION,\n UNIT_TO_CANONICAL,\n} from \"../../constants/conversion/conversion.constants\";\nimport strings from \"../../constants/strings/strings\";\nimport { round } from \"../math/math\";\nimport { formatMessage } from \"../strings/strings.utils\";\nimport { ConvertOptions } from \"./convert.types\";\n\nconst throwConversionError = ({ fromUnits, toUnits }: ConvertOptions) => {\n const fromDim = UNIT_DIMENSION[fromUnits];\n const toDim = UNIT_DIMENSION[toUnits];\n\n throw new Error(\n formatMessage(\n strings.convertDimensionMismatch,\n fromUnits,\n fromDim,\n toUnits,\n toDim,\n ),\n );\n};\n\nconst getFactor = (fromUnits: Units, toUnits: Units) => {\n if (fromUnits === toUnits) return 1;\n\n const fromDim = UNIT_DIMENSION[fromUnits];\n const toDim = UNIT_DIMENSION[toUnits];\n\n if (fromDim !== toDim) throwConversionError({ fromUnits, toUnits });\n\n const toCanonicalFrom = UNIT_TO_CANONICAL[fromUnits];\n const toCanonicalTo = UNIT_TO_CANONICAL[toUnits];\n return toCanonicalFrom / toCanonicalTo;\n};\n\nconst convertUtils = {\n getFactor,\n};\n\nexport default convertUtils;\n","import { round } from \"../math/math\";\nimport { ConvertOptions } from \"./convert.types\";\nimport utils from \"./convert.utils\";\n\nconst { getFactor } = utils;\n\nexport const convert = (\n value: number,\n { fromUnits, toUnits, roundTo }: ConvertOptions,\n) => {\n const factor = getFactor(fromUnits, toUnits);\n\n return round(value * factor, roundTo);\n};\n"],"mappings":";AAAO,IAAK,aAAL,kBAAKA,gBAAL;AACL,EAAAA,YAAA,YAAS;AACT,EAAAA,YAAA,cAAW;AAFD,SAAAA;AAAA,GAAA;AAKL,IAAK,YAAL,kBAAKC,eAAL;AACL,EAAAA,WAAA,YAAS;AACT,EAAAA,WAAA,YAAS;AACT,EAAAA,WAAA,WAAQ;AAHE,SAAAA;AAAA,GAAA;AAML,IAAK,kBAAL,kBAAKC,qBAAL;AACL,EAAAA,iBAAA,YAAS;AACT,EAAAA,iBAAA,YAAS;AACT,EAAAA,iBAAA,WAAQ;AACR,EAAAA,iBAAA,YAAS;AACT,EAAAA,iBAAA,iBAAc;AALJ,SAAAA;AAAA,GAAA;AAQL,IAAK,cAAL,kBAAKC,iBAAL;AACL,EAAAA,aAAA,QAAK;AACL,EAAAA,aAAA,OAAI;AACJ,EAAAA,aAAA,QAAK;AACL,EAAAA,aAAA,UAAO;AAJG,SAAAA;AAAA,GAAA;AAOL,IAAK,gBAAL,kBAAKC,mBAAL;AACL,EAAAA,eAAA,QAAK;AACL,EAAAA,eAAA,QAAK;AACL,EAAAA,eAAA,QAAK;AACL,EAAAA,eAAA,SAAM;AAJI,SAAAA;AAAA,GAAA;;;AC1BL,IAAM,QAAQ,CAAC,OAAe,kBAA2B;AAC9D,MAAI,kBAAkB,OAAW,QAAO;AAExC,SAAO,WAAW,MAAM,QAAQ,aAAa,CAAC;AAChD;;;ACIO,IAAM,oBAA2C;AAAA,EACtD,cAAe,GAAG;AAAA,EAClB,YAAc,GAAG;AAAA,EACjB,cAAiB,GAAG;AAAA,EACpB,cAAiB,GAAG;AAAA,EACpB,cAAe,GAAG;AAAA,EAClB,cAAiB,GAAG;AAAA,EACpB,kBAAiB,GAAG;AAAA,EACpB,gBAAkB,GAAG;AACvB;AAEO,IAAM,iBAA2C;AAAA,EACtD,cAAe;AAAA,EACf,YAAc;AAAA,EACd,cAAiB;AAAA,EACjB,cAAiB;AAAA,EACjB,cAAe;AAAA,EACf,cAAiB;AAAA,EACjB,kBAAiB;AAAA,EACjB,gBAAkB;AACpB;;;AC5BA,IAAM,UAAU;AAAA,EACd,0BACE;AACJ;AAEA,IAAO,kBAAQ;;;ACLR,IAAM,gBAAgB,CAAC,YAAoB,SAChD,QAAQ;AAAA,EAAQ;AAAA,EAAY,CAAC,OAAO,WAClC,KAAK,MAAM,MAAM,SAAY,KAAK,MAAM,IAAI;AAC9C;;;ACOF,IAAM,uBAAuB,CAAC,EAAE,WAAW,QAAQ,MAAsB;AACvE,QAAM,UAAU,eAAe,SAAS;AACxC,QAAM,QAAQ,eAAe,OAAO;AAEpC,QAAM,IAAI;AAAA,IACR;AAAA,MACE,gBAAQ;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;AAEA,IAAM,YAAY,CAAC,WAAkB,YAAmB;AACtD,MAAI,cAAc,QAAS,QAAO;AAElC,QAAM,UAAU,eAAe,SAAS;AACxC,QAAM,QAAQ,eAAe,OAAO;AAEpC,MAAI,YAAY,MAAO,sBAAqB,EAAE,WAAW,QAAQ,CAAC;AAElE,QAAM,kBAAkB,kBAAkB,SAAS;AACnD,QAAM,gBAAgB,kBAAkB,OAAO;AAC/C,SAAO,kBAAkB;AAC3B;AAEA,IAAM,eAAe;AAAA,EACnB;AACF;AAEA,IAAO,wBAAQ;;;ACtCf,IAAM,EAAE,WAAAC,WAAU,IAAI;AAEf,IAAM,UAAU,CACrB,OACA,EAAE,WAAW,SAAS,QAAQ,MAC3B;AACH,QAAM,SAASA,WAAU,WAAW,OAAO;AAE3C,SAAO,MAAM,QAAQ,QAAQ,OAAO;AACtC;","names":["UnitSystem","Dimension","MeasurementType","MetricUnits","ImperialUnits","getFactor"]}
|
|
1
|
+
{"version":3,"sources":["../src/constants/common/common.constants.ts","../src/utils/math/math.ts","../src/constants/conversion/conversion.constants.ts","../src/constants/strings/strings.ts","../src/utils/strings/strings.utils.ts","../src/utils/convert/convert.utils.ts","../src/utils/convert/convert.ts","../src/services/height/height.utils.ts","../src/services/height/height.ts"],"sourcesContent":["export enum UnitSystem {\n METRIC = \"Si\",\n IMPERIAL = \"Imperial\",\n}\n\nexport enum Dimension {\n LENGTH = \"length\",\n WEIGHT = \"weight\",\n SPEED = \"speed\",\n}\n\nexport enum MeasurementType {\n LENGTH = \"length\",\n WEIGHT = \"weight\",\n SPEED = \"speed\",\n HEIGHT = \"height\",\n LENGTH_FEET = \"length_feet\",\n}\n\nexport enum MetricUnits {\n CM = \"cm\",\n M = \"m\",\n KG = \"kg\",\n KM_H = \"km/h\",\n}\n\nexport enum ImperialUnits {\n IN = \"in\",\n FT = \"ft\",\n LB = \"lb\",\n MPH = \"mph\",\n}\n\nexport type Units = MetricUnits | ImperialUnits;\n","export const round = (value: number, decimalPlaces?: number) => {\n if (decimalPlaces === undefined) return value;\n\n return parseFloat(value.toFixed(decimalPlaces));\n};\n","import {\n Dimension,\n ImperialUnits,\n MetricUnits,\n Units,\n} from \"../common/common.constants\";\n\n/** Factor to multiply value by to get value in canonical unit for that dimension. */\nexport const UNIT_TO_CANONICAL: Record<Units, number> = {\n [MetricUnits.CM]: 1,\n [MetricUnits.M]: 100,\n [ImperialUnits.IN]: 2.54,\n [ImperialUnits.FT]: 30.48,\n [MetricUnits.KG]: 1,\n [ImperialUnits.LB]: 0.45359237,\n [MetricUnits.KM_H]: 1,\n [ImperialUnits.MPH]: 1.609344,\n};\n\nexport const UNIT_DIMENSION: Record<Units, Dimension> = {\n [MetricUnits.CM]: Dimension.LENGTH,\n [MetricUnits.M]: Dimension.LENGTH,\n [ImperialUnits.IN]: Dimension.LENGTH,\n [ImperialUnits.FT]: Dimension.LENGTH,\n [MetricUnits.KG]: Dimension.WEIGHT,\n [ImperialUnits.LB]: Dimension.WEIGHT,\n [MetricUnits.KM_H]: Dimension.SPEED,\n [ImperialUnits.MPH]: Dimension.SPEED,\n};\n","const strings = {\n convertDimensionMismatch:\n \"Cannot convert between different dimensions: {0} ({1}) and {2} ({3})\",\n};\n\nexport default strings;\n","export const formatMessage = (message: string, ...args: any[]) =>\n message.replace(/{(\\d+)}/g, (match, number) =>\n args[number] !== undefined ? args[number] : match,\n );\n","import { Units } from \"../../constants/common/common.constants\";\nimport {\n UNIT_DIMENSION,\n UNIT_TO_CANONICAL,\n} from \"../../constants/conversion/conversion.constants\";\nimport strings from \"../../constants/strings/strings\";\nimport { round } from \"../math/math\";\nimport { formatMessage } from \"../strings/strings.utils\";\nimport { ConvertOptions } from \"./convert.types\";\n\nconst throwConversionError = ({ fromUnits, toUnits }: ConvertOptions) => {\n const fromDim = UNIT_DIMENSION[fromUnits];\n const toDim = UNIT_DIMENSION[toUnits];\n\n throw new Error(\n formatMessage(\n strings.convertDimensionMismatch,\n fromUnits,\n fromDim,\n toUnits,\n toDim,\n ),\n );\n};\n\nconst getFactor = (fromUnits: Units, toUnits: Units) => {\n if (fromUnits === toUnits) return 1;\n\n const fromDim = UNIT_DIMENSION[fromUnits];\n const toDim = UNIT_DIMENSION[toUnits];\n\n if (fromDim !== toDim) throwConversionError({ fromUnits, toUnits });\n\n const toCanonicalFrom = UNIT_TO_CANONICAL[fromUnits];\n const toCanonicalTo = UNIT_TO_CANONICAL[toUnits];\n return toCanonicalFrom / toCanonicalTo;\n};\n\nconst convertUtils = {\n getFactor,\n};\n\nexport default convertUtils;\n","import { round } from \"../math/math\";\nimport { ConvertOptions } from \"./convert.types\";\nimport utils from \"./convert.utils\";\n\nconst { getFactor } = utils;\n\nexport const convert = (\n value: number,\n { fromUnits, toUnits, roundTo }: ConvertOptions,\n) => {\n const factor = getFactor(fromUnits, toUnits);\n\n return round(value * factor, roundTo);\n};\n","import { FeetInches } from \"./height.types\";\n\nconst parseFeetInches = (input: string): FeetInches => {\n // NOTE: this function is AI generated, but it's well tested and works as expected. And it's covered by unit tests.\n if (typeof input !== \"string\") return [0, 0];\n\n const normalized = input\n .toLowerCase()\n .replace(/[\"\"]/g, \"in\")\n .replace(/[''′]+/g, \"ft\")\n .replace(/(feet|foot)/g, \"ft\")\n .replace(/(inches|inch)/g, \"in\")\n .replace(/[\\s]+/g, \" \")\n .trim();\n\n const parseNumber = (value: string | undefined): number =>\n parseFloat(value || \"0\");\n\n const ftMatch = normalized.match(/([\\d.]+)\\s*ft/);\n const inMatch = normalized.match(/([\\d.]+)\\s*in/);\n\n const feet = parseNumber(ftMatch?.[1]);\n const inches = parseNumber(inMatch?.[1]);\n\n if (ftMatch && inMatch) {\n return [feet, inches];\n }\n\n const [firstNumberString, secondNumberString] = normalized.match(\n /[\\d.]+/g,\n ) || [\"0\", \"0\"];\n\n const firstNumber = parseNumber(firstNumberString);\n const secondNumber = parseNumber(secondNumberString);\n\n if (!ftMatch && !inMatch) {\n return [firstNumber, secondNumber];\n }\n\n if (ftMatch && !inMatch) {\n return [feet, secondNumber];\n }\n\n if (!ftMatch && inMatch) {\n return [0, inches];\n }\n\n return [0, 0];\n};\n\nconst heightUtils = {\n parseFeetInches,\n};\n\nexport default heightUtils;\n","import {\n ImperialUnits,\n MetricUnits,\n} from \"../../constants/common/common.constants\";\nimport { convert } from \"../../utils/convert/convert\";\nimport { round } from \"../../utils/math/math\";\nimport { FeetInches } from \"./height.types\";\nimport utils from \"./height.utils\";\n\nconst { parseFeetInches } = utils;\n\nclass Height {\n toFeetInches(valueInCm: number, roundTo?: number): FeetInches {\n const totalInches = convert(valueInCm, {\n fromUnits: MetricUnits.CM,\n toUnits: ImperialUnits.IN,\n roundTo,\n });\n\n const feet = Math.floor(totalInches / 12);\n const inches = round(totalInches - feet * 12, roundTo);\n\n return [feet, inches];\n }\n\n toCentimeters([feet, inches]: FeetInches): number {\n const totalInches = feet * 12 + inches;\n\n return convert(totalInches, {\n fromUnits: ImperialUnits.IN,\n toUnits: MetricUnits.CM,\n });\n }\n\n parseFeetInches(input: string): FeetInches {\n return parseFeetInches(input);\n }\n}\n\nconst height = new Height();\n\nexport default height;\n"],"mappings":"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","names":["UnitSystem","Dimension","MeasurementType","MetricUnits","ImperialUnits","getFactor","parseFeetInches"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "uconvert",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -19,7 +19,8 @@
|
|
|
19
19
|
"example": "npm run build && node example/run.mjs",
|
|
20
20
|
"example:cjs": "node example/run.cjs",
|
|
21
21
|
"format": "prettier --write .",
|
|
22
|
-
"
|
|
22
|
+
"postinstall": "husky",
|
|
23
|
+
"test": "jest"
|
|
23
24
|
},
|
|
24
25
|
"repository": {
|
|
25
26
|
"type": "git",
|
|
@@ -33,8 +34,15 @@
|
|
|
33
34
|
"url": "https://github.com/AndrewTkachuk42/uconvert/issues"
|
|
34
35
|
},
|
|
35
36
|
"homepage": "https://github.com/AndrewTkachuk42/uconvert#readme",
|
|
37
|
+
"overrides": {
|
|
38
|
+
"minimatch": "^10.2.2"
|
|
39
|
+
},
|
|
36
40
|
"devDependencies": {
|
|
41
|
+
"@types/jest": "^29.5.14",
|
|
42
|
+
"husky": "^9.1.7",
|
|
43
|
+
"jest": "^30.2.0",
|
|
37
44
|
"prettier": "^3.4.2",
|
|
45
|
+
"ts-jest": "^29.4.6",
|
|
38
46
|
"prettier-plugin-organize-imports": "^4.1.0",
|
|
39
47
|
"tsup": "^8.5.1",
|
|
40
48
|
"typescript": "^5.9.3"
|