mazey 5.4.2 → 5.5.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 CHANGED
@@ -83,6 +83,8 @@ There are some examples maintained by hand below. For more information, please c
83
83
  - [sha256Hex](#sha256hex)
84
84
  - [isValidData](#isvaliddata)
85
85
  - [genRndNumString](#genrndnumstring)
86
+ - [parseLocalDateTime](#parselocaldatetime)
87
+ - [formatLocalDateTime](#formatlocaldatetime)
86
88
  - [formatDate](#formatdate)
87
89
  - [isValidDate](#isvaliddate)
88
90
  - [isToday](#istoday)
@@ -93,8 +95,10 @@ There are some examples maintained by hand below. For more information, please c
93
95
  - [formatDistanceToNow](#formatdistancetonow)
94
96
  - [generateCalendarVersion](#generatecalendarversion)
95
97
  - [formatDurationFromMs](#formatdurationfromms)
98
+ - [formatByteSize](#formatbytesize)
96
99
  - [deepCopy](#deepcopy)
97
100
  - [deepFreeze](#deepfreeze)
101
+ - [assignDefined](#assigndefined)
98
102
  - [debounce](#debounce)
99
103
  - [throttle](#throttle)
100
104
  - [convertCamelToKebab](#convertcameltokebab)
@@ -120,6 +124,7 @@ There are some examples maintained by hand below. For more information, please c
120
124
  - [genStyleString](#genstylestring)
121
125
  - [newLine](#newline)
122
126
  - [Calculate and Formula](#calculate-and-formula)
127
+ - [calculateCAGR](#calculatecagr)
123
128
  - [inRate](#inrate)
124
129
  - [longestComSubstring](#longestcomsubstring)
125
130
  - [longestComSubsequence](#longestcomsubsequence)
@@ -128,6 +133,7 @@ There are some examples maintained by hand below. For more information, please c
128
133
  - [setThemePreference](#setthemepreference)
129
134
  - [resolveLanguagePreference](#resolvelanguagepreference)
130
135
  - [setLanguagePreference](#setlanguagepreference)
136
+ - [detectVisitorType](#detectvisitortype)
131
137
  - [getBrowserInfo](#getbrowserinfo)
132
138
  - [isSafePWAEnv](#issafepwaenv)
133
139
  - [isStandalonePWA](#isstandalonepwa)
@@ -388,6 +394,59 @@ Output:
388
394
  2262490
389
395
  ```
390
396
 
397
+ #### parseLocalDateTime
398
+
399
+ Strictly parse a normalized HTML `datetime-local` value as local wall-clock
400
+ time. The function accepts a year with at least four digits, minute values with
401
+ optional seconds and milliseconds, rejects timezone suffixes and impossible
402
+ dates, and returns `null` for invalid input.
403
+
404
+ Usage:
405
+
406
+ ```javascript
407
+ const date = parseLocalDateTime("2026-07-21T14:30:45.123");
408
+ console.log(date?.getFullYear());
409
+ console.log(date?.getHours());
410
+ console.log(date?.getMilliseconds());
411
+ ```
412
+
413
+ Output:
414
+
415
+ ```text
416
+ 2026
417
+ 14
418
+ 123
419
+ ```
420
+
421
+ #### formatLocalDateTime
422
+
423
+ Format a `Date` from its local calendar fields for an HTML `datetime-local`
424
+ control. Precision defaults to minutes and can be set to `second` or
425
+ `millisecond`. The year is padded to at least four digits, and the function
426
+ does not convert the value to UTC.
427
+
428
+ Usage:
429
+
430
+ ```javascript
431
+ const date = new Date(2026, 6, 21, 14, 30, 45, 123);
432
+ const minutes = formatLocalDateTime(date);
433
+ const seconds = formatLocalDateTime(date, { precision: "second" });
434
+ const milliseconds = formatLocalDateTime(date, {
435
+ precision: "millisecond",
436
+ });
437
+ console.log(minutes);
438
+ console.log(seconds);
439
+ console.log(milliseconds);
440
+ ```
441
+
442
+ Output:
443
+
444
+ ```text
445
+ 2026-07-21T14:30
446
+ 2026-07-21T14:30:45
447
+ 2026-07-21T14:30:45.123
448
+ ```
449
+
391
450
  #### formatDate
392
451
 
393
452
  Return the formatted date string in the given format.
@@ -553,6 +612,26 @@ Output:
553
612
  1.5 days
554
613
  ```
555
614
 
615
+ #### formatByteSize
616
+
617
+ Format a non-negative byte count using 1024-based units and one fractional
618
+ digit by default. Decimal scaling, precision, and the invalid-input fallback
619
+ are configurable. The former `getFileSize` name is a deprecated alias.
620
+
621
+ ```javascript
622
+ formatByteSize(0);
623
+ formatByteSize(1536);
624
+ formatByteSize(1500000, { base: 1000, fractionDigits: 2 });
625
+ ```
626
+
627
+ Output:
628
+
629
+ ```text
630
+ 0 B
631
+ 1.5 KB
632
+ 1.50 MB
633
+ ```
634
+
556
635
  #### deepCopy
557
636
 
558
637
  Copy/Clone Object deeply.
@@ -598,6 +677,26 @@ true
598
677
  true
599
678
  ```
600
679
 
680
+ #### assignDefined
681
+
682
+ Shallowly mutate a target with defined properties from later sources. The
683
+ helper skips only `undefined`, so `null`, empty strings, `0`, and `false`
684
+ remain valid overrides.
685
+
686
+ ```javascript
687
+ const options = assignDefined(
688
+ { retries: 3, verbose: true },
689
+ { retries: undefined, verbose: false }
690
+ );
691
+ console.log(options);
692
+ ```
693
+
694
+ Output:
695
+
696
+ ```text
697
+ { retries: 3, verbose: false }
698
+ ```
699
+
601
700
  #### debounce
602
701
 
603
702
  Debounce
@@ -1088,6 +1187,54 @@ a<br /><br />bc
1088
1187
 
1089
1188
  ### Calculate and Formula
1090
1189
 
1190
+ #### calculateCAGR
1191
+
1192
+ Calculate an investment's Compound Annual Growth Rate (CAGR) from its start date, end date, and total return over the complete period.
1193
+
1194
+ ```text
1195
+ CAGR = (1 + totalReturnRate)^(365 / durationInDays) - 1
1196
+ ```
1197
+
1198
+ The dates may be supported structured date strings, millisecond timestamps, or `Date` instances. The calculation uses the exact elapsed milliseconds, including time-of-day components, and a fixed 365-day financial year.
1199
+
1200
+ Number input is a decimal ratio, so `0.202` represents `20.2%`. String input is a percentage value, so `"20.2%"` and `"20.2"` both represent `20.2%`; strict scientific notation such as `"2.02e1%"` is also accepted. The returned CAGR is an unrounded decimal ratio.
1201
+
1202
+ ```javascript
1203
+ import { calculateCAGR, floatToPercent } from "mazey";
1204
+
1205
+ const cagr = calculateCAGR(
1206
+ "2022-04-01",
1207
+ "2025-10-01",
1208
+ "20.2%"
1209
+ );
1210
+
1211
+ console.log({
1212
+ cagr,
1213
+ percentage: floatToPercent(cagr, 2),
1214
+ });
1215
+ ```
1216
+
1217
+ Possible output:
1218
+
1219
+ ```text
1220
+ {
1221
+ cagr: 0.053908...,
1222
+ percentage: "5.39%"
1223
+ }
1224
+ ```
1225
+
1226
+ The equivalent decimal-number call is:
1227
+
1228
+ ```javascript
1229
+ calculateCAGR(
1230
+ "2022-04-01",
1231
+ "2025-10-01",
1232
+ 0.202
1233
+ );
1234
+ ```
1235
+
1236
+ Date strings are validated using Mazey's strict date rules. Invalid dates, malformed or non-finite returns, and non-increasing date ranges throw errors. The parsed total return must be greater than `-1`, because `-1` represents a complete loss for which CAGR is undefined.
1237
+
1091
1238
  #### inRate
1092
1239
 
1093
1240
  Hit probability (1% ~ 100%).
@@ -1247,6 +1394,58 @@ const stored = setLanguagePreference(
1247
1394
 
1248
1395
  Output: `true`
1249
1396
 
1397
+ #### detectVisitorType
1398
+
1399
+ Conservatively classify a visitor as `"crawler"`, `"automation"`, or
1400
+ `"unknown"`. The function first checks a focused list of recognizable crawler,
1401
+ indexing, SEO, AI-fetcher, and link-preview user-agent tokens. It then checks
1402
+ explicit automation user-agent tokens and `navigator.webdriver === true`.
1403
+
1404
+ When no argument is provided, the function safely reads
1405
+ `navigator.userAgent`. An explicit user-agent string can be supplied for
1406
+ captured-user-agent analysis, deterministic tests, or server-side use. During
1407
+ SSR or in Node.js without `navigator`, the default result is `"unknown"`;
1408
+ explicit user-agent classification still works.
1409
+
1410
+ ```javascript
1411
+ const visitorType = detectVisitorType();
1412
+
1413
+ console.log(visitorType);
1414
+ ```
1415
+
1416
+ Possible output:
1417
+
1418
+ ```text
1419
+ unknown
1420
+ ```
1421
+
1422
+ Explicit crawler example:
1423
+
1424
+ ```javascript
1425
+ const visitorType = detectVisitorType(
1426
+ "Mozilla/5.0 (compatible; Googlebot/2.1)"
1427
+ );
1428
+
1429
+ console.log(visitorType);
1430
+ ```
1431
+
1432
+ Output:
1433
+
1434
+ ```text
1435
+ crawler
1436
+ ```
1437
+
1438
+ `"unknown"` means that no supported crawler or browser-automation signal was
1439
+ detected. User-agent values can be spoofed, and WebDriver signals can be hidden
1440
+ or changed, so false positives and false negatives are possible.
1441
+
1442
+ > `unknown` does not mean that the visitor has been verified as human. This
1443
+ > function uses browser-side heuristics and must not be used as a security
1444
+ > boundary or by itself for authentication, authorization, payments, rate
1445
+ > limiting, fraud prevention, or access control. Genuine crawler verification
1446
+ > generally requires server-side request information and provider-specific
1447
+ > validation.
1448
+
1250
1449
  #### getBrowserInfo
1251
1450
 
1252
1451
  Browser Information
package/README.zh-CN.md CHANGED
@@ -105,10 +105,12 @@ isNumber(z, { isInfinityAsNumber: true }); // 输出: true
105
105
  - [genStyleString](#genstylestring)
106
106
  - [newLine](#newline)
107
107
  - [计算与公式](#计算与公式)
108
+ - [calculateCAGR](#calculatecagr)
108
109
  - [inRate](#inrate)
109
110
  - [longestComSubstring](#longestcomsubstring)
110
111
  - [longestComSubsequence](#longestcomsubsequence)
111
112
  - [浏览器信息](#浏览器信息)
113
+ - [detectVisitorType](#detectvisitortype)
112
114
  - [getBrowserInfo](#getbrowserinfo)
113
115
  - [isSafePWAEnv](#issafepwaenv)
114
116
  - [isStandalonePWA](#isstandalonepwa)
@@ -982,6 +984,54 @@ a<br /><br />bc
982
984
 
983
985
  ### 计算与公式
984
986
 
987
+ #### calculateCAGR
988
+
989
+ 根据投资的开始日期、结束日期和整个周期的总回报率,计算复合年增长率(Compound Annual Growth Rate,CAGR)。
990
+
991
+ ```text
992
+ CAGR = (1 + totalReturnRate)^(365 / durationInDays) - 1
993
+ ```
994
+
995
+ 日期可以是支持的结构化日期字符串、毫秒时间戳或 `Date` 实例。计算使用精确的毫秒间隔,包括日期中的时分秒,并固定以 365 天作为一个财务年度。
996
+
997
+ 数值输入使用十进制比率,因此 `0.202` 表示 `20.2%`。字符串输入使用百分比数值,因此 `"20.2%"` 和 `"20.2"` 都表示 `20.2%`;也支持 `"2.02e1%"` 这类严格的科学记数法。返回的 CAGR 是未经舍入的十进制比率。
998
+
999
+ ```javascript
1000
+ import { calculateCAGR, floatToPercent } from "mazey";
1001
+
1002
+ const cagr = calculateCAGR(
1003
+ "2022-04-01",
1004
+ "2025-10-01",
1005
+ "20.2%"
1006
+ );
1007
+
1008
+ console.log({
1009
+ cagr,
1010
+ percentage: floatToPercent(cagr, 2),
1011
+ });
1012
+ ```
1013
+
1014
+ 可能的输出:
1015
+
1016
+ ```text
1017
+ {
1018
+ cagr: 0.053908...,
1019
+ percentage: "5.39%"
1020
+ }
1021
+ ```
1022
+
1023
+ 等效的十进制数值调用如下:
1024
+
1025
+ ```javascript
1026
+ calculateCAGR(
1027
+ "2022-04-01",
1028
+ "2025-10-01",
1029
+ 0.202
1030
+ );
1031
+ ```
1032
+
1033
+ 日期字符串遵循 Mazey 的严格日期校验规则。无效日期、格式错误或非有限的回报率,以及没有递增的日期范围都会抛出错误。解析后的总回报率必须大于 `-1`,因为 `-1` 表示本金完全损失,此时 CAGR 没有定义。
1034
+
985
1035
  #### inRate
986
1036
 
987
1037
  按照指定概率返回命中结果。有效概率范围为 1%~100%。
@@ -1051,6 +1101,44 @@ console.log(ret);
1051
1101
 
1052
1102
  ### 浏览器信息
1053
1103
 
1104
+ #### detectVisitorType
1105
+
1106
+ 此函数使用保守的启发式规则,将访问者分类为 `"crawler"`、`"automation"` 或 `"unknown"`。函数首先检查一组明确的 User-Agent 令牌。这些令牌来自爬虫、索引、SEO、AI 抓取和链接预览客户端。随后,函数检查显式的自动化 User-Agent 令牌,以及 `navigator.webdriver === true`。
1107
+
1108
+ 省略参数时,函数会安全地读取 `navigator.userAgent`。也可以传入明确的 User-Agent 字符串。此方式适合分析已捕获的 User-Agent、编写确定性测试或在服务端分类。SSR 或 Node.js 环境没有 `navigator` 时,默认返回 `"unknown"`。此时仍可传入明确的 User-Agent 进行分类。
1109
+
1110
+ ```javascript
1111
+ const visitorType = detectVisitorType();
1112
+
1113
+ console.log(visitorType);
1114
+ ```
1115
+
1116
+ 可能的输出:
1117
+
1118
+ ```text
1119
+ unknown
1120
+ ```
1121
+
1122
+ 下面的示例传入爬虫 User-Agent:
1123
+
1124
+ ```javascript
1125
+ const visitorType = detectVisitorType(
1126
+ "Mozilla/5.0 (compatible; Googlebot/2.1)"
1127
+ );
1128
+
1129
+ console.log(visitorType);
1130
+ ```
1131
+
1132
+ 输出:
1133
+
1134
+ ```text
1135
+ crawler
1136
+ ```
1137
+
1138
+ `"unknown"` 仅表示没有检测到受支持的爬虫或浏览器自动化信号。User-Agent 可以伪造,WebDriver 信号也可以隐藏或修改。因此,分类可能出现误判或漏判。
1139
+
1140
+ > `unknown` 不表示访问者已经通过真人验证。此函数只使用浏览器端启发式规则,不能作为安全边界。请勿单独使用此结果进行身份验证、授权、支付决策、速率限制、欺诈防范或访问控制。验证真实爬虫通常需要服务端请求信息,以及服务提供商规定的验证流程。
1141
+
1054
1142
  #### getBrowserInfo
1055
1143
 
1056
1144
  获取浏览器信息。