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.
Files changed (47) hide show
  1. package/LICENSE.md +1 -1
  2. package/README.md +22 -1
  3. package/lib/cjs/array.js +32 -55
  4. package/lib/cjs/async.js +3 -3
  5. package/lib/cjs/clipboard.js +3 -3
  6. package/lib/cjs/cookie.js +5 -5
  7. package/lib/cjs/date.js +142 -24
  8. package/lib/cjs/dom.js +24 -10
  9. package/lib/cjs/download.js +9 -9
  10. package/lib/cjs/easing.js +1 -1
  11. package/lib/cjs/file.js +5 -4
  12. package/lib/cjs/func.js +160 -0
  13. package/lib/cjs/index.js +28 -2
  14. package/lib/cjs/number.js +82 -0
  15. package/lib/cjs/object.js +13 -11
  16. package/lib/cjs/path.js +1 -1
  17. package/lib/cjs/qs.js +5 -5
  18. package/lib/cjs/random.js +72 -0
  19. package/lib/cjs/string.js +40 -7
  20. package/lib/cjs/type.js +12 -2
  21. package/lib/cjs/unique.js +83 -0
  22. package/lib/cjs/url.js +1 -1
  23. package/lib/cjs/watermark.js +8 -9
  24. package/lib/es/array.js +33 -55
  25. package/lib/es/async.js +3 -3
  26. package/lib/es/clipboard.js +3 -3
  27. package/lib/es/cookie.js +5 -5
  28. package/lib/es/date.js +139 -25
  29. package/lib/es/dom.js +24 -11
  30. package/lib/es/download.js +9 -9
  31. package/lib/es/easing.js +1 -1
  32. package/lib/es/file.js +5 -4
  33. package/lib/es/func.js +154 -0
  34. package/lib/es/index.js +10 -6
  35. package/lib/es/number.js +77 -0
  36. package/lib/es/object.js +12 -10
  37. package/lib/es/path.js +1 -1
  38. package/lib/es/qs.js +5 -5
  39. package/lib/es/random.js +67 -0
  40. package/lib/es/string.js +40 -8
  41. package/lib/es/type.js +12 -3
  42. package/lib/es/unique.js +79 -0
  43. package/lib/es/url.js +1 -1
  44. package/lib/es/watermark.js +8 -9
  45. package/lib/index.d.ts +254 -80
  46. package/lib/umd/index.js +637 -132
  47. package/package.json +36 -12
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * sculp-js v0.0.1
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
- const downloadURL = (url, params) => {
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
- const downloadHref = (href, filename) => {
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
- const downloadBlob = (blob, filename) => {
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
- const downloadData = (data, fileType, filename, headers) => {
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
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * sculp-js v0.0.1
2
+ * sculp-js v1.0.0
3
3
  * (c) 2023-2023 chandq
4
4
  * Released under the MIT License.
5
5
  */
package/lib/es/file.js CHANGED
@@ -1,15 +1,16 @@
1
1
  /*!
2
- * sculp-js v0.0.1
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 {function} changeCb 选择文件回调
10
- * @return {*}
9
+ * @param {string} accept 上传的文件类型,用于过滤
10
+ * @param {Function} changeCb 选择文件回调
11
+ * @returns {HTMLInputElement}
11
12
  */
12
- function chooseLocalFile({ accept }, changeCb) {
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 v0.0.1
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, asyncForEach, deepTraversal, getTreeIds } from './array.js';
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';
@@ -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 v0.0.1
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 typeIs, { isObject, isUndefined, isArray } from './type.js';
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
- const objectHas = (obj, key) => Object.prototype.hasOwnProperty.call(obj, key);
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
- const objectEach = (obj, iterator) => {
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
- const objectAssign = (source, ...targets) => {
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
- const objectFill = (source, target, fillable) => {
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
- * @return {AnyObject | AnyArray}
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
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * sculp-js v0.0.1
2
+ * sculp-js v1.0.0
3
3
  * (c) 2023-2023 chandq
4
4
  * Released under the MIT License.
5
5
  */
package/lib/es/qs.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * sculp-js v0.0.1
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
- const qsParse = (queryString) => {
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
- const qsStringify = (query, replacer = defaultReplacer) => {
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 };
@@ -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 v0.0.1
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
- const stringCamelCase = (string, bigger) => {
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
- const stringKebabCase = (string, separator = '-') => {
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
- const stringFormat = (string, ...args) => {
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 };