sculp-js 1.5.1 → 1.7.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 (61) hide show
  1. package/README.md +10 -1
  2. package/lib/cjs/array.js +2 -21
  3. package/lib/cjs/async.js +2 -2
  4. package/lib/cjs/base64.js +62 -0
  5. package/lib/cjs/clipboard.js +2 -2
  6. package/lib/cjs/cookie.js +2 -2
  7. package/lib/cjs/date.js +2 -3
  8. package/lib/cjs/dom.js +2 -2
  9. package/lib/cjs/download.js +2 -2
  10. package/lib/cjs/easing.js +2 -2
  11. package/lib/cjs/file.js +2 -2
  12. package/lib/cjs/func.js +3 -3
  13. package/lib/cjs/index.js +37 -4
  14. package/lib/cjs/math.js +88 -0
  15. package/lib/cjs/number.js +2 -2
  16. package/lib/cjs/object.js +10 -20
  17. package/lib/cjs/path.js +2 -2
  18. package/lib/cjs/qs.js +2 -2
  19. package/lib/cjs/random.js +2 -2
  20. package/lib/cjs/string.js +3 -3
  21. package/lib/cjs/tooltip.js +2 -2
  22. package/lib/cjs/tree.js +4 -4
  23. package/lib/cjs/type.js +69 -3
  24. package/lib/cjs/unique.js +2 -2
  25. package/lib/cjs/url.js +2 -2
  26. package/lib/cjs/validator.js +147 -0
  27. package/lib/cjs/variable.js +118 -0
  28. package/lib/cjs/watermark.js +2 -2
  29. package/lib/cjs/we-decode.js +4 -4
  30. package/lib/es/array.js +3 -21
  31. package/lib/es/async.js +2 -2
  32. package/lib/es/base64.js +59 -0
  33. package/lib/es/clipboard.js +2 -2
  34. package/lib/es/cookie.js +2 -2
  35. package/lib/es/date.js +2 -3
  36. package/lib/es/dom.js +2 -2
  37. package/lib/es/download.js +2 -2
  38. package/lib/es/easing.js +2 -2
  39. package/lib/es/file.js +2 -2
  40. package/lib/es/func.js +3 -3
  41. package/lib/es/index.js +9 -5
  42. package/lib/es/math.js +82 -0
  43. package/lib/es/number.js +2 -2
  44. package/lib/es/object.js +9 -18
  45. package/lib/es/path.js +2 -2
  46. package/lib/es/qs.js +2 -2
  47. package/lib/es/random.js +2 -2
  48. package/lib/es/string.js +3 -3
  49. package/lib/es/tooltip.js +2 -2
  50. package/lib/es/tree.js +4 -4
  51. package/lib/es/type.js +67 -4
  52. package/lib/es/unique.js +2 -2
  53. package/lib/es/url.js +2 -2
  54. package/lib/es/validator.js +130 -0
  55. package/lib/es/variable.js +112 -0
  56. package/lib/es/watermark.js +2 -2
  57. package/lib/es/we-decode.js +4 -4
  58. package/lib/index.d.ts +236 -21
  59. package/lib/tsdoc-metadata.json +11 -0
  60. package/lib/umd/index.js +571 -155
  61. package/package.json +2 -2
package/lib/es/math.js ADDED
@@ -0,0 +1,82 @@
1
+ /*!
2
+ * sculp-js v1.7.0
3
+ * (c) 2023-present chandq
4
+ * Released under the MIT License.
5
+ */
6
+
7
+ /**
8
+ * 数值安全乘法
9
+ * @param arg1 数值1
10
+ * @param arg2 数值2
11
+ */
12
+ const multiply = (arg1, arg2) => {
13
+ let m = 0;
14
+ const s1 = arg1.toString();
15
+ const s2 = arg2.toString();
16
+ if (s1.split('.')[1] !== undefined)
17
+ m += s1.split('.')[1].length;
18
+ if (s2.split('.')[1] !== undefined)
19
+ m += s2.split('.')[1].length;
20
+ return (Number(s1.replace('.', '')) * Number(s2.replace('.', ''))) / Math.pow(10, m);
21
+ };
22
+ /**
23
+ * 数值安全加法
24
+ * @param arg1 数值1
25
+ * @param arg2 数值2
26
+ */
27
+ const add = (arg1, arg2) => {
28
+ let r1 = 0;
29
+ let r2 = 0;
30
+ let m = 0;
31
+ try {
32
+ r1 = arg1.toString().split('.')[1].length;
33
+ }
34
+ catch (e) {
35
+ r1 = 0;
36
+ }
37
+ try {
38
+ r2 = arg2.toString().split('.')[1].length;
39
+ }
40
+ catch (e) {
41
+ r2 = 0;
42
+ }
43
+ m = 10 ** Math.max(r1, r2);
44
+ return (multiply(arg1, m) + multiply(arg2, m)) / m;
45
+ };
46
+ /**
47
+ * 数值安全减法
48
+ * @param arg1 数值1
49
+ * @param arg2 数值2
50
+ */
51
+ const subtract = (arg1, arg2) => add(arg1, -arg2);
52
+ /**
53
+ * 数值安全除法
54
+ * @param arg1 数值1
55
+ * @param arg2 数值2
56
+ */
57
+ const divide = (arg1, arg2) => {
58
+ let t1 = 0;
59
+ let t2 = 0;
60
+ let r1 = 0;
61
+ let r2 = 0;
62
+ if (arg1.toString().split('.')[1] !== undefined)
63
+ t1 = arg1.toString().split('.')[1].length;
64
+ if (arg2.toString().split('.')[1] !== undefined)
65
+ t2 = arg2.toString().split('.')[1].length;
66
+ r1 = Number(arg1.toString().replace('.', ''));
67
+ r2 = Number(arg2.toString().replace('.', ''));
68
+ return (r1 / r2) * Math.pow(10, t2 - t1);
69
+ };
70
+ /**
71
+ * Correct the given number to specifying significant digits.
72
+ *
73
+ * @param num The input number
74
+ * @param precision An integer specifying the number of significant digits
75
+ *
76
+ * @example strip(0.09999999999999998) === 0.1 // true
77
+ */
78
+ function strip(num, precision = 15) {
79
+ return +parseFloat(Number(num).toPrecision(precision));
80
+ }
81
+
82
+ export { add, divide, multiply, strip, subtract };
package/lib/es/number.js CHANGED
@@ -1,6 +1,6 @@
1
1
  /*!
2
- * sculp-js v1.5.0
3
- * (c) 2023-2024 chandq
2
+ * sculp-js v1.7.0
3
+ * (c) 2023-present chandq
4
4
  * Released under the MIT License.
5
5
  */
6
6
 
package/lib/es/object.js CHANGED
@@ -1,10 +1,10 @@
1
1
  /*!
2
- * sculp-js v1.5.0
3
- * (c) 2023-2024 chandq
2
+ * sculp-js v1.7.0
3
+ * (c) 2023-present chandq
4
4
  * Released under the MIT License.
5
5
  */
6
6
 
7
- import { isObject, isUndefined, typeIs, isArray } from './type.js';
7
+ import { isObject, objectHas, isNumber, isUndefined, typeIs, isArray } from './type.js';
8
8
 
9
9
  /**
10
10
  * 判断对象是否为纯对象
@@ -21,15 +21,6 @@ const isPlainObject = (obj) => {
21
21
  // 是否对象直接实例
22
22
  return proto === Object.prototype;
23
23
  };
24
- /**
25
- * 判断对象内是否有该静态属性
26
- * @param {object} obj
27
- * @param {string} key
28
- * @returns {boolean}
29
- */
30
- function objectHas(obj, key) {
31
- return Object.prototype.hasOwnProperty.call(obj, key);
32
- }
33
24
  /**
34
25
  * 遍历对象,返回 false 中断遍历
35
26
  * @param {O} obj
@@ -183,23 +174,23 @@ function objectGet(obj, path, strict = false) {
183
174
  let i = 0;
184
175
  for (let len = keyArr.length; i < len - 1; ++i) {
185
176
  const key = keyArr[i];
186
- if (key in tempObj) {
187
- // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access,@typescript-eslint/no-unsafe-assignment
177
+ if (isNumber(Number(key)) && Array.isArray(tempObj)) {
178
+ tempObj = tempObj[key];
179
+ }
180
+ else if (isObject(tempObj) && objectHas(tempObj, key)) {
188
181
  tempObj = tempObj[key];
189
182
  }
190
183
  else {
191
184
  tempObj = undefined;
192
185
  if (strict) {
193
- throw new Error('[berry/js-utils/object] objectGet path 路径不正确');
186
+ throw new Error('[Object] objectGet path 路径不正确');
194
187
  }
195
188
  break;
196
189
  }
197
190
  }
198
191
  return {
199
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
200
192
  p: tempObj,
201
193
  k: tempObj ? keyArr[i] : undefined,
202
- // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access,@typescript-eslint/no-unsafe-assignment
203
194
  v: tempObj ? tempObj[keyArr[i]] : undefined
204
195
  };
205
196
  }
@@ -227,4 +218,4 @@ function cloneDeep(obj, map = new WeakMap()) {
227
218
  return cloneObj;
228
219
  }
229
220
 
230
- export { cloneDeep, isPlainObject, objectAssign, objectEach, objectEachAsync, objectFill, objectGet, objectHas, objectMap, objectAssign as objectMerge, objectOmit, objectPick };
221
+ export { cloneDeep, isPlainObject, objectAssign, objectEach, objectEachAsync, objectFill, objectGet, objectMap, objectAssign as objectMerge, objectOmit, objectPick };
package/lib/es/path.js CHANGED
@@ -1,6 +1,6 @@
1
1
  /*!
2
- * sculp-js v1.5.0
3
- * (c) 2023-2024 chandq
2
+ * sculp-js v1.7.0
3
+ * (c) 2023-present chandq
4
4
  * Released under the MIT License.
5
5
  */
6
6
 
package/lib/es/qs.js CHANGED
@@ -1,6 +1,6 @@
1
1
  /*!
2
- * sculp-js v1.5.0
3
- * (c) 2023-2024 chandq
2
+ * sculp-js v1.7.0
3
+ * (c) 2023-present chandq
4
4
  * Released under the MIT License.
5
5
  */
6
6
 
package/lib/es/random.js CHANGED
@@ -1,6 +1,6 @@
1
1
  /*!
2
- * sculp-js v1.5.0
3
- * (c) 2023-2024 chandq
2
+ * sculp-js v1.7.0
3
+ * (c) 2023-present chandq
4
4
  * Released under the MIT License.
5
5
  */
6
6
 
package/lib/es/string.js CHANGED
@@ -1,6 +1,6 @@
1
1
  /*!
2
- * sculp-js v1.5.0
3
- * (c) 2023-2024 chandq
2
+ * sculp-js v1.7.0
3
+ * (c) 2023-present chandq
4
4
  * Released under the MIT License.
5
5
  */
6
6
 
@@ -123,7 +123,7 @@ const stringFill = (length, value = ' ') => new Array(length).fill(value).join('
123
123
  /**
124
124
  * 解析URL查询参数
125
125
  * @param {string} searchStr
126
- * @return {Record<string, string | string[]>}
126
+ * @returns {Record<string, string | string[]>}
127
127
  */
128
128
  function parseQueryParams(searchStr = location.search) {
129
129
  const queryObj = {};
package/lib/es/tooltip.js CHANGED
@@ -1,6 +1,6 @@
1
1
  /*!
2
- * sculp-js v1.5.0
3
- * (c) 2023-2024 chandq
2
+ * sculp-js v1.7.0
3
+ * (c) 2023-present chandq
4
4
  * Released under the MIT License.
5
5
  */
6
6
 
package/lib/es/tree.js CHANGED
@@ -1,6 +1,6 @@
1
1
  /*!
2
- * sculp-js v1.5.0
3
- * (c) 2023-2024 chandq
2
+ * sculp-js v1.7.0
3
+ * (c) 2023-present chandq
4
4
  * Released under the MIT License.
5
5
  */
6
6
 
@@ -278,7 +278,7 @@ function formatTree(list, options = defaultFieldOptions) {
278
278
  * 树形结构转扁平化
279
279
  * @param {any} treeList
280
280
  * @param {IFieldOptions} options
281
- * @return {*}
281
+ * @returns {*}
282
282
  */
283
283
  function flatTree(treeList, options = defaultFieldOptions) {
284
284
  const { childField, keyField, pidField } = options;
@@ -304,7 +304,7 @@ function flatTree(treeList, options = defaultFieldOptions) {
304
304
  * @param {any[]} nodes
305
305
  * @param {string} query
306
306
  * @param {ISearchTreeOpts} options
307
- * @return {any[]}
307
+ * @returns {any[]}
308
308
  */
309
309
  function fuzzySearchTree(nodes, query, options = defaultSearchTreeOptions) {
310
310
  const result = [];
package/lib/es/type.js CHANGED
@@ -1,9 +1,34 @@
1
1
  /*!
2
- * sculp-js v1.5.0
3
- * (c) 2023-2024 chandq
2
+ * sculp-js v1.7.0
3
+ * (c) 2023-present chandq
4
4
  * Released under the MIT License.
5
5
  */
6
6
 
7
+ // 常用类型定义
8
+ /**
9
+ * 判断对象内是否有该静态属性
10
+ * @param {object} obj
11
+ * @param {string} key
12
+ * @returns {boolean}
13
+ */
14
+ function objectHas(obj, key) {
15
+ return Object.prototype.hasOwnProperty.call(obj, key);
16
+ }
17
+ /**
18
+ * 判断一个对象是否为类数组
19
+ *
20
+ * @param any
21
+ * @returns {boolean}
22
+ */
23
+ function arrayLike(any) {
24
+ if (isArray(any))
25
+ return true;
26
+ if (isString(any))
27
+ return true;
28
+ if (!isObject(any))
29
+ return false;
30
+ return objectHas(any, 'length');
31
+ }
7
32
  /**
8
33
  * 判断任意值的数据类型
9
34
  * @param {unknown} any
@@ -39,7 +64,7 @@ const isRegExp = (any) => typeIs(any) === 'RegExp';
39
64
  /**
40
65
  * 判断一个字符串是否为有效的 JSON, 若有效则返回有效的JSON对象,否则false
41
66
  * @param {string} str
42
- * @return {Object | boolean}
67
+ * @returns {Object | boolean}
43
68
  */
44
69
  function isJsonString(str) {
45
70
  try {
@@ -50,5 +75,43 @@ function isJsonString(str) {
50
75
  return false;
51
76
  }
52
77
  }
78
+ /**
79
+ * Checks if `value` is an empty object, collection, map, or set.
80
+ *
81
+ * Objects are considered empty if they have no own enumerable string keyed
82
+ * properties.
83
+ *
84
+ * Array-like values such as `arguments` objects, arrays, buffers, strings, or
85
+ * jQuery-like collections are considered empty if they have a `length` of `0`.
86
+ * Similarly, maps and sets are considered empty if they have a `size` of `0`.
87
+ *
88
+ * @param {*} value The value to check.
89
+ * @returns {boolean} Returns `true` if `value` is empty, else `false`.
90
+ * @example
91
+ *
92
+ * isEmpty(null);
93
+ * // => true
94
+ *
95
+ * isEmpty(true);
96
+ * // => true
97
+ *
98
+ * isEmpty(1);
99
+ * // => true
100
+ *
101
+ * isEmpty([1, 2, 3]);
102
+ * // => false
103
+ *
104
+ * isEmpty({ 'a': 1 });
105
+ * // => false
106
+ */
107
+ function isEmpty(value) {
108
+ if (isNullOrUnDef(value) || Number.isNaN(value)) {
109
+ return true;
110
+ }
111
+ if (arrayLike(value) && (isArray(value) || isString(value) || isFunction(value.splice))) {
112
+ return !value.length;
113
+ }
114
+ return !Object.keys(value).length;
115
+ }
53
116
 
54
- export { typeIs as default, isArray, isBigInt, isBoolean, isDate, isError, isFunction, isJsonString, isNaN, isNull, isNullOrUnDef, isNumber, isObject, isPrimitive, isRegExp, isString, isSymbol, isUndefined, typeIs };
117
+ export { arrayLike, typeIs as default, isArray, isBigInt, isBoolean, isDate, isEmpty, isError, isFunction, isJsonString, isNaN, isNull, isNullOrUnDef, isNumber, isObject, isPrimitive, isRegExp, isString, isSymbol, isUndefined, objectHas, typeIs };
package/lib/es/unique.js CHANGED
@@ -1,6 +1,6 @@
1
1
  /*!
2
- * sculp-js v1.5.0
3
- * (c) 2023-2024 chandq
2
+ * sculp-js v1.7.0
3
+ * (c) 2023-present chandq
4
4
  * Released under the MIT License.
5
5
  */
6
6
 
package/lib/es/url.js CHANGED
@@ -1,6 +1,6 @@
1
1
  /*!
2
- * sculp-js v1.5.0
3
- * (c) 2023-2024 chandq
2
+ * sculp-js v1.7.0
3
+ * (c) 2023-present chandq
4
4
  * Released under the MIT License.
5
5
  */
6
6
 
@@ -0,0 +1,130 @@
1
+ /*!
2
+ * sculp-js v1.7.0
3
+ * (c) 2023-present chandq
4
+ * Released under the MIT License.
5
+ */
6
+
7
+ // 邮箱
8
+ const EMAIL_REGEX = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
9
+ /**
10
+ * 判断字符串是否为邮箱格式,不对邮箱真实性做验证,如域名是否正确等
11
+ * @param {string} value
12
+ * @returns {boolean}
13
+ */
14
+ const isEmail = (value) => EMAIL_REGEX.test(value);
15
+ // 手机号码 (中国大陆)
16
+ // reference: https://www.runoob.com/regexp/regexp-syntax.html (?: 是非捕获元之一)
17
+ const PHONE_REGEX = /^(?:(?:\+|00)86)?1\d{10}$/;
18
+ /**
19
+ * 判断字符串是否为宽松手机格式,即首位为 1 的 11 位数字都属于手机号
20
+ * @param {string} value
21
+ * @returns {boolean}
22
+ */
23
+ const isPhone = (value) => PHONE_REGEX.test(value);
24
+ // 身份证号码
25
+ // http://www.stats.gov.cn/tjsj/tjbz/xzqhdm/
26
+ // ["北京市", "天津市", "河北省", "山西省", "内蒙古自治区",
27
+ // "辽宁省", "吉林省", "黑龙江省",
28
+ // "上海市", "江苏省", "浙江省", "安徽省", "福建省", "江西省", "山东省",
29
+ // "河南省", "湖北省", "湖南省", "广东省", "广西壮族自治区", "海南省",
30
+ // "重庆市", "四川省", "贵州省", "云南省", "西藏自治区",
31
+ // "陕西省", "甘肃省", "青海省","宁夏回族自治区", "新疆维吾尔自治区",
32
+ // "台湾省",
33
+ // "香港特别行政区", "澳门特别行政区"]
34
+ // ["11", "12", "13", "14", "15",
35
+ // "21", "22", "23",
36
+ // "31", "32", "33", "34", "35", "36", "37",
37
+ // "41", "42", "43", "44", "45", "46",
38
+ // "50", "51", "52", "53", "54",
39
+ // "61", "62", "63", "64", "65",
40
+ // "71",
41
+ // "81", "82"]
42
+ // 91 国外
43
+ const IDNO_RE = /^(1[1-5]|2[1-3]|3[1-7]|4[1-6]|5[0-4]|6[1-5]|7[1]|8[1-2]|9[1])\d{4}(18|19|20)\d{2}[01]\d[0123]\d{4}[\dxX]$/;
44
+ /**
45
+ * 判断字符串是否为身份证号码格式
46
+ * @param {string} value
47
+ * @returns {boolean}
48
+ */
49
+ const isIdNo = (value) => {
50
+ const isSameFormat = IDNO_RE.test(value);
51
+ if (!isSameFormat)
52
+ return false;
53
+ const year = Number(value.slice(6, 10));
54
+ const month = Number(value.slice(10, 12));
55
+ const date = Number(value.slice(12, 14));
56
+ const d = new Date(year, month - 1, date);
57
+ const isSameDate = d.getFullYear() === year && d.getMonth() + 1 === month && d.getDate() === date;
58
+ if (!isSameDate)
59
+ return false;
60
+ // 将身份证号码前面的17位数分别乘以不同的系数;
61
+ // 从第一位到第十七位的系数分别为:7-9-10-5-8-4-2-1-6-3-7-9-10-5-8-4-2
62
+ // 将这17位数字和系数相乘的结果相加;
63
+ // 用加出来和除以11,看余数是多少;
64
+ // 余数只可能有0-1-2-3-4-5-6-7-8-9-10这11个数字;
65
+ // 其分别对应的最后一位身份证的号码为1-0-X-9-8-7-6-5-4-3-2
66
+ // 通过上面得知如果余数是2,就会在身份证的第18位数字上出现罗马数字的Ⅹ。如果余数是10,身份证的最后一位号码就是2。
67
+ const coefficientList = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
68
+ const residueList = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'];
69
+ let sum = 0;
70
+ for (let start = 0; start < 17; start++) {
71
+ sum += Number(value.slice(start, start + 1)) * coefficientList[start];
72
+ }
73
+ return residueList[sum % 11] === value.slice(-1);
74
+ };
75
+ const URL_REGEX = /^(https?|ftp):\/\/([^\s/$.?#].[^\s]*)$/i;
76
+ const HTTP_URL_REGEX = /^https?:\/\/([^\s/$.?#].[^\s]*)$/i;
77
+ /**
78
+ * 判断字符串是否为 url 格式,支持 http、https、ftp 协议,支持域名或者 ipV4
79
+ * @param {string} value
80
+ * @returns {boolean}
81
+ */
82
+ const isUrl = (url, includeFtp = false) => {
83
+ const regex = includeFtp ? URL_REGEX : HTTP_URL_REGEX;
84
+ return regex.test(url);
85
+ };
86
+ // ipv4
87
+ const IPV4_REGEX = /^(?:(?:\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.){3}(?:\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])$/;
88
+ // ipv6
89
+ const IPV6_REGEX = /^(([\da-fA-F]{1,4}:){7}[\da-fA-F]{1,4}|([\da-fA-F]{1,4}:){1,7}:|([\da-fA-F]{1,4}:){1,6}:[\da-fA-F]{1,4}|([\da-fA-F]{1,4}:){1,5}(:[\da-fA-F]{1,4}){1,2}|([\da-fA-F]{1,4}:){1,4}(:[\da-fA-F]{1,4}){1,3}|([\da-fA-F]{1,4}:){1,3}(:[\da-fA-F]{1,4}){1,4}|([\da-fA-F]{1,4}:){1,2}(:[\da-fA-F]{1,4}){1,5}|[\da-fA-F]{1,4}:((:[\da-fA-F]{1,4}){1,6})|:((:[\da-fA-F]{1,4}){1,7}|:)|fe80:(:[\da-fA-F]{0,4}){0,4}%[\da-zA-Z]+|::(ffff(:0{1,4})?:)?((25[0-5]|(2[0-4]|1?\d)?\d)\.){3}(25[0-5]|(2[0-4]|1?\d)?\d)|([\da-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1?\d)?\d)\.){3}(25[0-5]|(2[0-4]|1?\d)?\d))$/i;
90
+ /**
91
+ * 判断字符串是否为 IPV4 格式,不对 ip 真实性做验证
92
+ * @param {string} value
93
+ * @returns {boolean}
94
+ */
95
+ const isIpV4 = (value) => IPV4_REGEX.test(value);
96
+ /**
97
+ * 判断字符串是否为 IPV6 格式,不对 ip 真实性做验证
98
+ * @param {string} value
99
+ * @returns {boolean}
100
+ */
101
+ const isIpV6 = (value) => IPV6_REGEX.test(value);
102
+ const INTEGER_RE = /^(-?[1-9]\d*|0)$/;
103
+ /**
104
+ * 判断字符串是否为整数(自然数),即 ...,-3,-2,-1,0,1,2,3,...
105
+ * @param {string} value
106
+ * @returns {boolean}
107
+ */
108
+ const isInteger = (value) => INTEGER_RE.test(value);
109
+ const FLOAT_RE = /^-?([1-9]\d*|0)\.\d*[1-9]$/;
110
+ /**
111
+ * 判断字符串是否为浮点数,即必须有小数点的有理数
112
+ * @param {string} value
113
+ * @returns {boolean}
114
+ */
115
+ const isFloat = (value) => FLOAT_RE.test(value);
116
+ /**
117
+ * 判断字符串是否为正确数值,包括整数和浮点数
118
+ * @param {string} value
119
+ * @returns {boolean}
120
+ */
121
+ const isNumerical = (value) => isInteger(value) || isFloat(value);
122
+ const DIGIT_RE = /^\d+$/;
123
+ /**
124
+ * 判断字符串是否为数字,例如六位数字短信验证码(093031)
125
+ * @param {string} value
126
+ * @returns {boolean}
127
+ */
128
+ const isDigit = (value) => DIGIT_RE.test(value);
129
+
130
+ export { EMAIL_REGEX, HTTP_URL_REGEX, IPV4_REGEX, IPV6_REGEX, PHONE_REGEX, URL_REGEX, isDigit, isEmail, isFloat, isIdNo, isInteger, isIpV4, isIpV6, isNumerical, isPhone, isUrl };
@@ -0,0 +1,112 @@
1
+ /*!
2
+ * sculp-js v1.7.0
3
+ * (c) 2023-present chandq
4
+ * Released under the MIT License.
5
+ */
6
+
7
+ import { objectHas } from './type.js';
8
+
9
+ /**
10
+ * 去除字符串中重复字符
11
+ * @param {string} str
12
+ * @returns string
13
+ * @example
14
+ *
15
+ * uniqueSymbol('1a1bac');
16
+ * // => '1abc'
17
+ */
18
+ function uniqueSymbol(str) {
19
+ return [...new Set(str.trim().split(''))].join('');
20
+ }
21
+ /**
22
+ * 转义所有特殊字符
23
+ * @param {string} str 原字符串
24
+ * reference: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Regular_expressions
25
+ * @returns string
26
+ */
27
+ function escapeRegExp(str) {
28
+ return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); //$&表示整个被匹配的字符串
29
+ }
30
+ /**
31
+ * 根据左右匹配符号生产解析变量(自动删除变量内的空白)
32
+ * @param {string} leftMatchSymbol
33
+ * @param {string} rightMatchSymbol
34
+ * @returns RegExp
35
+ */
36
+ function parseVariableRegExp(leftMatchSymbol, rightMatchSymbol) {
37
+ return new RegExp(`${escapeRegExp(leftMatchSymbol.trim())}\\s*([^${escapeRegExp(uniqueSymbol(leftMatchSymbol))}${escapeRegExp(uniqueSymbol(rightMatchSymbol))}\\s]*)\\s*${rightMatchSymbol.trim()}`, 'g');
38
+ }
39
+ /**
40
+ * 解析字符串的插值变量
41
+ * @param {string} str 字符串
42
+ * @param {string} leftMatchSymbol 变量左侧匹配符号,默认:{
43
+ * @param {string} rightMatchSymbol 变量右侧匹配符号,默认:}
44
+ * @returns string[]
45
+ * @example
46
+ *
47
+ * default match symbol {} same as /{\s*([^{}\s]*)\s*}/g
48
+ */
49
+ function parseVarFromString(str, leftMatchSymbol = '{', rightMatchSymbol = '}') {
50
+ return Array.from(str.matchAll(parseVariableRegExp(leftMatchSymbol, rightMatchSymbol))).map(el => el?.[1]);
51
+ }
52
+ /**
53
+ * 替换字符串中的插值变量
54
+ * @param {string} sourceStr
55
+ * @param {Record<string, any>} targetObj
56
+ * @param {string} leftMatchSymbol 变量左侧匹配符号,默认:{
57
+ * @param {string} rightMatchSymbol 变量右侧匹配符号,默认:}
58
+ * @returns string
59
+ */
60
+ function replaceVarFromString(sourceStr, targetObj, leftMatchSymbol = '{', rightMatchSymbol = '}') {
61
+ return sourceStr.replace(new RegExp(parseVariableRegExp(leftMatchSymbol, rightMatchSymbol)), function (m, p1) {
62
+ return objectHas(targetObj, p1) ? targetObj[p1] : m;
63
+ });
64
+ }
65
+ /**
66
+ * 在指定作用域中执行代码
67
+ * @param {string} code 要执行的代码(需包含 return 语句或表达式)
68
+ * @param {Object} scope 作用域对象(键值对形式的变量环境)
69
+ * @returns 代码执行结果
70
+ *
71
+ * @example
72
+ * // 测试用例 1: 基本变量访问
73
+ * executeInScope("return a + b;", { a: 1, b: 2 });
74
+ * // 3
75
+ *
76
+ * // 测试用例 2: 支持复杂表达式和运算
77
+ * executeInScope(
78
+ * "return Array.from({ length: 3 }, (_, i) => base + i);",
79
+ * { base: 100 }
80
+ * );
81
+ * // [100, 101, 102]
82
+ *
83
+ * // 支持外传函数作用域执行
84
+ * const scope = {
85
+ * $: {
86
+ * fun: {
87
+ * time: {
88
+ * now: function () {
89
+ * return new Date();
90
+ * },
91
+ * },
92
+ * },
93
+ * },
94
+ * };
95
+ * executeInScope("return $.fun.time.now()", scope)
96
+ */
97
+ function executeInScope(code, scope = {}) {
98
+ // 提取作用域对象的键和值
99
+ const keys = Object.keys(scope);
100
+ const values = keys.map(key => scope[key]);
101
+ try {
102
+ // 动态创建函数,将作用域的键作为参数,代码作为函数体
103
+ const func = new Function(...keys, `return (() => { ${code} })()`);
104
+ // 调用函数并传入作用域的值
105
+ return func(...values);
106
+ }
107
+ catch (error) {
108
+ throw new Error(`代码执行失败: ${error.message}`);
109
+ }
110
+ }
111
+
112
+ export { escapeRegExp, executeInScope, parseVarFromString, replaceVarFromString, uniqueSymbol };
@@ -1,6 +1,6 @@
1
1
  /*!
2
- * sculp-js v1.5.0
3
- * (c) 2023-2024 chandq
2
+ * sculp-js v1.7.0
3
+ * (c) 2023-present chandq
4
4
  * Released under the MIT License.
5
5
  */
6
6
 
@@ -1,6 +1,6 @@
1
1
  /*!
2
- * sculp-js v1.5.0
3
- * (c) 2023-2024 chandq
2
+ * sculp-js v1.7.0
3
+ * (c) 2023-present chandq
4
4
  * Released under the MIT License.
5
5
  */
6
6
 
@@ -10,7 +10,7 @@ const b64re = /^(?:[A-Za-z\d+\/]{4})*?(?:[A-Za-z\d+\/]{2}(?:==)?|[A-Za-z\d+\/]{3
10
10
  /**
11
11
  * 字符串编码成Base64 (适用于任何环境,包括小程序)
12
12
  * @param {string} string
13
- * @return {string}
13
+ * @returns {string}
14
14
  */
15
15
  function weBtoa(string) {
16
16
  // 同window.btoa: 字符串编码成Base64
@@ -32,7 +32,7 @@ function weBtoa(string) {
32
32
  /**
33
33
  * Base64解码为原始字符串(适用于任何环境,包括小程序)
34
34
  * @param {string} string
35
- * @return {string}
35
+ * @returns {string}
36
36
  */
37
37
  function weAtob(string) {
38
38
  // 同window.atob: Base64解码为原始字符串