sculp-js 0.0.2 → 1.0.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/LICENSE.md +1 -1
- package/README.md +22 -1
- package/lib/cjs/array.js +32 -55
- package/lib/cjs/async.js +3 -3
- package/lib/cjs/clipboard.js +3 -3
- package/lib/cjs/cookie.js +5 -5
- package/lib/cjs/date.js +142 -24
- package/lib/cjs/dom.js +24 -10
- package/lib/cjs/download.js +9 -9
- package/lib/cjs/easing.js +1 -1
- package/lib/cjs/file.js +5 -4
- package/lib/cjs/func.js +160 -0
- package/lib/cjs/index.js +28 -2
- package/lib/cjs/number.js +82 -0
- package/lib/cjs/object.js +13 -11
- package/lib/cjs/path.js +1 -1
- package/lib/cjs/qs.js +5 -5
- package/lib/cjs/random.js +72 -0
- package/lib/cjs/string.js +40 -7
- package/lib/cjs/type.js +12 -2
- package/lib/cjs/unique.js +83 -0
- package/lib/cjs/url.js +1 -1
- package/lib/cjs/watermark.js +8 -9
- package/lib/es/array.js +33 -55
- package/lib/es/async.js +3 -3
- package/lib/es/clipboard.js +3 -3
- package/lib/es/cookie.js +5 -5
- package/lib/es/date.js +139 -25
- package/lib/es/dom.js +24 -11
- package/lib/es/download.js +9 -9
- package/lib/es/easing.js +1 -1
- package/lib/es/file.js +5 -4
- package/lib/es/func.js +154 -0
- package/lib/es/index.js +10 -6
- package/lib/es/number.js +77 -0
- package/lib/es/object.js +12 -10
- package/lib/es/path.js +1 -1
- package/lib/es/qs.js +5 -5
- package/lib/es/random.js +67 -0
- package/lib/es/string.js +40 -8
- package/lib/es/type.js +12 -3
- package/lib/es/unique.js +79 -0
- package/lib/es/url.js +1 -1
- package/lib/es/watermark.js +8 -9
- package/lib/index.d.ts +254 -80
- package/lib/umd/index.js +637 -132
- package/package.json +36 -12
package/lib/es/download.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* sculp-js
|
|
2
|
+
* sculp-js v1.0.0
|
|
3
3
|
* (c) 2023-2023 chandq
|
|
4
4
|
* Released under the MIT License.
|
|
5
5
|
*/
|
|
@@ -11,15 +11,15 @@ import { urlSetParams } from './url.js';
|
|
|
11
11
|
* @param {string} url
|
|
12
12
|
* @param {LooseParams} params
|
|
13
13
|
*/
|
|
14
|
-
|
|
14
|
+
function downloadURL(url, params) {
|
|
15
15
|
window.open(params ? urlSetParams(url, params) : url);
|
|
16
|
-
}
|
|
16
|
+
}
|
|
17
17
|
/**
|
|
18
18
|
* 通过 A 链接的方式下载
|
|
19
19
|
* @param {string} href
|
|
20
20
|
* @param {string} filename
|
|
21
21
|
*/
|
|
22
|
-
|
|
22
|
+
function downloadHref(href, filename) {
|
|
23
23
|
const eleLink = document.createElement('a');
|
|
24
24
|
eleLink.download = filename;
|
|
25
25
|
eleLink.style.display = 'none';
|
|
@@ -27,17 +27,17 @@ const downloadHref = (href, filename) => {
|
|
|
27
27
|
document.body.appendChild(eleLink);
|
|
28
28
|
eleLink.click();
|
|
29
29
|
setTimeout(() => document.body.removeChild(eleLink));
|
|
30
|
-
}
|
|
30
|
+
}
|
|
31
31
|
/**
|
|
32
32
|
* 将大文件对象通过 A 链接的方式下载
|
|
33
33
|
* @param {Blob} blob
|
|
34
34
|
* @param {string} filename
|
|
35
35
|
*/
|
|
36
|
-
|
|
36
|
+
function downloadBlob(blob, filename) {
|
|
37
37
|
const objURL = URL.createObjectURL(blob);
|
|
38
38
|
downloadHref(objURL, filename);
|
|
39
39
|
setTimeout(() => URL.revokeObjectURL(objURL));
|
|
40
|
-
}
|
|
40
|
+
}
|
|
41
41
|
/**
|
|
42
42
|
* 将指定数据格式通过 A 链接的方式下载
|
|
43
43
|
* @param {AnyObject | AnyObject[]} data
|
|
@@ -45,7 +45,7 @@ const downloadBlob = (blob, filename) => {
|
|
|
45
45
|
* @param {string} filename
|
|
46
46
|
* @param {string[]} [headers]
|
|
47
47
|
*/
|
|
48
|
-
|
|
48
|
+
function downloadData(data, fileType, filename, headers) {
|
|
49
49
|
filename = filename.replace(`.${fileType}`, '') + `.${fileType}`;
|
|
50
50
|
if (fileType === 'json') {
|
|
51
51
|
const blob = new Blob([JSON.stringify(data, null, 4)]);
|
|
@@ -72,6 +72,6 @@ const downloadData = (data, fileType, filename, headers) => {
|
|
|
72
72
|
const href = 'data:' + MIMETypes[fileType] + ';charset=utf-8,\ufeff' + encodeURIComponent(headerStr + bodyStr);
|
|
73
73
|
downloadHref(href, filename);
|
|
74
74
|
}
|
|
75
|
-
}
|
|
75
|
+
}
|
|
76
76
|
|
|
77
77
|
export { downloadBlob, downloadData, downloadHref, downloadURL };
|
package/lib/es/easing.js
CHANGED
package/lib/es/file.js
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* sculp-js
|
|
2
|
+
* sculp-js v1.0.0
|
|
3
3
|
* (c) 2023-2023 chandq
|
|
4
4
|
* Released under the MIT License.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* 选择本地文件
|
|
9
|
-
* @param {
|
|
10
|
-
* @
|
|
9
|
+
* @param {string} accept 上传的文件类型,用于过滤
|
|
10
|
+
* @param {Function} changeCb 选择文件回调
|
|
11
|
+
* @returns {HTMLInputElement}
|
|
11
12
|
*/
|
|
12
|
-
function chooseLocalFile(
|
|
13
|
+
function chooseLocalFile(accept, changeCb) {
|
|
13
14
|
const inputObj = document.createElement('input');
|
|
14
15
|
inputObj.setAttribute('id', String(Date.now()));
|
|
15
16
|
inputObj.setAttribute('type', 'file');
|
package/lib/es/func.js
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* sculp-js v1.0.0
|
|
3
|
+
* (c) 2023-2023 chandq
|
|
4
|
+
* Released under the MIT License.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* 防抖函数
|
|
9
|
+
* 当函数被连续调用时,该函数并不执行,只有当其全部停止调用超过一定时间后才执行1次。
|
|
10
|
+
* 例如:上电梯的时候,大家陆陆续续进来,电梯的门不会关上,只有当一段时间都没有人上来,电梯才会关门。
|
|
11
|
+
* @param {F} func
|
|
12
|
+
* @param {number} wait
|
|
13
|
+
* @returns {DebounceFunc<F>}
|
|
14
|
+
*/
|
|
15
|
+
const debounce = (func, wait) => {
|
|
16
|
+
let timeout;
|
|
17
|
+
let canceled = false;
|
|
18
|
+
const f = function (...args) {
|
|
19
|
+
if (canceled)
|
|
20
|
+
return;
|
|
21
|
+
clearTimeout(timeout);
|
|
22
|
+
timeout = setTimeout(() => {
|
|
23
|
+
func.call(this, ...args);
|
|
24
|
+
}, wait);
|
|
25
|
+
};
|
|
26
|
+
f.cancel = () => {
|
|
27
|
+
clearTimeout(timeout);
|
|
28
|
+
canceled = true;
|
|
29
|
+
};
|
|
30
|
+
return f;
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* 节流函数
|
|
34
|
+
* 节流就是节约流量,将连续触发的事件稀释成预设评率。 比如每间隔1秒执行一次函数,无论这期间触发多少次事件。
|
|
35
|
+
* 这有点像公交车,无论在站点等车的人多不多,公交车只会按时来一班,不会来一个人就来一辆公交车。
|
|
36
|
+
* @param {F} func
|
|
37
|
+
* @param {number} wait
|
|
38
|
+
* @param {boolean} immediate
|
|
39
|
+
* @returns {ThrottleFunc<F>}
|
|
40
|
+
*/
|
|
41
|
+
const throttle = (func, wait, immediate) => {
|
|
42
|
+
let timeout;
|
|
43
|
+
let canceled = false;
|
|
44
|
+
let lastCalledTime = 0;
|
|
45
|
+
const f = function (...args) {
|
|
46
|
+
if (canceled)
|
|
47
|
+
return;
|
|
48
|
+
const now = Date.now();
|
|
49
|
+
const call = () => {
|
|
50
|
+
lastCalledTime = now;
|
|
51
|
+
func.call(this, ...args);
|
|
52
|
+
};
|
|
53
|
+
// 第一次执行
|
|
54
|
+
if (lastCalledTime === 0) {
|
|
55
|
+
if (immediate) {
|
|
56
|
+
return call();
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
lastCalledTime = now;
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
const remain = lastCalledTime + wait - now;
|
|
64
|
+
if (remain > 0) {
|
|
65
|
+
clearTimeout(timeout);
|
|
66
|
+
timeout = setTimeout(() => call(), wait);
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
call();
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
f.cancel = () => {
|
|
73
|
+
clearTimeout(timeout);
|
|
74
|
+
canceled = true;
|
|
75
|
+
};
|
|
76
|
+
return f;
|
|
77
|
+
};
|
|
78
|
+
/**
|
|
79
|
+
* 单次函数
|
|
80
|
+
* @param {AnyFunc} func
|
|
81
|
+
* @returns {AnyFunc}
|
|
82
|
+
*/
|
|
83
|
+
const once = (func) => {
|
|
84
|
+
let called = false;
|
|
85
|
+
let result;
|
|
86
|
+
return function (...args) {
|
|
87
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
88
|
+
if (called)
|
|
89
|
+
return result;
|
|
90
|
+
called = true;
|
|
91
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
92
|
+
result = func.call(this, ...args);
|
|
93
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
94
|
+
return result;
|
|
95
|
+
};
|
|
96
|
+
};
|
|
97
|
+
/**
|
|
98
|
+
* 设置全局变量
|
|
99
|
+
* @param {string | number | symbol} key
|
|
100
|
+
* @param val
|
|
101
|
+
*/
|
|
102
|
+
function setGlobal(key, val) {
|
|
103
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
104
|
+
// @ts-ignore
|
|
105
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
106
|
+
if (typeof globalThis !== 'undefined')
|
|
107
|
+
globalThis[key] = val;
|
|
108
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
109
|
+
// @ts-ignore
|
|
110
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
111
|
+
else if (typeof window !== 'undefined')
|
|
112
|
+
window[key] = val;
|
|
113
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
114
|
+
// @ts-ignore
|
|
115
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
116
|
+
else if (typeof global !== 'undefined')
|
|
117
|
+
global[key] = val;
|
|
118
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
119
|
+
// @ts-ignore
|
|
120
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
121
|
+
else if (typeof self !== 'undefined')
|
|
122
|
+
self[key] = val;
|
|
123
|
+
else
|
|
124
|
+
throw new SyntaxError('当前环境下无法设置全局属性');
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* 设置全局变量
|
|
128
|
+
* @param {string | number | symbol} key
|
|
129
|
+
* @param val
|
|
130
|
+
*/
|
|
131
|
+
function getGlobal(key) {
|
|
132
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
133
|
+
// @ts-ignore
|
|
134
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
135
|
+
if (typeof globalThis !== 'undefined')
|
|
136
|
+
return globalThis[key];
|
|
137
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
138
|
+
// @ts-ignore
|
|
139
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
140
|
+
else if (typeof window !== 'undefined')
|
|
141
|
+
return window[key];
|
|
142
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
143
|
+
// @ts-ignore
|
|
144
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
145
|
+
else if (typeof global !== 'undefined')
|
|
146
|
+
return global[key];
|
|
147
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
148
|
+
// @ts-ignore
|
|
149
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
150
|
+
else if (typeof self !== 'undefined')
|
|
151
|
+
return self[key];
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
export { debounce, getGlobal, once, setGlobal, throttle };
|
package/lib/es/index.js
CHANGED
|
@@ -1,21 +1,25 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* sculp-js
|
|
2
|
+
* sculp-js v1.0.0
|
|
3
3
|
* (c) 2023-2023 chandq
|
|
4
4
|
* Released under the MIT License.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
export { arrayEach, arrayEachAsync, arrayInsertBefore, arrayLike, arrayRemove,
|
|
7
|
+
export { arrayEach, arrayEachAsync, arrayInsertBefore, arrayLike, arrayRemove, deepTraversal, getTreeIds } from './array.js';
|
|
8
8
|
export { copyText } from './clipboard.js';
|
|
9
9
|
export { cookieDel, cookieGet, cookieSet } from './cookie.js';
|
|
10
|
-
export { calculateDate, calculateDateTime, formatDate } from './date.js';
|
|
11
|
-
export { addClass, getStyle, hasClass, isDomReady, onDomReady, removeClass, setStyle, smoothScroll } from './dom.js';
|
|
10
|
+
export { calculateDate, calculateDateTime, dateParse, dateToEnd, dateToStart, formatDate, isValidDate } from './date.js';
|
|
11
|
+
export { addClass, getComputedCssVal, getStyle, hasClass, isDomReady, onDomReady, removeClass, setStyle, smoothScroll } from './dom.js';
|
|
12
12
|
export { downloadBlob, downloadData, downloadHref, downloadURL } from './download.js';
|
|
13
13
|
export { cloneDeep, isPlainObject, objectAssign, objectEach, objectEachAsync, objectFill, objectGet, objectHas, objectMap, objectAssign as objectMerge, objectOmit, objectPick } from './object.js';
|
|
14
14
|
export { pathJoin, pathNormalize } from './path.js';
|
|
15
15
|
export { qsParse, qsStringify } from './qs.js';
|
|
16
|
-
export { STRING_ARABIC_NUMERALS, STRING_LOWERCASE_ALPHA, STRING_UPPERCASE_ALPHA, stringAssign, stringCamelCase, stringEscapeHtml, stringFill, stringFormat, stringKebabCase } from './string.js';
|
|
17
|
-
export { isArray, isBigInt, isBoolean, isDate, isError, isFunction, isNaN, isNull, isNumber, isObject, isPrimitive, isRegExp, isString, isSymbol, isUndefined } from './type.js';
|
|
16
|
+
export { STRING_ARABIC_NUMERALS, STRING_LOWERCASE_ALPHA, STRING_UPPERCASE_ALPHA, getStrWidthPx, stringAssign, stringCamelCase, stringEscapeHtml, stringFill, stringFormat, stringKebabCase } from './string.js';
|
|
17
|
+
export { isArray, isBigInt, isBoolean, isDate, isError, isFunction, isNaN, isNull, isNumber, isObject, isPrimitive, isRegExp, isString, isSymbol, isUndefined, typeIs } from './type.js';
|
|
18
18
|
export { urlDelParams, urlParse, urlSetParams, urlStringify } from './url.js';
|
|
19
19
|
export { asyncMap, wait } from './async.js';
|
|
20
20
|
export { chooseLocalFile } from './file.js';
|
|
21
21
|
export { genCanvasWM } from './watermark.js';
|
|
22
|
+
export { debounce, getGlobal, once, setGlobal, throttle } from './func.js';
|
|
23
|
+
export { STRING_POOL, randomNumber, randomString, randomUuid } from './random.js';
|
|
24
|
+
export { HEX_POOL, formatNumber, numberAbbr, numberToHex } from './number.js';
|
|
25
|
+
export { UNIQUE_NUMBER_SAFE_LENGTH, uniqueNumber, uniqueString } from './unique.js';
|
package/lib/es/number.js
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* sculp-js v1.0.0
|
|
3
|
+
* (c) 2023-2023 chandq
|
|
4
|
+
* Released under the MIT License.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { getGlobal } from './func.js';
|
|
8
|
+
import { STRING_ARABIC_NUMERALS, STRING_UPPERCASE_ALPHA, STRING_LOWERCASE_ALPHA } from './string.js';
|
|
9
|
+
|
|
10
|
+
const HEX_POOL = `${STRING_ARABIC_NUMERALS}${STRING_UPPERCASE_ALPHA}${STRING_LOWERCASE_ALPHA}`;
|
|
11
|
+
const supportBigInt = typeof BigInt !== 'undefined';
|
|
12
|
+
const jsbi = () => getGlobal('JSBI');
|
|
13
|
+
const toBigInt = (n) => (supportBigInt ? BigInt(n) : jsbi().BigInt(n));
|
|
14
|
+
const divide = (x, y) => (supportBigInt ? x / y : jsbi().divide(x, y));
|
|
15
|
+
const remainder = (x, y) => (supportBigInt ? x % y : jsbi().remainder(x, y));
|
|
16
|
+
/**
|
|
17
|
+
* 将十进制转换成任意进制
|
|
18
|
+
* @param {number | string} decimal 十进制数值或字符串,可以是任意长度,会使用大数进行计算
|
|
19
|
+
* @param {string} [hexPool] 进制池,默认 62 进制
|
|
20
|
+
* @returns {string}
|
|
21
|
+
*/
|
|
22
|
+
function numberToHex(decimal, hexPool = HEX_POOL) {
|
|
23
|
+
if (hexPool.length < 2)
|
|
24
|
+
throw new Error('进制池长度不能少于 2');
|
|
25
|
+
if (!supportBigInt) {
|
|
26
|
+
throw new Error('需要安装 jsbi 模块并将 JSBI 设置为全局变量:\nimport JSBI from "jsbi"; window.JSBI = JSBI;');
|
|
27
|
+
}
|
|
28
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
29
|
+
let bigInt = toBigInt(decimal);
|
|
30
|
+
const ret = [];
|
|
31
|
+
const { length } = hexPool;
|
|
32
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
33
|
+
const bigLength = toBigInt(length);
|
|
34
|
+
const execute = () => {
|
|
35
|
+
const y = Number(remainder(bigInt, bigLength));
|
|
36
|
+
bigInt = divide(bigInt, bigLength);
|
|
37
|
+
ret.unshift(hexPool[y]);
|
|
38
|
+
if (bigInt > 0) {
|
|
39
|
+
execute();
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
execute();
|
|
43
|
+
return ret.join('');
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* 缩写
|
|
47
|
+
* @param {number | string} num
|
|
48
|
+
* @param {Array<string>} units
|
|
49
|
+
* @param {number} ratio
|
|
50
|
+
* @param {number} exponent
|
|
51
|
+
* @returns {string}
|
|
52
|
+
*/
|
|
53
|
+
const numberAbbr = (num, units, ratio = 1000, exponent) => {
|
|
54
|
+
const { length } = units;
|
|
55
|
+
if (length === 0)
|
|
56
|
+
throw new Error('至少需要一个单位');
|
|
57
|
+
let num2 = Number(num);
|
|
58
|
+
let times = 0;
|
|
59
|
+
while (num2 >= ratio && times < length - 1) {
|
|
60
|
+
num2 = num2 / ratio;
|
|
61
|
+
times++;
|
|
62
|
+
}
|
|
63
|
+
const value = num2.toFixed(exponent);
|
|
64
|
+
const unit = units[times];
|
|
65
|
+
return value.toString() + '' + unit;
|
|
66
|
+
};
|
|
67
|
+
/**
|
|
68
|
+
* 将数字格式化成千位分隔符显示的字符串
|
|
69
|
+
* @param {number} val 数字
|
|
70
|
+
* @param {'int' | 'float'} type 展示分段显示的类型 int:整型 | float:浮点型
|
|
71
|
+
* @returns {string}
|
|
72
|
+
*/
|
|
73
|
+
function formatNumber(val, type = 'int') {
|
|
74
|
+
return type === 'int' ? parseInt(String(val)).toLocaleString() : Number(val).toLocaleString('en-US');
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export { HEX_POOL, formatNumber, numberAbbr, numberToHex };
|
package/lib/es/object.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* sculp-js
|
|
2
|
+
* sculp-js v1.0.0
|
|
3
3
|
* (c) 2023-2023 chandq
|
|
4
4
|
* Released under the MIT License.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import
|
|
7
|
+
import { isObject, isUndefined, typeIs, isArray } from './type.js';
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* 判断对象是否为纯对象
|
|
@@ -27,20 +27,22 @@ const isPlainObject = (obj) => {
|
|
|
27
27
|
* @param {string} key
|
|
28
28
|
* @returns {boolean}
|
|
29
29
|
*/
|
|
30
|
-
|
|
30
|
+
function objectHas(obj, key) {
|
|
31
|
+
return Object.prototype.hasOwnProperty.call(obj, key);
|
|
32
|
+
}
|
|
31
33
|
/**
|
|
32
34
|
* 遍历对象,返回 false 中断遍历
|
|
33
35
|
* @param {O} obj
|
|
34
36
|
* @param {(val: O[keyof O], key: keyof O) => (boolean | void)} iterator
|
|
35
37
|
*/
|
|
36
|
-
|
|
38
|
+
function objectEach(obj, iterator) {
|
|
37
39
|
for (const key in obj) {
|
|
38
40
|
if (!objectHas(obj, key))
|
|
39
41
|
continue;
|
|
40
42
|
if (iterator(obj[key], key) === false)
|
|
41
43
|
break;
|
|
42
44
|
}
|
|
43
|
-
}
|
|
45
|
+
}
|
|
44
46
|
/**
|
|
45
47
|
* 异步遍历对象,返回 false 中断遍历
|
|
46
48
|
* @param {O} obj
|
|
@@ -146,7 +148,7 @@ const merge = (map, source, target) => {
|
|
|
146
148
|
* @param {ObjectAssignItem | undefined} targets
|
|
147
149
|
* @returns {R}
|
|
148
150
|
*/
|
|
149
|
-
|
|
151
|
+
function objectAssign(source, ...targets) {
|
|
150
152
|
const map = new Map();
|
|
151
153
|
for (let i = 0; i < targets.length; i++) {
|
|
152
154
|
const target = targets[i];
|
|
@@ -156,7 +158,7 @@ const objectAssign = (source, ...targets) => {
|
|
|
156
158
|
}
|
|
157
159
|
map.clear();
|
|
158
160
|
return source;
|
|
159
|
-
}
|
|
161
|
+
}
|
|
160
162
|
/**
|
|
161
163
|
* 对象填充
|
|
162
164
|
* @param {Partial<R>} source
|
|
@@ -164,7 +166,7 @@ const objectAssign = (source, ...targets) => {
|
|
|
164
166
|
* @param {(s: Partial<R>, t: Partial<R>, key: keyof R) => boolean} fillable
|
|
165
167
|
* @returns {R}
|
|
166
168
|
*/
|
|
167
|
-
|
|
169
|
+
function objectFill(source, target, fillable) {
|
|
168
170
|
const _fillable = fillable || ((source, target, key) => source[key] === undefined);
|
|
169
171
|
objectEach(target, (val, key) => {
|
|
170
172
|
if (_fillable(source, target, key)) {
|
|
@@ -172,7 +174,7 @@ const objectFill = (source, target, fillable) => {
|
|
|
172
174
|
}
|
|
173
175
|
});
|
|
174
176
|
return source;
|
|
175
|
-
}
|
|
177
|
+
}
|
|
176
178
|
function objectGet(obj, path, strict = false) {
|
|
177
179
|
path = path.replace(/\[(\w+)\]/g, '.$1');
|
|
178
180
|
path = path.replace(/^\./, '');
|
|
@@ -205,7 +207,7 @@ function objectGet(obj, path, strict = false) {
|
|
|
205
207
|
* 深拷贝堪称完全体 即:任何类型的数据都会被深拷贝
|
|
206
208
|
* @param {AnyObject | AnyArray} obj
|
|
207
209
|
* @param {WeakMap} map
|
|
208
|
-
* @
|
|
210
|
+
* @returns {AnyObject | AnyArray}
|
|
209
211
|
*/
|
|
210
212
|
function cloneDeep(obj, map = new WeakMap()) {
|
|
211
213
|
if (obj instanceof Date)
|
package/lib/es/path.js
CHANGED
package/lib/es/qs.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* sculp-js
|
|
2
|
+
* sculp-js v1.0.0
|
|
3
3
|
* (c) 2023-2023 chandq
|
|
4
4
|
* Released under the MIT License.
|
|
5
5
|
*/
|
|
@@ -12,7 +12,7 @@ import { isUndefined, isArray, isString, isNumber, isBoolean, isDate } from './t
|
|
|
12
12
|
* @param {string} queryString
|
|
13
13
|
* @returns {Params}
|
|
14
14
|
*/
|
|
15
|
-
|
|
15
|
+
function qsParse(queryString) {
|
|
16
16
|
const params = new URLSearchParams(queryString);
|
|
17
17
|
const result = {};
|
|
18
18
|
for (const [key, val] of params.entries()) {
|
|
@@ -26,7 +26,7 @@ const qsParse = (queryString) => {
|
|
|
26
26
|
result[key] = params.getAll(key);
|
|
27
27
|
}
|
|
28
28
|
return result;
|
|
29
|
-
}
|
|
29
|
+
}
|
|
30
30
|
const defaultReplacer = (val) => {
|
|
31
31
|
if (isString(val))
|
|
32
32
|
return val;
|
|
@@ -44,7 +44,7 @@ const defaultReplacer = (val) => {
|
|
|
44
44
|
* @param {Replacer} replacer
|
|
45
45
|
* @returns {string}
|
|
46
46
|
*/
|
|
47
|
-
|
|
47
|
+
function qsStringify(query, replacer = defaultReplacer) {
|
|
48
48
|
const params = new URLSearchParams();
|
|
49
49
|
objectEach(query, (val, key) => {
|
|
50
50
|
if (isArray(val)) {
|
|
@@ -63,6 +63,6 @@ const qsStringify = (query, replacer = defaultReplacer) => {
|
|
|
63
63
|
}
|
|
64
64
|
});
|
|
65
65
|
return params.toString();
|
|
66
|
-
}
|
|
66
|
+
}
|
|
67
67
|
|
|
68
68
|
export { qsParse, qsStringify };
|
package/lib/es/random.js
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* sculp-js v1.0.0
|
|
3
|
+
* (c) 2023-2023 chandq
|
|
4
|
+
* Released under the MIT License.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { STRING_ARABIC_NUMERALS, STRING_UPPERCASE_ALPHA, STRING_LOWERCASE_ALPHA } from './string.js';
|
|
8
|
+
import { isString, isNumber } from './type.js';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* 随机整数
|
|
12
|
+
* @param {number} min
|
|
13
|
+
* @param {number} max
|
|
14
|
+
* @returns {number}
|
|
15
|
+
*/
|
|
16
|
+
const randomNumber = (min, max) => Math.floor(Math.random() * (max - min + 1) + min);
|
|
17
|
+
const STRING_POOL = `${STRING_ARABIC_NUMERALS}${STRING_UPPERCASE_ALPHA}${STRING_LOWERCASE_ALPHA}`;
|
|
18
|
+
/**
|
|
19
|
+
* 随机字符串
|
|
20
|
+
* @param {number | string} length
|
|
21
|
+
* @param {string} pool
|
|
22
|
+
* @returns {string}
|
|
23
|
+
*/
|
|
24
|
+
const randomString = (length, pool) => {
|
|
25
|
+
let _length = 0;
|
|
26
|
+
let _pool = STRING_POOL;
|
|
27
|
+
if (isString(pool)) {
|
|
28
|
+
_length = length;
|
|
29
|
+
_pool = pool;
|
|
30
|
+
}
|
|
31
|
+
else if (isNumber(length)) {
|
|
32
|
+
_length = length;
|
|
33
|
+
}
|
|
34
|
+
else if (isString(length)) {
|
|
35
|
+
_pool = length;
|
|
36
|
+
}
|
|
37
|
+
let times = Math.max(_length, 1);
|
|
38
|
+
let result = '';
|
|
39
|
+
const min = 0;
|
|
40
|
+
const max = _pool.length - 1;
|
|
41
|
+
if (max < 2)
|
|
42
|
+
throw new Error('字符串池长度不能少于 2');
|
|
43
|
+
while (times--) {
|
|
44
|
+
const index = randomNumber(min, max);
|
|
45
|
+
result += _pool[index];
|
|
46
|
+
}
|
|
47
|
+
return result;
|
|
48
|
+
};
|
|
49
|
+
/**
|
|
50
|
+
* 优先浏览器原生能力获取 UUID v4
|
|
51
|
+
* @returns {string}
|
|
52
|
+
*/
|
|
53
|
+
function randomUuid() {
|
|
54
|
+
if (typeof URL === 'undefined' || !URL.createObjectURL || typeof Blob === 'undefined') {
|
|
55
|
+
const hex = '0123456789abcdef';
|
|
56
|
+
const model = 'xxxxxxxx-xxxx-4xxx-xxxx-xxxxxxxxxxxx';
|
|
57
|
+
let str = '';
|
|
58
|
+
for (let i = 0; i < model.length; i++) {
|
|
59
|
+
const rnd = randomNumber(0, 15);
|
|
60
|
+
str += model[i] == '-' || model[i] == '4' ? model[i] : hex[rnd];
|
|
61
|
+
}
|
|
62
|
+
return str;
|
|
63
|
+
}
|
|
64
|
+
return /[^/]+$/.exec(URL.createObjectURL(new Blob()).slice())[0];
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export { STRING_POOL, randomNumber, randomString, randomUuid };
|
package/lib/es/string.js
CHANGED
|
@@ -1,33 +1,35 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* sculp-js
|
|
2
|
+
* sculp-js v1.0.0
|
|
3
3
|
* (c) 2023-2023 chandq
|
|
4
4
|
* Released under the MIT License.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
+
import { isString } from './type.js';
|
|
8
|
+
|
|
7
9
|
/**
|
|
8
10
|
* 将字符串转换为驼峰格式
|
|
9
11
|
* @param {string} string
|
|
10
12
|
* @param {boolean} [bigger] 是否大写第一个字母
|
|
11
13
|
* @returns {string}
|
|
12
14
|
*/
|
|
13
|
-
|
|
15
|
+
function stringCamelCase(string, bigger) {
|
|
14
16
|
let string2 = string;
|
|
15
17
|
if (bigger) {
|
|
16
18
|
string2 = string.replace(/^./, origin => origin.toUpperCase());
|
|
17
19
|
}
|
|
18
20
|
const HUMP_RE = /[\s_-](.)/g;
|
|
19
21
|
return string2.replace(HUMP_RE, (orign, char) => char.toUpperCase());
|
|
20
|
-
}
|
|
22
|
+
}
|
|
21
23
|
/**
|
|
22
24
|
* 将字符串转换为连字格式
|
|
23
25
|
* @param {string} string
|
|
24
26
|
* @param {string} [separator] 分隔符,默认是"-"(短横线)
|
|
25
27
|
* @returns {string}
|
|
26
28
|
*/
|
|
27
|
-
|
|
29
|
+
function stringKebabCase(string, separator = '-') {
|
|
28
30
|
const string2 = string.replace(/^./, origin => origin.toLowerCase());
|
|
29
31
|
return string2.replace(/[A-Z]/g, origin => `${separator}${origin.toLowerCase()}`);
|
|
30
|
-
}
|
|
32
|
+
}
|
|
31
33
|
const STRING_ARABIC_NUMERALS = '0123456789';
|
|
32
34
|
const STRING_LOWERCASE_ALPHA = 'abcdefghijklmnopqrstuvwxyz';
|
|
33
35
|
const STRING_UPPERCASE_ALPHA = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
|
@@ -43,7 +45,7 @@ const placeholderRE = /%[%sdo]/g;
|
|
|
43
45
|
* @param args
|
|
44
46
|
* @returns {string}
|
|
45
47
|
*/
|
|
46
|
-
|
|
48
|
+
function stringFormat(string, ...args) {
|
|
47
49
|
let index = 0;
|
|
48
50
|
const result = string.replace(placeholderRE, (origin) => {
|
|
49
51
|
const arg = args[index++];
|
|
@@ -61,7 +63,7 @@ const stringFormat = (string, ...args) => {
|
|
|
61
63
|
}
|
|
62
64
|
});
|
|
63
65
|
return [result, ...args.splice(index).map(String)].join(' ');
|
|
64
|
-
}
|
|
66
|
+
}
|
|
65
67
|
const ev = (expression, data) => {
|
|
66
68
|
try {
|
|
67
69
|
// eslint-disable-next-line @typescript-eslint/no-implied-eval,@typescript-eslint/no-unsafe-return
|
|
@@ -120,5 +122,35 @@ const stringEscapeHtml = (html) => {
|
|
|
120
122
|
* @returns {string}
|
|
121
123
|
*/
|
|
122
124
|
const stringFill = (length, value = ' ') => new Array(length).fill(value).join('');
|
|
125
|
+
/**
|
|
126
|
+
* 字符串的像素宽度
|
|
127
|
+
* @param {string} str 目标字符串
|
|
128
|
+
* @param {number} fontSize 字符串字体大小
|
|
129
|
+
* @param {boolean} isRemoveDom 计算后是否移除中间dom元素
|
|
130
|
+
* @returns {*}
|
|
131
|
+
*/
|
|
132
|
+
function getStrWidthPx(str, fontSize = 14, isRemoveDom = false) {
|
|
133
|
+
let strWidth = 0;
|
|
134
|
+
console.assert(isString(str), `${str} 不是有效的字符串`);
|
|
135
|
+
if (isString(str) && str.length > 0) {
|
|
136
|
+
let getEle = document.querySelector('#getStrWidth1494304949567');
|
|
137
|
+
if (!getEle) {
|
|
138
|
+
const _ele = document.createElement('span');
|
|
139
|
+
_ele.id = 'getStrWidth1494304949567';
|
|
140
|
+
_ele.style.fontSize = fontSize + 'px';
|
|
141
|
+
_ele.style.whiteSpace = 'nowrap';
|
|
142
|
+
_ele.style.visibility = 'hidden';
|
|
143
|
+
_ele.textContent = str;
|
|
144
|
+
document.body.appendChild(_ele);
|
|
145
|
+
getEle = _ele;
|
|
146
|
+
}
|
|
147
|
+
getEle.textContent = str;
|
|
148
|
+
strWidth = getEle.offsetWidth;
|
|
149
|
+
if (isRemoveDom) {
|
|
150
|
+
document.body.appendChild(getEle);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
return strWidth;
|
|
154
|
+
}
|
|
123
155
|
|
|
124
|
-
export { STRING_ARABIC_NUMERALS, STRING_LOWERCASE_ALPHA, STRING_UPPERCASE_ALPHA, stringAssign, stringCamelCase, stringEscapeHtml, stringFill, stringFormat, stringKebabCase };
|
|
156
|
+
export { STRING_ARABIC_NUMERALS, STRING_LOWERCASE_ALPHA, STRING_UPPERCASE_ALPHA, getStrWidthPx, stringAssign, stringCamelCase, stringEscapeHtml, stringFill, stringFormat, stringKebabCase };
|