mazey 3.1.0 → 3.3.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/src/index.ts CHANGED
@@ -5,9 +5,9 @@
5
5
  * @description Computes the longest common substring of two strings.
6
6
  * @param {string} aStr String
7
7
  * @param {string} bStr String
8
- * @return {number} Length
8
+ * @returns {number} Length
9
9
  */
10
- export function calLongestCommonSubstring(aStr = '', bStr = ''): number {
10
+ export function calLongestCommonSubstring(aStr: string, bStr: string): number {
11
11
  const aLen = aStr.length;
12
12
  const bLen = bStr.length;
13
13
  // 创建二维数组并且深拷贝
@@ -35,9 +35,9 @@ export function calLongestCommonSubstring(aStr = '', bStr = ''): number {
35
35
  * @description 计算两个字符串的最长公共子序列
36
36
  * @param {string} aStr 字符串
37
37
  * @param {string} bStr 字符串
38
- * @return {number} 长度
38
+ * @returns {number} 长度
39
39
  */
40
- export function calLongestCommonSubsequence(aStr = '', bStr = ''): number {
40
+ export function calLongestCommonSubsequence(aStr: string, bStr: string): number {
41
41
  const aLen = aStr.length;
42
42
  const bLen = bStr.length;
43
43
  // 创建二维数组并且深拷贝
@@ -73,13 +73,14 @@ export function calLongestCommonSubsequence(aStr = '', bStr = ''): number {
73
73
  * @method getQueryParam
74
74
  * @description Get the query param's value of the current Web URL(`location.search`).
75
75
  * @param {string} param Query param.
76
- * @return {string} value
77
- * */
78
- export function getQueryParam(param = ''): string {
76
+ * @returns {string} value
77
+ */
78
+ export function getQueryParam(param: string): string {
79
79
  const reg = new RegExp('(^|&)' + param + '=([^&]*)(&|$)');
80
80
  const r = location.search.substr(1).match(reg);
81
81
  if (r !== null) {
82
- return decodeURIComponent(unescape(r[2]));
82
+ // return decodeURIComponent(unescape(r[2]));
83
+ return decodeURIComponent(r[2]);
83
84
  }
84
85
  return '';
85
86
  }
@@ -89,10 +90,12 @@ export function getQueryParam(param = ''): string {
89
90
  * @description Get the query param's value of the input URL.
90
91
  * @param {string} url URL string.
91
92
  * @param {string} param Query param.
92
- * @return {string} value
93
- * */
94
- export function getUrlParam(url = '', param = ''): string {
95
- const result: any = {};
93
+ * @returns {string} value
94
+ */
95
+ export function getUrlParam(url: string, param: string): string | string[] {
96
+ const result: {
97
+ [key: string]: string | string[] | any;
98
+ } = {};
96
99
  // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace
97
100
  url.replace(/\??(\w+)=([^&]*)&?/g, function (a, k, v): any {
98
101
  if (result[k] !== undefined) {
@@ -116,9 +119,9 @@ export function getUrlParam(url = '', param = ''): string {
116
119
  * @param {string} url URL string.
117
120
  * @param {string} param Query param.
118
121
  * @param {string} value Param's value.
119
- * @return {string} URL.
120
- * */
121
- export function updateQueryParam(url = '', param = '', value = ''): string {
122
+ * @returns {string} URL.
123
+ */
124
+ export function updateQueryParam(url: string, param: string, value: string): string {
122
125
  const re = new RegExp('([?&])' + param + '=.*?(&|$)', 'i');
123
126
  const separator = url.indexOf('?') !== -1 ? '&' : '?';
124
127
  if (url.match(re)) {
@@ -132,9 +135,9 @@ export function getUrlParam(url = '', param = ''): string {
132
135
  * @method getHashQueryParam
133
136
  * @description Get the hash query param's value of the current Web URL(`location.hash`).
134
137
  * @param {string} param Query param.
135
- * @return {string} value
138
+ * @returns {string} value
136
139
  */
137
- export function getHashQueryParam(param = ''): string {
140
+ export function getHashQueryParam(param: string): string {
138
141
  const hashs = location.hash.split('?');
139
142
  if (hashs.length === 1) {
140
143
  return '';
@@ -149,8 +152,8 @@ export function getHashQueryParam(param = ''): string {
149
152
  * @description Get the domain of URL, and other params.
150
153
  * @param {string} url
151
154
  * @param {array} rules Object.keys(location), ['href', 'protocol', 'host', 'hostname', 'port', 'pathname', 'search', 'hash'], ['hostname', 'pathname'] = 'km.mazey.net/plugins/servlet/mobile'
152
- * */
153
- export function getDomain(url = '', rules = ['hostname']): string {
155
+ */
156
+ export function getDomain(url: string, rules = ['hostname']): string {
154
157
  const aEl: any = document.createElement('a');
155
158
  aEl.href = url;
156
159
  return rules.reduce((ret, v) => {
@@ -163,9 +166,9 @@ export function getDomain(url = '', rules = ['hostname']): string {
163
166
  * @method camelCaseToKebabCase
164
167
  * @description Transfer CamelCase to KebabCase.
165
168
  * @param {string} camelCase 'aBC' or 'ABC'
166
- * @return {string} 'a-b-c'
167
- * */
168
- export function camelCaseToKebabCase(camelCase = ''): string {
169
+ * @returns {string} 'a-b-c'
170
+ */
171
+ export function camelCaseToKebabCase(camelCase: string): string {
169
172
  const kebabCase = camelCase.replace(/([A-Z])/g, '-$1').toLowerCase();
170
173
  return kebabCase[0] === '-' ? kebabCase.substr(1) : kebabCase;
171
174
  }
@@ -174,9 +177,9 @@ export function camelCaseToKebabCase(camelCase = ''): string {
174
177
  * @method camelCase2Underscore
175
178
  * @description Transfer CamelCase to Underscore.
176
179
  * @param {string} camelCase 'aBC' or 'ABC'
177
- * @return {string} 'a_b_c'
178
- * */
179
- export function camelCase2Underscore(camelCase = ''): string {
180
+ * @returns {string} 'a_b_c'
181
+ */
182
+ export function camelCase2Underscore(camelCase: string): string {
180
183
  const kebabCase = camelCase.replace(/([A-Z])/g, '_$1').toLowerCase();
181
184
  return kebabCase[0] === '_' ? kebabCase.substr(1) : kebabCase;
182
185
  }
@@ -185,9 +188,9 @@ export function camelCase2Underscore(camelCase = ''): string {
185
188
  * @method mTrim
186
189
  * @description Remove leading and trailing whitespace or specified characters from string.
187
190
  * @param {string} str The string to trim.
188
- * @return {string} Trimmed string.
189
- * */
190
- export function mTrim(str = ''): string {
191
+ * @returns {string} Trimmed string.
192
+ */
193
+ export function mTrim(str: string): string {
191
194
  str = str.replace(/^\s+/, ''); // 去除头部空格
192
195
  let end = str.length - 1;
193
196
  const ws = /\s/;
@@ -201,9 +204,9 @@ export function mTrim(str = ''): string {
201
204
  * @method newLine
202
205
  * @description Make a newline of HTML.
203
206
  * @param {string} str The string to make a newline.
204
- * @return {string} A newline with `br`.
205
- * */
206
- export function newLine(str = ''): string {
207
+ * @returns {string} A newline with `br`.
208
+ */
209
+ export function newLine(str: string): string {
207
210
  if (!str) {
208
211
  return '';
209
212
  }
@@ -215,8 +218,8 @@ export function newLine(str = ''): string {
215
218
  * @method deepCopyObject
216
219
  * @description Clone Object deeply.
217
220
  * @param {object} obj The value to clone.
218
- * @return {object} Returns the deep cloned value.
219
- * */
221
+ * @returns {object} Returns the deep cloned value.
222
+ */
220
223
  export function deepCopyObject(obj: any): any {
221
224
  return JSON.parse(JSON.stringify(obj));
222
225
  }
@@ -225,9 +228,9 @@ export function deepCopyObject(obj: any): any {
225
228
  * @method isJsonString
226
229
  * @description Check whether it is a valid JSON string.
227
230
  * @param {string} str The string to check.
228
- * @return {boolean} Return the result of checking.
229
- * */
230
- export function isJsonString(str = ''): boolean {
231
+ * @returns {boolean} Return the result of checking.
232
+ */
233
+ export function isJsonString(str: string): boolean {
231
234
  try {
232
235
  if (typeof JSON.parse(str) === 'object') {
233
236
  return true;
@@ -242,8 +245,8 @@ export function isJsonString(str = ''): boolean {
242
245
  * @method generateRndNum
243
246
  * @description Produce a random string of number, `generateRndNum(7)` => '7658495'.
244
247
  * @param {number} n Length
245
- * @return {string} Return the random string.
246
- * */
248
+ * @returns {string} Return the random string.
249
+ */
247
250
  export function generateRndNum(n = 5): string {
248
251
  let ret = '';
249
252
  while (n--) {
@@ -256,7 +259,7 @@ export function generateRndNum(n = 5): string {
256
259
  * @method generateUniqueNum
257
260
  * @description 根据时间生成唯一标志的数字 mGenerateUniqueNum() => 1538324722364123。
258
261
  * @param {number} n 随机数的长度
259
- * */
262
+ */
260
263
  export function generateUniqueNum(n = 3): string {
261
264
  const [now, rnd] = [mNow(), generateRndNum(n || 3)];
262
265
  return now + rnd;
@@ -267,8 +270,8 @@ export function generateUniqueNum(n = 3): string {
267
270
  * @description 浮点数转为百分比 0.2 => 20%。
268
271
  * @param {number} num 浮点数
269
272
  * @param {number} fixSize 保留几位浮点数
270
- * */
271
- export function floatToPercent(num = 0, fixSize = 0): string {
273
+ */
274
+ export function floatToPercent(num: number, fixSize = 0): string {
272
275
  let ret = '';
273
276
  if (fixSize) {
274
277
  ret = (num * 100).toFixed(fixSize);
@@ -281,7 +284,7 @@ export function floatToPercent(num = 0, fixSize = 0): string {
281
284
  /**
282
285
  * @method floatFixed
283
286
  * @description 浮点数保留指定位。
284
- * */
287
+ */
285
288
  export function floatFixed(num: string, size = 0): string {
286
289
  return parseFloat(num).toFixed(size);
287
290
  }
@@ -289,7 +292,7 @@ export function floatFixed(num: string, size = 0): string {
289
292
  /**
290
293
  * @method cancelBubble
291
294
  * @description 阻止冒泡。
292
- * */
295
+ */
293
296
  export function cancelBubble(e: any): void {
294
297
  const ev = e || window.event;
295
298
  if (ev.stopPropagation) {
@@ -303,7 +306,7 @@ export function cancelBubble(e: any): void {
303
306
 
304
307
  /**
305
308
  * @method hasClass
306
- * */
309
+ */
307
310
  export function hasClass(obj: any, cls: string): boolean {
308
311
  const oriCls = obj.className; // 获取对象的class值
309
312
  const oriClsArr = oriCls.split(/\s+/); // 分隔空格转换成数组
@@ -317,7 +320,7 @@ export function hasClass(obj: any, cls: string): boolean {
317
320
 
318
321
  /**
319
322
  * @method addClass
320
- * */
323
+ */
321
324
  export function addClass(obj: any, cls: string): void {
322
325
  const oriCls = obj.className;
323
326
  let space = '';
@@ -331,7 +334,7 @@ export function addClass(obj: any, cls: string): void {
331
334
 
332
335
  /**
333
336
  * @method removeClass
334
- * */
337
+ */
335
338
  export function removeClass(obj: any, cls: string): void {
336
339
  const oriCls = obj.className;
337
340
  let newCls; // 获取对象的class值
@@ -343,19 +346,25 @@ export function removeClass(obj: any, cls: string): void {
343
346
  }
344
347
 
345
348
  /**
346
- * @method throttle
347
- * @description 节流。
348
- * */
349
- export function throttle(func: any, wait: number, options: any): any {
349
+ * EN: Throttle
350
+ * ZH: 节流
351
+ *
352
+ * @see https://lodash.com/docs/4.17.15#throttle
353
+ */
354
+ export function throttle(func: any, wait: number, options: { leading?: boolean; trailing?: boolean; } = {}): any {
355
+ options = Object.assign(
356
+ {},
357
+ options,
358
+ );
350
359
  // timeout: setTimeout Handle
351
360
  // previous: 上次时间戳
352
361
  let context: any = null;
353
362
  let args: any = null;
354
363
  let timeout: any = null;
355
364
  let [result, previous] = [null, 0];
356
- if (!options) {
357
- options = {};
358
- }
365
+ // if (!options) {
366
+ // options = {};
367
+ // }
359
368
  const later = function () {
360
369
  previous = options.leading === false ? 0 : mNow();
361
370
  timeout = null;
@@ -390,10 +399,11 @@ export function throttle(func: any, wait: number, options: any): any {
390
399
  }
391
400
 
392
401
  /**
393
- * @method debounce
394
- * @description 去抖。
395
- * */
396
- export function debounce(func: any, wait: number, immediate: any): any {
402
+ * EN: Debounce
403
+ *
404
+ * ZH: 去抖
405
+ */
406
+ export function debounce(func: any, wait: number, immediate?: any): any {
397
407
  let context: any = null;
398
408
  let timeout: any = null;
399
409
  let timestamp: any = null;
@@ -434,14 +444,15 @@ export function debounce(func: any, wait: number, immediate: any): any {
434
444
  * @description 获取间隔时间。
435
445
  * @param {number/Date} start 开始时间戳 1585325367122
436
446
  * @param {number/Date} end 结束时间戳 1585325367122
437
- * @type {string} type 返回类型 d: 2(天) text: 2 天 4 时...
438
- * @return {String/number} 取决于 type
439
- * */
440
- export function friendlyInterval(start = 0, end = 0, { type = 'd' } = {}): number | string {
447
+ * @param {string} options.type 返回类型 d: 2(天) text: 2 天 4 时...
448
+ * @returns {String/number} 取决于 type
449
+ */
450
+ export function friendlyInterval(start = 0, end = 0, options: { type?: string; } = { type: 'd' }): number | string {
451
+ const { type } = options;
441
452
  if (!isNumber(start)) start = new Date(start).getTime();
442
453
  if (!isNumber(end)) end = new Date(end).getTime();
443
454
  const t = end - start;
444
- let ret = null;
455
+ let ret = '';
445
456
  let [d, h, m, s] = new Array(4).fill(0);
446
457
  if (t >= 0) {
447
458
  d = Math.floor(t / 1000 / 60 / 60 / 24);
@@ -470,11 +481,15 @@ export function friendlyInterval(start = 0, end = 0, { type = 'd' } = {}): numbe
470
481
  * @method isNumber
471
482
  * @description 判断是否有效数字
472
483
  * @param {*} num 被判断的值
473
- * @param {boolean} isNaNAsNumber 是否 NaN 算数字(默认不算)
474
- * @param {boolean} isUnFiniteAsNumber 是否 无限 算数字(默认不算)
475
- * @return {boolean} true 是数字
484
+ * @param {boolean} options.isNaNAsNumber 是否 NaN 算数字(默认不算)
485
+ * @param {boolean} options.isUnFiniteAsNumber 是否 无限 算数字(默认不算)
486
+ * @returns {boolean} true 是数字
476
487
  */
477
- export function isNumber(num: any, { isNaNAsNumber = false, isUnFiniteAsNumber = false } = {}): boolean {
488
+ export function isNumber(num: any, options: { isNaNAsNumber?: boolean; isUnFiniteAsNumber?: boolean; } = { isNaNAsNumber: false, isUnFiniteAsNumber: false }): boolean {
489
+ const { isNaNAsNumber, isUnFiniteAsNumber } = Object.assign(
490
+ { isNaNAsNumber: false, isUnFiniteAsNumber: false },
491
+ options,
492
+ );
478
493
  let ret = true;
479
494
  // 数字类型
480
495
  if (typeof num !== 'number') {
@@ -497,7 +512,7 @@ export function isNumber(num: any, { isNaNAsNumber = false, isUnFiniteAsNumber =
497
512
  * @method doFn
498
513
  * @description 执行有效函数
499
514
  * @param {function} fn 等待被执行的未知是否有效的函数
500
- * */
515
+ */
501
516
  export function doFn(fn: any, ...params: any[]): any {
502
517
  let ret = null;
503
518
  if (fn && typeof fn === 'function') {
@@ -511,7 +526,7 @@ export function doFn(fn: any, ...params: any[]): any {
511
526
  * @description 存储数据到 sessionStorage
512
527
  * @param {string} key 键
513
528
  * @param {string} value 值
514
- * */
529
+ */
515
530
  export function setSessionStorage(key: string, value: any = null): void {
516
531
  if (key) {
517
532
  sessionStorage.setItem(key, JSON.stringify(value));
@@ -522,8 +537,8 @@ export function setSessionStorage(key: string, value: any = null): void {
522
537
  * @method getSessionStorage
523
538
  * @description 存储数据到 sessionStorage
524
539
  * @param {string} key 键
525
- * @return {*} 返回值
526
- * */
540
+ * @returns {*} 返回值
541
+ */
527
542
  export function getSessionStorage(key: string): any {
528
543
  let ret = null;
529
544
  if (key) {
@@ -540,7 +555,7 @@ export function getSessionStorage(key: string): any {
540
555
  * @description 存储数据到 localStorage
541
556
  * @param {string} key 键
542
557
  * @param {string} value 值
543
- * */
558
+ */
544
559
  export function setLocalStorage(key: string, value: any = null): void {
545
560
  if (key) {
546
561
  localStorage.setItem(key, JSON.stringify(value));
@@ -551,8 +566,8 @@ export function setLocalStorage(key: string, value: any = null): void {
551
566
  * @method getLocalStorage
552
567
  * @description 存储数据到 localStorage
553
568
  * @param {string} key 键
554
- * @return {*} 返回值
555
- * */
569
+ * @returns {*} 返回值
570
+ */
556
571
  export function getLocalStorage(key: string): any {
557
572
  let ret = null;
558
573
  if (key) {
@@ -568,18 +583,20 @@ export function getLocalStorage(key: string): any {
568
583
  * @method loadCSS
569
584
  * @description 动态加载css文件
570
585
  * @param {string} url -- css资源路径
571
- * @param {string} id -- link标签id
572
- * @return {Promise<boolean>} true -- 加载成功
586
+ * @param {string} options.id -- link标签id
587
+ * @returns {Promise<boolean>} true -- 加载成功
573
588
  */
574
- export function loadCSS(url = '', { id = '' } = {}): Promise<any> {
575
- let success: any = null;
576
- let fail: any = null;
589
+ export function loadCSS(url: string, options: { id?: string } = { id: '' }): Promise<boolean | Error | any> {
590
+ const { id } = options;
591
+ let success: (v: boolean) => void;
592
+ let fail: (v: Error) => void;
577
593
  const status = new Promise((resolve, reject) => {
578
594
  ([success, fail] = [resolve, reject]);
579
595
  });
580
596
  // const tempCB = (typeof callback === 'function' ? callback : function () { });
581
597
  const callback = function () {
582
- doFn(success, true);
598
+ // doFn(success, true);
599
+ success(true);
583
600
  };
584
601
  let node: any = document.createElement('link');
585
602
  const supportOnload = 'onload' in node;
@@ -689,13 +706,22 @@ export function loadCSS(url = '', { id = '' } = {}): Promise<any> {
689
706
  * @method loadScript
690
707
  * @description 动态加载js文件
691
708
  * @param {string} url -- js资源路径
692
- * @param {string} id -- DOM ID
693
- * @param {function} callback -- 加载后回调函数
694
- * @param {number} timeout -- 超时时长
695
- * @param {boolean} isDefer -- 是否添加 defer 标签
696
- * @return {Promise<boolean>} -- true 成功
709
+ * @param {string} options.id -- DOM ID
710
+ * @param {function} options.callback -- 加载后回调函数
711
+ * @param {number} options.timeout -- 超时时长
712
+ * @param {boolean} options.isDefer -- 是否添加 defer 标签
713
+ * @returns {Promise<boolean>} -- true 成功
697
714
  */
698
- export function loadScript(url = '', { id = '', callback = function () { /* pass */ }, timeout = 5000, isDefer = false } = {}): Promise<any> {
715
+ export function loadScript(url: string, options: {
716
+ id: string;
717
+ callback: (...params: any[]) => any;
718
+ timeout: number;
719
+ isDefer: boolean;
720
+ } = { id: '', callback: function () { /* pass */ }, timeout: 5000, isDefer: false }): Promise<boolean | string | Error> {
721
+ const { id, callback, timeout, isDefer } = Object.assign(
722
+ { id: '', callback: function () { /* pass */ }, timeout: 5000, isDefer: false },
723
+ options,
724
+ );
699
725
  let success: any = null;
700
726
  let fail: any = null;
701
727
  const script: any = document.createElement('script');
@@ -729,7 +755,7 @@ export function loadScript(url = '', { id = '', callback = function () { /* pass
729
755
  return new Promise((resolve, reject) => {
730
756
  ([success, fail] = [resolve, reject]);
731
757
  if (timeout) {
732
- setTimeout(fail.bind(null, 'timeout'), timeout);
758
+ setTimeout(fail.bind(null, Error('timeout')), timeout);
733
759
  }
734
760
  });
735
761
  }
@@ -807,16 +833,20 @@ export function getCookie(name: string): string {
807
833
  return '';
808
834
  }
809
835
 
836
+ interface WebPerformance {
837
+ [key: string]: string | number;
838
+ }
839
+
810
840
  /**
811
841
  * @method getPerformance
812
842
  * @description 获取页面加载相关的各项数据
813
843
  * @param {boolean} camelCase -- true(默认) 以驼峰形式返回数据 false 以下划线形式返回数据
814
- * @return {Promise<object>} 加载数据
844
+ * @returns {Promise<object>} 加载数据
815
845
  */
816
- export function getPerformance(camelCase = true): Promise<any> {
817
- let success: any;
818
- let fail: any;
819
- const status = new Promise((resolve, reject) => {
846
+ export function getPerformance(camelCase = true): Promise<WebPerformance | Error> {
847
+ let success: (v: WebPerformance) => void;
848
+ let fail: (v: Error) => void;
849
+ const status: Promise<WebPerformance> = new Promise((resolve, reject) => {
820
850
  ([success, fail] = [resolve, reject]);
821
851
  });
822
852
  const timing = window.performance.timing;
@@ -909,10 +939,10 @@ export function getPerformance(camelCase = true): Promise<any> {
909
939
  }
910
940
  success(Underscore || data);
911
941
  } else {
912
- fail('startTime');
942
+ fail(Error('startTime'));
913
943
  }
914
944
  } else {
915
- fail('getEntries');
945
+ fail(Error('getEntries'));
916
946
  }
917
947
  }
918
948
  //获取当前操作系统
@@ -1021,7 +1051,7 @@ export function getPerformance(camelCase = true): Promise<any> {
1021
1051
  * @method inRate
1022
1052
  * @description 百分位概率
1023
1053
  * @param {number} rate -- 0.1 ~ 1 => 1% ~ 100%
1024
- * @return {boolean} true 命中
1054
+ * @returns {boolean} true 命中
1025
1055
  */
1026
1056
  export function inRate(rate: number): boolean {
1027
1057
  if(Math.random() < rate) {
@@ -1033,7 +1063,7 @@ export function inRate(rate: number): boolean {
1033
1063
  /**
1034
1064
  * @method isSafePWAEnv
1035
1065
  * @description 判断是否是安全的 PWA 环境
1036
- * @return {boolean} true 是
1066
+ * @returns {boolean} true 是
1037
1067
  */
1038
1068
  export function isSafePWAEnv(): boolean {
1039
1069
  // 判断是否支持 async await
@@ -1076,16 +1106,53 @@ export function isSafePWAEnv(): boolean {
1076
1106
  }
1077
1107
 
1078
1108
  /**
1079
- * @method getBrowserInfo
1080
- * @description 返回浏览器信息 https://github.com/JowayYoung/juejin-code/blob/master/browser-type.js
1081
- * @return {object} 浏览器信息
1109
+ * EN: Browser Information
1110
+ *
1111
+ * ZH: 返回浏览器信息 https://github.com/JowayYoung/juejin-code/blob/master/browser-type.js
1112
+ *
1113
+ * ```
1114
+ * getBrowserInfo(); // {"engine":"webkit","engineVs":"537.36","platform":"desktop","supporter":"chrome","supporterVs":"85.0.4183.121","system":"windows","systemVs":"10"}
1115
+ * ```
1116
+ *
1117
+ * | Index | Field | Description |
1118
+ * | --- | --- | --- |
1119
+ * | System | system | android, ios, windows, macos, linux |
1120
+ * | System version | systemVs | windows: 2000, xp, 2003, vista, 7, 8, 8.1, 10 <br />macos: ... |
1121
+ * | Platform | platform | desktop, mobile |
1122
+ * | Engine | engine | webkit, gecko, presto, trident |
1123
+ * | Engine version | engineVs | - |
1124
+ * | Supporter | supporter | edge, opera, chrome, safari, firefox, iexplore |
1125
+ * | Supporter version | supporterVs | - |
1126
+ * | Shell | shell | (Optional) wechat, qq_browser, qq_app, uc, 360, 2345, sougou, liebao, maxthon, bilibili |
1127
+ * | Shell version | shellVs | (Optional) |
1128
+ * | Apple device type | appleType | (Optional) iphone, ipad, ipod, iwatch |
1129
+ *
1130
+ * Example: Determine the environment of the mobile QQ.
1131
+ *
1132
+ * ```
1133
+ * const { system, shell } = getBrowserInfo();
1134
+ * const isMobileQQ = ['android', 'ios'].includes(system) && ['qq_browser', 'qq_app'].includes(shell);
1135
+ * ```
1136
+ *
1137
+ * @returns 浏览器信息
1082
1138
  */
1083
- export function getBrowserInfo(): any {
1139
+ export function getBrowserInfo(): {
1140
+ engine: string; // webkit gecko presto trident
1141
+ engineVs: string;
1142
+ platform: string; // desktop mobile
1143
+ supporter: string; // chrome safari firefox opera iexplore edge
1144
+ supporterVs: string;
1145
+ system: string; // windows macos linux android ios
1146
+ systemVs: string;
1147
+ shell?: string; // wechat qq uc 360 2345 sougou liebao maxthon
1148
+ shellVs?: string;
1149
+ appleType?: string;
1150
+ } {
1084
1151
  try {
1085
1152
  // 权重:系统 + 系统版本 > 平台 > 内核 + 载体 + 内核版本 + 载体版本 > 外壳 + 外壳版本
1086
- const ua: any = navigator.userAgent.toLowerCase();
1087
- const testUa: (regexp: any) => any = regexp => regexp.test(ua);
1088
- const testVs: (regexp: any) => any = regexp => {
1153
+ const ua: string = navigator.userAgent.toLowerCase();
1154
+ const testUa: (regexp: RegExp) => boolean = regexp => regexp.test(ua);
1155
+ const testVs: (regexp: RegExp) => string = regexp => {
1089
1156
  const matchRes = ua.match(regexp);
1090
1157
  let ret = '';
1091
1158
  if (matchRes) {
@@ -1248,18 +1315,26 @@ export function getBrowserInfo(): any {
1248
1315
  });
1249
1316
  } catch (err) {
1250
1317
  console.warn('mazey:', err);
1251
- return {};
1318
+ return {
1319
+ engine: '', // webkit gecko presto trident
1320
+ engineVs: '',
1321
+ platform: '', // desktop mobile
1322
+ supporter: '', // chrome safari firefox opera iexplore edge
1323
+ supporterVs: '',
1324
+ system: '', // windows macos linux android ios
1325
+ systemVs: '',
1326
+ };
1252
1327
  }
1253
1328
  }
1254
1329
 
1255
1330
  /**
1256
1331
  * @method clearHtml
1257
1332
  * @description 去除HTML标签
1258
- * @param {string} string 带html标签的字符串
1259
- * @return {string} 字符串
1333
+ * @param {string} str 带html标签的字符串
1334
+ * @returns {string} 字符串
1260
1335
  */
1261
- export function clearHtml (string = ''): string {
1262
- return string.replace(/<\/?.+?>/g, '').replace(/[\r\n]/g, '');
1336
+ export function clearHtml (str: string): string {
1337
+ return str.replace(/<\/?.+?>/g, '').replace(/[\r\n]/g, '');
1263
1338
  }
1264
1339
 
1265
1340
  /**
@@ -1268,9 +1343,9 @@ export function clearHtml (string = ''): string {
1268
1343
  * @param {string} str 要截取的字符串
1269
1344
  * @param {number} len
1270
1345
  * @param {boolean} hasDot
1271
- * @returns {string} 返回截取后的字符串
1346
+ * @returnss {string} 返回截取后的字符串
1272
1347
  */
1273
- export function cutCHSString(str = '', len = str.length, hasDot = false): string {
1348
+ export function cutCHSString(str: string, len: number, hasDot = false): string {
1274
1349
  if (str == '' || !str) {
1275
1350
  return '';
1276
1351
  } else {
@@ -1304,12 +1379,12 @@ export function cutCHSString(str = '', len = str.length, hasDot = false): string
1304
1379
  * @method windowLoaded
1305
1380
  * @description 页面加载完成
1306
1381
  * @param {number} timeout 超时时间 / 单位:秒
1307
- * @return {Promise<string>} document is loaded? 'complete' 'load' / 'timeout'
1308
- */
1309
- export function windowLoaded(timeout = 90): Promise<string> {
1382
+ * @returns {Promise<string>} document is loaded? 'complete' 'load' / 'timeout'
1383
+ */
1384
+ export function windowLoaded(timeout = 90): Promise<string | Error> {
1310
1385
  let loaded: (value: string) => void = () => undefined;
1311
- let loadFail: (value: string) => void = () => undefined;
1312
- const status = new Promise((resolve: (value: string) => void, reject: (value: string) => void) => {
1386
+ let loadFail: (value: Error) => void;
1387
+ const status = new Promise((resolve: (value: string) => void, reject: (value: Error) => void) => {
1313
1388
  loaded = resolve;
1314
1389
  loadFail = reject;
1315
1390
  });
@@ -1319,42 +1394,83 @@ export function windowLoaded(timeout = 90): Promise<string> {
1319
1394
  window.addEventListener('load', () => loaded('load'));
1320
1395
  }
1321
1396
  // 超过 timeout 秒后加载失败
1322
- setTimeout(() => loadFail('timeout'), timeout * 1000);
1397
+ setTimeout(() => loadFail(Error('timeout')), timeout * 1000);
1323
1398
  return status;
1324
1399
  }
1325
1400
 
1326
1401
  /**
1327
- * @method addInlineStyle
1328
- * @description 添加内联样式
1329
- * @param {string} inlineStyle 内联样式字符串
1330
- * @param {string} id style 标签的 ID
1331
- * @return {boolean} 添加成功/失败
1332
- */
1333
- export function addInlineStyle(inlineStyle = '', { id = '' } = {}): boolean {
1334
- if (!inlineStyle) {
1402
+ * EN: Add `<style>` in `<head>`.
1403
+ *
1404
+ * ZH: 添加样式标签; style: 样式标签内的字符串; id: `<style>` 标签的 `id`; 返回: 添加成功/失败.
1405
+ *
1406
+ * Example 1: Add the `<style>` with `id`, and repeated invoking will update the content instead of adding a new one.
1407
+ *
1408
+ * ```
1409
+ * addStyle(
1410
+ * `
1411
+ * body {
1412
+ * background-color: #333;
1413
+ * }
1414
+ * `,
1415
+ * {
1416
+ * id: 'test',
1417
+ * }
1418
+ * );
1419
+ * // <style id="test">
1420
+ * // body {
1421
+ * // background-color: #333;
1422
+ * // }
1423
+ * // </style>
1424
+ * ```
1425
+ *
1426
+ * Example 2: Add the `<style>` without `id`, and repeated invoking will adding a new one.
1427
+ *
1428
+ * ```
1429
+ * addStyle(
1430
+ * `
1431
+ * body {
1432
+ * background-color: #333;
1433
+ * }
1434
+ * `
1435
+ * );
1436
+ * // <style>
1437
+ * // body {
1438
+ * // background-color: #333;
1439
+ * // }
1440
+ * // </style>
1441
+ * ```
1442
+ *
1443
+ * @param style Style string.
1444
+ * @param options.id `id` in `<style>`
1445
+ * @returns Success/Fail
1446
+ */
1447
+ export function addStyle(style: string, options: { id?: string; } = { id: '' }): boolean {
1448
+ // console.log('_ style', style);
1449
+ // console.log('_ options', options);
1450
+ if (!style) {
1335
1451
  return false;
1336
1452
  }
1337
1453
  // 创建 style 文档碎片
1338
1454
  const styleFrag = document.createDocumentFragment();
1339
- let idDom = null;
1455
+ let idDom: HTMLElement | null = null;
1340
1456
  let domId = '';
1341
1457
  // Custom Style
1342
1458
  const customStyle = document.createElement('style');
1343
1459
  // 如果需要 ID
1344
- if (id) {
1345
- domId = `${id}`;
1460
+ if (options.id) {
1461
+ domId = `${options.id}`;
1346
1462
  idDom = document.getElementById(domId);
1347
1463
  // 如果 Dom 不存在,插入 style
1348
1464
  if (!idDom) {
1349
- customStyle.setAttribute('id', id);
1350
- customStyle.innerHTML = inlineStyle;
1465
+ customStyle.setAttribute('id', options.id);
1466
+ customStyle.innerHTML = style;
1351
1467
  styleFrag.appendChild(customStyle);
1352
1468
  document.head.appendChild(styleFrag);
1353
1469
  } else { // 如果 Dom 存在,直接更新
1354
- idDom.innerHTML = inlineStyle;
1470
+ idDom.innerHTML = style;
1355
1471
  }
1356
1472
  } else { // 不需要 ID,直接添加新标签
1357
- customStyle.innerHTML = inlineStyle;
1473
+ customStyle.innerHTML = style;
1358
1474
  styleFrag.appendChild(customStyle);
1359
1475
  document.head.appendChild(styleFrag);
1360
1476
  }
@@ -1366,9 +1482,9 @@ export function addInlineStyle(inlineStyle = '', { id = '' } = {}): boolean {
1366
1482
  * @description 生成自定义控制台打印
1367
1483
  * @param {string} prefix 前缀
1368
1484
  * @param {function} allowFn 允许打印的判断函数
1369
- * @return {object} 新实例
1370
- */
1371
- export function genCustomConsole(prefix = ''): any {
1485
+ * @returns {object} 新实例
1486
+ */
1487
+ export function genCustomConsole(prefix = ''): Console {
1372
1488
  const methods = ['log', 'info', 'warn', 'error'];
1373
1489
  const newConsole = Object.create(null);
1374
1490
  methods.forEach(method => {
@@ -1382,3 +1498,98 @@ export function genCustomConsole(prefix = ''): any {
1382
1498
  });
1383
1499
  return newConsole;
1384
1500
  }
1501
+
1502
+ /**
1503
+ * Verify the validity of axios response.
1504
+ */
1505
+ export function zAxiosIsValidRes(res: any, options: {
1506
+ validStatus: number[];
1507
+ validCode: number[];
1508
+ } = {
1509
+ validStatus: [200],
1510
+ validCode: [0],
1511
+ }): boolean {
1512
+ const { validStatus, validCode } = Object.assign(
1513
+ {
1514
+ validStatus: [200],
1515
+ validCode: [0],
1516
+ },
1517
+ options,
1518
+ );
1519
+ let ret = false;
1520
+ if (res && res.status && validStatus.includes(res.status)) {
1521
+ ret = true;
1522
+ const resData = res.data;
1523
+ if (resData && validCode.includes(resData.code)) {
1524
+ ret = true;
1525
+ }
1526
+ }
1527
+ return ret;
1528
+ }
1529
+
1530
+ /**
1531
+ * Verify the validity of a non-empty array.
1532
+ */
1533
+ export function isNonEmptyArray(arr: any[]): boolean {
1534
+ let ret = false;
1535
+ if (Array.isArray(arr) && arr.length) {
1536
+ ret = true;
1537
+ }
1538
+ return ret;
1539
+ }
1540
+
1541
+ /**
1542
+ * 语义化文件大小, 把字节转换成正常文件大小.
1543
+ */
1544
+ export function getFileSize(size: number): string {
1545
+ const toCeilStr: (v: number) => string = n => String(Math.ceil(n));
1546
+ if (!size) return '';
1547
+ const num = 1024.0; // byte
1548
+ if (size < num) {
1549
+ return size + ' B';
1550
+ }
1551
+ if (size < Math.pow(num, 2)) {
1552
+ return toCeilStr(size / num) + ' KB';
1553
+ } // kb
1554
+ if (size < Math.pow(num, 3)) {
1555
+ return toCeilStr(size / Math.pow(num, 2)) + ' MB';
1556
+ } // M
1557
+ if (size < Math.pow(num, 4)) {
1558
+ return toCeilStr(size / Math.pow(num, 3)) + ' G';
1559
+ } // G
1560
+ return toCeilStr(size / Math.pow(num, 4)) + ' T';
1561
+ }
1562
+
1563
+ /**
1564
+ * Detect webp support.
1565
+ *
1566
+ * @see https://davidwalsh.name/detect-webp
1567
+ */
1568
+ export function isSupportWebp(): Promise<boolean> {
1569
+ const fn = (resolve: (v: boolean) => void) => {
1570
+ const img = new Image();
1571
+ img.onload = () => {
1572
+ resolve(img.width > 0 && img.height > 0);
1573
+ };
1574
+ img.onerror = () => {
1575
+ resolve(false);
1576
+ };
1577
+ img.src = "data:image/webp;base64,UklGRh4AAABXRUJQVlA4TBEAAAAvAAAAAAfQ//73v/+BiOh/AAA=";
1578
+ };
1579
+ return new Promise(fn);
1580
+ }
1581
+
1582
+ /**
1583
+ * Generate a Hash Code from a string.
1584
+ *
1585
+ * @see https://stackoverflow.com/questions/7616461/generate-a-hash-from-string-in-javascript-jquery
1586
+ */
1587
+ export function genHashCode(str: string): number {
1588
+ let hash = 0, i, chr;
1589
+ for (i = 0; i < str.length; i++) {
1590
+ chr = str.charCodeAt(i);
1591
+ hash = ((hash << 5) - hash) + chr;
1592
+ hash |= 0;
1593
+ }
1594
+ return hash;
1595
+ }