@visulima/humanizer 3.0.0-alpha.1 → 3.0.0-alpha.10
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.md +1 -1
- package/README.md +32 -14
- package/dist/index.js +3 -3
- package/dist/language/ro.js +21 -8
- package/dist/language/sr_Latn.d.ts +1 -0
- package/dist/language/util/validate-duration-language.js +3 -2
- package/dist/packem_shared/{duration-C62ipnQn.js → duration-Br8Mr-Lj.js} +4 -8
- package/dist/packem_shared/{parseBytes-JWspeMzP.js → parseBytes-BkjYV2ut.js} +22 -10
- package/dist/packem_shared/{parseDuration-CeFaBgx9.js → parseDuration-qO1Y4eiu.js} +3 -3
- package/package.json +1 -1
package/LICENSE.md
CHANGED
package/README.md
CHANGED
|
@@ -1,15 +1,24 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
<!-- START_PACKAGE_OG_IMAGE_PLACEHOLDER -->
|
|
2
|
+
|
|
3
|
+
<a href="https://www.anolilab.com/open-source" align="center">
|
|
4
|
+
|
|
5
|
+
<img src="__assets__/package-og.svg" alt="humanizer" />
|
|
6
|
+
|
|
7
|
+
</a>
|
|
8
|
+
|
|
9
|
+
<h3 align="center">Humanizer is a library for humanizing data in a human-readable form.</h3>
|
|
10
|
+
|
|
11
|
+
<!-- END_PACKAGE_OG_IMAGE_PLACEHOLDER -->
|
|
7
12
|
|
|
8
13
|
<br />
|
|
9
14
|
|
|
10
15
|
<div align="center">
|
|
11
16
|
|
|
12
|
-
[![typescript-image]
|
|
17
|
+
[![typescript-image][typescript-badge]][typescript-url]
|
|
18
|
+
[![mit licence][license-badge]][license]
|
|
19
|
+
[![npm downloads][npm-downloads-badge]][npm-downloads]
|
|
20
|
+
[![Chat][chat-badge]][chat]
|
|
21
|
+
[![PRs Welcome][prs-welcome-badge]][prs-welcome]
|
|
13
22
|
|
|
14
23
|
</div>
|
|
15
24
|
|
|
@@ -1056,14 +1065,23 @@ If you would like to help take a look at the [list of issues](https://github.com
|
|
|
1056
1065
|
- [Daniel Bannert](https://github.com/prisis)
|
|
1057
1066
|
- [All Contributors](https://github.com/visulima/visulima/graphs/contributors)
|
|
1058
1067
|
|
|
1068
|
+
## Made with ❤️ at Anolilab
|
|
1069
|
+
|
|
1070
|
+
This is an open source project and will always remain free to use. If you think it's cool, please star it 🌟. [Anolilab](https://www.anolilab.com/open-source) is a Development and AI Studio. Contact us at [hello@anolilab.com](mailto:hello@anolilab.com) if you need any help with these technologies or just want to say hi!
|
|
1071
|
+
|
|
1059
1072
|
## License
|
|
1060
1073
|
|
|
1061
|
-
The visulima humanizer is open-sourced software licensed under the [MIT][license
|
|
1074
|
+
The visulima humanizer is open-sourced software licensed under the [MIT][license]
|
|
1062
1075
|
|
|
1063
|
-
|
|
1076
|
+
<!-- badges -->
|
|
1064
1077
|
|
|
1065
|
-
[
|
|
1066
|
-
[license
|
|
1067
|
-
[
|
|
1068
|
-
[npm-
|
|
1069
|
-
[
|
|
1078
|
+
[license-badge]: https://img.shields.io/npm/l/@visulima/humanizer?style=for-the-badge
|
|
1079
|
+
[license]: https://github.com/visulima/visulima/blob/main/LICENSE
|
|
1080
|
+
[npm-downloads-badge]: https://img.shields.io/npm/dm/@visulima/humanizer?style=for-the-badge
|
|
1081
|
+
[npm-downloads]: https://www.npmjs.com/package/@visulima/humanizer
|
|
1082
|
+
[prs-welcome-badge]: https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=for-the-badge
|
|
1083
|
+
[prs-welcome]: https://github.com/visulima/visulima/blob/main/.github/CONTRIBUTING.md
|
|
1084
|
+
[chat-badge]: https://img.shields.io/discord/932323359193186354.svg?style=for-the-badge
|
|
1085
|
+
[chat]: https://discord.gg/TtFJY8xkFK
|
|
1086
|
+
[typescript-badge]: https://img.shields.io/badge/Typescript-294E80.svg?style=for-the-badge&logo=typescript
|
|
1087
|
+
[typescript-url]: https://www.typescriptlang.org/
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { formatBytes, parseBytes } from './packem_shared/parseBytes-
|
|
2
|
-
export { default as duration } from './packem_shared/duration-
|
|
3
|
-
export { default as parseDuration } from './packem_shared/parseDuration-
|
|
1
|
+
export { formatBytes, parseBytes } from './packem_shared/parseBytes-BkjYV2ut.js';
|
|
2
|
+
export { default as duration } from './packem_shared/duration-Br8Mr-Lj.js';
|
|
3
|
+
export { default as parseDuration } from './packem_shared/parseDuration-qO1Y4eiu.js';
|
package/dist/language/ro.js
CHANGED
|
@@ -28,15 +28,28 @@ const roUnitMap = {
|
|
|
28
28
|
zi: "d",
|
|
29
29
|
zile: "d"
|
|
30
30
|
};
|
|
31
|
+
const romanianUnit = (unit) => (counter) => {
|
|
32
|
+
if (counter === 1) {
|
|
33
|
+
return unit[0];
|
|
34
|
+
}
|
|
35
|
+
if (Math.floor(counter) !== counter || counter === 0) {
|
|
36
|
+
return unit[1];
|
|
37
|
+
}
|
|
38
|
+
const remainder = counter % 100;
|
|
39
|
+
if (remainder >= 1 && remainder <= 19) {
|
|
40
|
+
return unit[1];
|
|
41
|
+
}
|
|
42
|
+
return unit[2];
|
|
43
|
+
};
|
|
31
44
|
const durationLanguage = createDurationLanguage(
|
|
32
|
-
(
|
|
33
|
-
(
|
|
34
|
-
(
|
|
35
|
-
(
|
|
36
|
-
(
|
|
37
|
-
(
|
|
38
|
-
(
|
|
39
|
-
(
|
|
45
|
+
romanianUnit(["an", "ani", "de ani"]),
|
|
46
|
+
romanianUnit(["lună", "luni", "de luni"]),
|
|
47
|
+
romanianUnit(["săptămână", "săptămâni", "de săptămâni"]),
|
|
48
|
+
romanianUnit(["zi", "zile", "de zile"]),
|
|
49
|
+
romanianUnit(["oră", "ore", "de ore"]),
|
|
50
|
+
romanianUnit(["minut", "minute", "de minute"]),
|
|
51
|
+
romanianUnit(["secundă", "secunde", "de secunde"]),
|
|
52
|
+
romanianUnit(["milisecundă", "milisecunde", "de milisecunde"]),
|
|
40
53
|
"peste %s",
|
|
41
54
|
// "in %s"
|
|
42
55
|
"%s în urmă",
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
const validateDurationLanguage = (language) => {
|
|
2
2
|
const requiredProperties = ["y", "mo", "w", "d", "h", "m", "s", "ms", "future", "past"];
|
|
3
3
|
for (const property of requiredProperties) {
|
|
4
|
-
if (!Object.
|
|
4
|
+
if (!Object.hasOwn(language, property)) {
|
|
5
5
|
throw new TypeError(`Missing required property: ${property}`);
|
|
6
6
|
}
|
|
7
7
|
}
|
|
8
8
|
if (typeof language.future !== "string" || typeof language.past !== "string") {
|
|
9
9
|
throw new TypeError("Properties future and past must be of type string");
|
|
10
10
|
}
|
|
11
|
-
|
|
11
|
+
const unitProperties = ["y", "mo", "w", "d", "h", "m", "s", "ms"];
|
|
12
|
+
for (const property of unitProperties) {
|
|
12
13
|
if (typeof language[property] !== "string" && typeof language[property] !== "function") {
|
|
13
14
|
throw new TypeError(`Property ${property} must be of type string or function`);
|
|
14
15
|
}
|
|
@@ -88,7 +88,7 @@ const getPieces = (ms, options) => {
|
|
|
88
88
|
for (let index_ = index + 1; index_ < units.length; index_++) {
|
|
89
89
|
const smallerUnitName = units[index_];
|
|
90
90
|
const smallerUnitCount = unitCounts[smallerUnitName];
|
|
91
|
-
unitCounts[unitName]
|
|
91
|
+
unitCounts[unitName] = (unitCounts[unitName] ?? 0) + smallerUnitCount * unitMeasures[smallerUnitName] / unitMeasures[unitName];
|
|
92
92
|
unitCounts[smallerUnitName] = 0;
|
|
93
93
|
}
|
|
94
94
|
break;
|
|
@@ -109,7 +109,7 @@ const getPieces = (ms, options) => {
|
|
|
109
109
|
const previousUnitMs = unitMeasures[previousUnitName];
|
|
110
110
|
const amountOfPreviousUnit = Math.floor(rounded * unitMeasures[unitName] / previousUnitMs);
|
|
111
111
|
if (amountOfPreviousUnit) {
|
|
112
|
-
unitCounts[previousUnitName]
|
|
112
|
+
unitCounts[previousUnitName] = (unitCounts[previousUnitName] ?? 0) + amountOfPreviousUnit;
|
|
113
113
|
unitCounts[unitName] = 0;
|
|
114
114
|
} else {
|
|
115
115
|
break;
|
|
@@ -158,18 +158,14 @@ const formatPieces = (pieces, options, ms) => {
|
|
|
158
158
|
adverb = language.past ?? "";
|
|
159
159
|
}
|
|
160
160
|
}
|
|
161
|
-
const renderedPieces =
|
|
162
|
-
for (const piece_ of pieces) {
|
|
163
|
-
const piece = piece_;
|
|
164
|
-
renderedPieces.push(renderPiece(piece, language, options));
|
|
165
|
-
}
|
|
161
|
+
const renderedPieces = pieces.map((piece) => renderPiece(piece, language, options));
|
|
166
162
|
let result;
|
|
167
163
|
if (!conjunction || pieces.length === 1) {
|
|
168
164
|
result = renderedPieces.join(delimiter);
|
|
169
165
|
} else if (pieces.length === 2) {
|
|
170
166
|
result = renderedPieces.join(conjunction);
|
|
171
167
|
} else {
|
|
172
|
-
result = renderedPieces.slice(0, -1).join(delimiter) + (serialComma ? "," : "") + conjunction + renderedPieces.at(-1);
|
|
168
|
+
result = renderedPieces.slice(0, -1).join(delimiter) + (serialComma ? "," : "") + conjunction + (renderedPieces.at(-1) ?? "");
|
|
173
169
|
}
|
|
174
170
|
if (adverb) {
|
|
175
171
|
result = adverb.replace("%s", result);
|
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
const PARSE_BYTES_REGEX = /^(?<value>-?\d+(?:[.,]\d+)*) *(?<type>[a-z]+)?$/i;
|
|
2
|
+
const KIBI_REGEX = /^KIBI/;
|
|
3
|
+
const MIBI_REGEX = /^MIBI/;
|
|
4
|
+
const GIBI_REGEX = /^GIBI/;
|
|
5
|
+
const TEBI_REGEX = /^TEBI/;
|
|
6
|
+
const PEBI_REGEX = /^PEBI/;
|
|
7
|
+
const EXBI_REGEX = /^EXBI/;
|
|
8
|
+
const ZEBI_REGEX = /^ZEBI/;
|
|
9
|
+
const YIBI_REGEX = /^YIBI/;
|
|
10
|
+
const IB_SUFFIX_REGEX = /^(.)IB$/;
|
|
1
11
|
const BYTE_SIZES = {
|
|
2
12
|
iec: [
|
|
3
13
|
{
|
|
@@ -158,13 +168,17 @@ const parseLocalizedNumber = (stringNumber, locale) => {
|
|
|
158
168
|
return Number.parseFloat(stringNumber.replaceAll(new RegExp(`\\${thousandSeparator}`, "g"), "").replace(new RegExp(`\\${decimalSeparator}`), "."));
|
|
159
169
|
};
|
|
160
170
|
const fromBase = (base) => {
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
171
|
+
switch (base) {
|
|
172
|
+
case 2: {
|
|
173
|
+
return 1024;
|
|
174
|
+
}
|
|
175
|
+
case 10: {
|
|
176
|
+
return 1e3;
|
|
177
|
+
}
|
|
178
|
+
default: {
|
|
179
|
+
throw new Error("Unsupported base.");
|
|
180
|
+
}
|
|
166
181
|
}
|
|
167
|
-
throw new TypeError(`Unsupported base.`);
|
|
168
182
|
};
|
|
169
183
|
const parseBytes = (value, options) => {
|
|
170
184
|
const config = {
|
|
@@ -179,15 +193,13 @@ const parseBytes = (value, options) => {
|
|
|
179
193
|
if (value.length > 100) {
|
|
180
194
|
throw new TypeError("Value exceeds the maximum length of 100 characters.");
|
|
181
195
|
}
|
|
182
|
-
const match =
|
|
183
|
-
value
|
|
184
|
-
);
|
|
196
|
+
const match = PARSE_BYTES_REGEX.exec(value);
|
|
185
197
|
const groups = match?.groups;
|
|
186
198
|
if (!groups) {
|
|
187
199
|
return Number.NaN;
|
|
188
200
|
}
|
|
189
201
|
const localizedNumber = parseLocalizedNumber(groups.value, config.locale);
|
|
190
|
-
const type = (groups.type ?? "Bytes").toUpperCase().replace(
|
|
202
|
+
const type = (groups.type ?? "Bytes").toUpperCase().replace(KIBI_REGEX, "KILO").replace(MIBI_REGEX, "MEGA").replace(GIBI_REGEX, "GIGA").replace(TEBI_REGEX, "TERA").replace(PEBI_REGEX, "PETA").replace(EXBI_REGEX, "EXA").replace(ZEBI_REGEX, "ZETTA").replace(YIBI_REGEX, "YOTTA").replace(IB_SUFFIX_REGEX, "$1B");
|
|
191
203
|
const level = BYTE_SIZES[config.units].findIndex((unit) => unit.short[0].toUpperCase() === type[0]);
|
|
192
204
|
const base = fromBase(config.base);
|
|
193
205
|
return localizedNumber * base ** level;
|
|
@@ -15,6 +15,7 @@ const ESCAPE_REGEX = /[-/\\^$*+?.()|[\]{}]/g;
|
|
|
15
15
|
const ISO_FORMAT = /^PT(?:(\d+)H)?(?:(\d+)M)?(?:(\d+)S)?$/i;
|
|
16
16
|
const COLON_FORMAT = /^(?:(\d+):)?(?:(\d+):)?(\d+)$/;
|
|
17
17
|
const NUMERIC_STRING_REGEX = /^[+-]?\d+(?:\.\d+)?$/;
|
|
18
|
+
const SIGN_PREFIX_REGEX = /^[-+]/;
|
|
18
19
|
const parseDuration = (value, options) => {
|
|
19
20
|
if (typeof value !== "string" || value.length === 0) {
|
|
20
21
|
return void 0;
|
|
@@ -53,14 +54,13 @@ const parseDuration = (value, options) => {
|
|
|
53
54
|
if (colonMatch) {
|
|
54
55
|
let hours = 0;
|
|
55
56
|
let minutes = 0;
|
|
56
|
-
let seconds = 0;
|
|
57
57
|
if (colonMatch[2] !== void 0) {
|
|
58
58
|
hours = Number.parseInt(colonMatch[1] ?? "0", 10);
|
|
59
59
|
minutes = Number.parseInt(colonMatch[2], 10);
|
|
60
60
|
} else if (colonMatch[1] !== void 0) {
|
|
61
61
|
minutes = Number.parseInt(colonMatch[1], 10);
|
|
62
62
|
}
|
|
63
|
-
seconds = Number.parseInt(colonMatch[3] ?? "0", 10);
|
|
63
|
+
const seconds = Number.parseInt(colonMatch[3] ?? "0", 10);
|
|
64
64
|
return hours * 36e5 + minutes * 6e4 + seconds * 1e3;
|
|
65
65
|
}
|
|
66
66
|
const currentUnitMapKeys = Object.keys(currentUnitMap);
|
|
@@ -84,7 +84,7 @@ const parseDuration = (value, options) => {
|
|
|
84
84
|
}
|
|
85
85
|
const trimmedNumberString = numberString.trim();
|
|
86
86
|
const sign = trimmedNumberString.startsWith("-") ? -1 : 1;
|
|
87
|
-
const absNumberString = trimmedNumberString.replace(
|
|
87
|
+
const absNumberString = trimmedNumberString.replace(SIGN_PREFIX_REGEX, "");
|
|
88
88
|
const parsedNumber = Number.parseFloat(absNumberString);
|
|
89
89
|
const unitKey = currentUnitMap[unitString.toLowerCase()];
|
|
90
90
|
if (unitKey === void 0) {
|