sculp-js 1.6.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 -2
  3. package/lib/cjs/async.js +2 -2
  4. package/lib/cjs/base64.js +2 -2
  5. package/lib/cjs/clipboard.js +2 -2
  6. package/lib/cjs/cookie.js +2 -2
  7. package/lib/cjs/date.js +2 -2
  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 +2 -2
  13. package/lib/cjs/index.js +25 -2
  14. package/lib/cjs/math.js +2 -2
  15. package/lib/cjs/number.js +2 -2
  16. package/lib/cjs/object.js +2 -2
  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 +8 -8
  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 +2 -2
  31. package/lib/es/async.js +2 -2
  32. package/lib/es/base64.js +2 -2
  33. package/lib/es/clipboard.js +2 -2
  34. package/lib/es/cookie.js +2 -2
  35. package/lib/es/date.js +2 -2
  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 +2 -2
  41. package/lib/es/index.js +4 -2
  42. package/lib/es/math.js +2 -2
  43. package/lib/es/number.js +2 -2
  44. package/lib/es/object.js +2 -2
  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 +8 -8
  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 +150 -12
  59. package/lib/tsdoc-metadata.json +11 -0
  60. package/lib/umd/index.js +260 -13
  61. package/package.json +1 -1
package/lib/index.d.ts CHANGED
@@ -53,7 +53,7 @@ declare const isRegExp: (any: unknown) => any is RegExp;
53
53
  /**
54
54
  * 判断一个字符串是否为有效的 JSON, 若有效则返回有效的JSON对象,否则false
55
55
  * @param {string} str
56
- * @return {Object | boolean}
56
+ * @returns {Object | boolean}
57
57
  */
58
58
  declare function isJsonString(str: string): Object | boolean;
59
59
  /**
@@ -70,19 +70,19 @@ declare function isJsonString(str: string): Object | boolean;
70
70
  * @returns {boolean} Returns `true` if `value` is empty, else `false`.
71
71
  * @example
72
72
  *
73
- * _.isEmpty(null);
73
+ * isEmpty(null);
74
74
  * // => true
75
75
  *
76
- * _.isEmpty(true);
76
+ * isEmpty(true);
77
77
  * // => true
78
78
  *
79
- * _.isEmpty(1);
79
+ * isEmpty(1);
80
80
  * // => true
81
81
  *
82
- * _.isEmpty([1, 2, 3]);
82
+ * isEmpty([1, 2, 3]);
83
83
  * // => false
84
84
  *
85
- * _.isEmpty({ 'a': 1 });
85
+ * isEmpty({ 'a': 1 });
86
86
  * // => false
87
87
  */
88
88
  declare function isEmpty(value: any): boolean;
@@ -492,7 +492,7 @@ declare const stringFill: (length: number, value?: string) => string;
492
492
  /**
493
493
  * 解析URL查询参数
494
494
  * @param {string} searchStr
495
- * @return {Record<string, string | string[]>}
495
+ * @returns {Record<string, string | string[]>}
496
496
  */
497
497
  declare function parseQueryParams(searchStr?: string): Record<string, string | string[]>;
498
498
 
@@ -846,7 +846,7 @@ declare function formatTree(list: any[], options?: IFieldOptions): any[];
846
846
  * 树形结构转扁平化
847
847
  * @param {any} treeList
848
848
  * @param {IFieldOptions} options
849
- * @return {*}
849
+ * @returns {*}
850
850
  */
851
851
  declare function flatTree(treeList: any[], options?: IFieldOptions): any[];
852
852
  /**
@@ -854,7 +854,7 @@ declare function flatTree(treeList: any[], options?: IFieldOptions): any[];
854
854
  * @param {any[]} nodes
855
855
  * @param {string} query
856
856
  * @param {ISearchTreeOpts} options
857
- * @return {any[]}
857
+ * @returns {any[]}
858
858
  */
859
859
  declare function fuzzySearchTree(nodes: any[], query: string, options?: ISearchTreeOpts): any[];
860
860
 
@@ -896,13 +896,13 @@ declare function strip(num: NumberType, precision?: number): number;
896
896
  /**
897
897
  * 字符串编码成Base64 (适用于任何环境,包括小程序)
898
898
  * @param {string} string
899
- * @return {string}
899
+ * @returns {string}
900
900
  */
901
901
  declare function weBtoa(string: string): string;
902
902
  /**
903
903
  * Base64解码为原始字符串(适用于任何环境,包括小程序)
904
904
  * @param {string} string
905
- * @return {string}
905
+ * @returns {string}
906
906
  */
907
907
  declare function weAtob(string: string): string;
908
908
 
@@ -919,4 +919,142 @@ declare function decodeFromBase64(base64: string): string;
919
919
  */
920
920
  declare function encodeToBase64(rawStr: string): string;
921
921
 
922
- export { type AnyArray, type AnyFunc, type AnyObject, type ArrayElements, type DateObj, type DateValue, type DebounceFunc, type FileType, HEX_POOL, type ICanvasWM, type ICompressOptions, type IFieldOptions, type ISearchTreeOpts, type ITreeConf, type IdLike, type LooseParamValue, type LooseParams, type ObjectAssignItem, type OnceFunc, type Params, type PartialDeep, type RandomString, type ReadyCallback, type Replacer, STRING_ARABIC_NUMERALS, STRING_LOWERCASE_ALPHA, STRING_POOL, STRING_UPPERCASE_ALPHA, type SetStyle, type SmoothScrollOptions, type Style, type ThrottleFunc, UNIQUE_NUMBER_SAFE_LENGTH, type UniqueString, type Url, type WithChildren, add, addClass, arrayEach, arrayEachAsync, arrayInsertBefore, arrayLike, arrayRemove, asyncMap, buildTree, calculateDate, calculateDateTime, chooseLocalFile, cloneDeep, compressImg, cookieDel, cookieGet, cookieSet, copyText, crossOriginDownload, dateParse, dateToEnd, dateToStart, debounce, decodeFromBase64, divide, downloadBlob, downloadData, downloadHref, downloadURL, encodeToBase64, flatTree, forEachDeep, forEachMap, formatDate, formatNumber, formatTree, fuzzySearchTree, genCanvasWM, getComputedCssVal, getGlobal, getStrWidthPx, getStyle, hasClass, isArray, isBigInt, isBoolean, isDate, isDomReady, isEmpty, isError, isFunction, isJsonString, isNaN, isNull, isNullOrUnDef, isNumber, isObject, isPlainObject, isPrimitive, isRegExp, isString, isSymbol, isUndefined, isValidDate, multiply, numberAbbr, numberToHex, objectAssign, objectEach, objectEachAsync, objectFill, objectGet, objectHas, objectMap, objectAssign as objectMerge, objectOmit, objectPick, onDomReady, once, parseQueryParams, pathJoin, pathNormalize, qsParse, qsStringify, randomNumber, randomString, randomUuid, removeClass, searchTreeById, setGlobal, setStyle, smoothScroll, stringAssign, stringCamelCase, stringEscapeHtml, stringFill, stringFormat, stringKebabCase, strip, subtract, supportCanvas, throttle, tooltipEvent, typeIs, uniqueNumber, uniqueString, urlDelParams, urlParse, urlSetParams, urlStringify, wait, weAtob, weBtoa };
922
+ declare const EMAIL_REGEX: RegExp;
923
+ /**
924
+ * 判断字符串是否为邮箱格式,不对邮箱真实性做验证,如域名是否正确等
925
+ * @param {string} value
926
+ * @returns {boolean}
927
+ */
928
+ declare const isEmail: (value: string) => boolean;
929
+ declare const PHONE_REGEX: RegExp;
930
+ /**
931
+ * 判断字符串是否为宽松手机格式,即首位为 1 的 11 位数字都属于手机号
932
+ * @param {string} value
933
+ * @returns {boolean}
934
+ */
935
+ declare const isPhone: (value: string) => boolean;
936
+ /**
937
+ * 判断字符串是否为身份证号码格式
938
+ * @param {string} value
939
+ * @returns {boolean}
940
+ */
941
+ declare const isIdNo: (value: string) => boolean;
942
+ declare const URL_REGEX: RegExp;
943
+ declare const HTTP_URL_REGEX: RegExp;
944
+ /**
945
+ * 判断字符串是否为 url 格式,支持 http、https、ftp 协议,支持域名或者 ipV4
946
+ * @param {string} value
947
+ * @returns {boolean}
948
+ */
949
+ declare const isUrl: (url: string, includeFtp?: boolean) => boolean;
950
+ declare const IPV4_REGEX: RegExp;
951
+ declare const IPV6_REGEX: RegExp;
952
+ /**
953
+ * 判断字符串是否为 IPV4 格式,不对 ip 真实性做验证
954
+ * @param {string} value
955
+ * @returns {boolean}
956
+ */
957
+ declare const isIpV4: (value: string) => boolean;
958
+ /**
959
+ * 判断字符串是否为 IPV6 格式,不对 ip 真实性做验证
960
+ * @param {string} value
961
+ * @returns {boolean}
962
+ */
963
+ declare const isIpV6: (value: string) => boolean;
964
+ /**
965
+ * 判断字符串是否为整数(自然数),即 ...,-3,-2,-1,0,1,2,3,...
966
+ * @param {string} value
967
+ * @returns {boolean}
968
+ */
969
+ declare const isInteger: (value: string) => boolean;
970
+ /**
971
+ * 判断字符串是否为浮点数,即必须有小数点的有理数
972
+ * @param {string} value
973
+ * @returns {boolean}
974
+ */
975
+ declare const isFloat: (value: string) => boolean;
976
+ /**
977
+ * 判断字符串是否为正确数值,包括整数和浮点数
978
+ * @param {string} value
979
+ * @returns {boolean}
980
+ */
981
+ declare const isNumerical: (value: string) => boolean;
982
+ /**
983
+ * 判断字符串是否为数字,例如六位数字短信验证码(093031)
984
+ * @param {string} value
985
+ * @returns {boolean}
986
+ */
987
+ declare const isDigit: (value: string) => boolean;
988
+
989
+ /**
990
+ * 去除字符串中重复字符
991
+ * @param {string} str
992
+ * @returns string
993
+ * @example
994
+ *
995
+ * uniqueSymbol('1a1bac');
996
+ * // => '1abc'
997
+ */
998
+ declare function uniqueSymbol(str: string): string;
999
+ /**
1000
+ * 转义所有特殊字符
1001
+ * @param {string} str 原字符串
1002
+ * reference: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Regular_expressions
1003
+ * @returns string
1004
+ */
1005
+ declare function escapeRegExp(str: string): string;
1006
+ /**
1007
+ * 解析字符串的插值变量
1008
+ * @param {string} str 字符串
1009
+ * @param {string} leftMatchSymbol 变量左侧匹配符号,默认:{
1010
+ * @param {string} rightMatchSymbol 变量右侧匹配符号,默认:}
1011
+ * @returns string[]
1012
+ * @example
1013
+ *
1014
+ * default match symbol {} same as /{\s*([^{}\s]*)\s*}/g
1015
+ */
1016
+ declare function parseVarFromString(str: string, leftMatchSymbol?: string, rightMatchSymbol?: string): string[];
1017
+ /**
1018
+ * 替换字符串中的插值变量
1019
+ * @param {string} sourceStr
1020
+ * @param {Record<string, any>} targetObj
1021
+ * @param {string} leftMatchSymbol 变量左侧匹配符号,默认:{
1022
+ * @param {string} rightMatchSymbol 变量右侧匹配符号,默认:}
1023
+ * @returns string
1024
+ */
1025
+ declare function replaceVarFromString(sourceStr: string, targetObj: Record<string, any>, leftMatchSymbol?: string, rightMatchSymbol?: string): string;
1026
+ /**
1027
+ * 在指定作用域中执行代码
1028
+ * @param {string} code 要执行的代码(需包含 return 语句或表达式)
1029
+ * @param {Object} scope 作用域对象(键值对形式的变量环境)
1030
+ * @returns 代码执行结果
1031
+ *
1032
+ * @example
1033
+ * // 测试用例 1: 基本变量访问
1034
+ * executeInScope("return a + b;", { a: 1, b: 2 });
1035
+ * // 3
1036
+ *
1037
+ * // 测试用例 2: 支持复杂表达式和运算
1038
+ * executeInScope(
1039
+ * "return Array.from({ length: 3 }, (_, i) => base + i);",
1040
+ * { base: 100 }
1041
+ * );
1042
+ * // [100, 101, 102]
1043
+ *
1044
+ * // 支持外传函数作用域执行
1045
+ * const scope = {
1046
+ * $: {
1047
+ * fun: {
1048
+ * time: {
1049
+ * now: function () {
1050
+ * return new Date();
1051
+ * },
1052
+ * },
1053
+ * },
1054
+ * },
1055
+ * };
1056
+ * executeInScope("return $.fun.time.now()", scope)
1057
+ */
1058
+ declare function executeInScope(code: string, scope?: Record<string, any>): any;
1059
+
1060
+ export { type AnyArray, type AnyFunc, type AnyObject, type ArrayElements, type DateObj, type DateValue, type DebounceFunc, EMAIL_REGEX, type FileType, HEX_POOL, HTTP_URL_REGEX, type ICanvasWM, type ICompressOptions, type IFieldOptions, IPV4_REGEX, IPV6_REGEX, type ISearchTreeOpts, type ITreeConf, type IdLike, type LooseParamValue, type LooseParams, type ObjectAssignItem, type OnceFunc, PHONE_REGEX, type Params, type PartialDeep, type RandomString, type ReadyCallback, type Replacer, STRING_ARABIC_NUMERALS, STRING_LOWERCASE_ALPHA, STRING_POOL, STRING_UPPERCASE_ALPHA, type SetStyle, type SmoothScrollOptions, type Style, type ThrottleFunc, UNIQUE_NUMBER_SAFE_LENGTH, URL_REGEX, type UniqueString, type Url, type WithChildren, add, addClass, arrayEach, arrayEachAsync, arrayInsertBefore, arrayLike, arrayRemove, asyncMap, buildTree, calculateDate, calculateDateTime, chooseLocalFile, cloneDeep, compressImg, cookieDel, cookieGet, cookieSet, copyText, crossOriginDownload, dateParse, dateToEnd, dateToStart, debounce, decodeFromBase64, divide, downloadBlob, downloadData, downloadHref, downloadURL, encodeToBase64, escapeRegExp, executeInScope, flatTree, forEachDeep, forEachMap, formatDate, formatNumber, formatTree, fuzzySearchTree, genCanvasWM, getComputedCssVal, getGlobal, getStrWidthPx, getStyle, hasClass, isArray, isBigInt, isBoolean, isDate, isDigit, isDomReady, isEmail, isEmpty, isError, isFloat, isFunction, isIdNo, isInteger, isIpV4, isIpV6, isJsonString, isNaN, isNull, isNullOrUnDef, isNumber, isNumerical, isObject, isPhone, isPlainObject, isPrimitive, isRegExp, isString, isSymbol, isUndefined, isUrl, isValidDate, multiply, numberAbbr, numberToHex, objectAssign, objectEach, objectEachAsync, objectFill, objectGet, objectHas, objectMap, objectAssign as objectMerge, objectOmit, objectPick, onDomReady, once, parseQueryParams, parseVarFromString, pathJoin, pathNormalize, qsParse, qsStringify, randomNumber, randomString, randomUuid, removeClass, replaceVarFromString, searchTreeById, setGlobal, setStyle, smoothScroll, stringAssign, stringCamelCase, stringEscapeHtml, stringFill, stringFormat, stringKebabCase, strip, subtract, supportCanvas, throttle, tooltipEvent, typeIs, uniqueNumber, uniqueString, uniqueSymbol, urlDelParams, urlParse, urlSetParams, urlStringify, wait, weAtob, weBtoa };
@@ -0,0 +1,11 @@
1
+ // This file is read by tools that parse documentation comments conforming to the TSDoc standard.
2
+ // It should be published with your NPM package. It should not be tracked by Git.
3
+ {
4
+ "tsdocVersion": "0.12",
5
+ "toolPackages": [
6
+ {
7
+ "packageName": "@microsoft/api-extractor",
8
+ "packageVersion": "7.38.3"
9
+ }
10
+ ]
11
+ }
package/lib/umd/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  /*!
2
- * sculp-js v1.6.1
3
- * (c) 2023-2025 chandq
2
+ * sculp-js v1.7.0
3
+ * (c) 2023-present chandq
4
4
  * Released under the MIT License.
5
5
  */
6
6
 
@@ -156,7 +156,7 @@
156
156
  /**
157
157
  * 判断一个字符串是否为有效的 JSON, 若有效则返回有效的JSON对象,否则false
158
158
  * @param {string} str
159
- * @return {Object | boolean}
159
+ * @returns {Object | boolean}
160
160
  */
161
161
  function isJsonString(str) {
162
162
  try {
@@ -181,19 +181,19 @@
181
181
  * @returns {boolean} Returns `true` if `value` is empty, else `false`.
182
182
  * @example
183
183
  *
184
- * _.isEmpty(null);
184
+ * isEmpty(null);
185
185
  * // => true
186
186
  *
187
- * _.isEmpty(true);
187
+ * isEmpty(true);
188
188
  * // => true
189
189
  *
190
- * _.isEmpty(1);
190
+ * isEmpty(1);
191
191
  * // => true
192
192
  *
193
- * _.isEmpty([1, 2, 3]);
193
+ * isEmpty([1, 2, 3]);
194
194
  * // => false
195
195
  *
196
- * _.isEmpty({ 'a': 1 });
196
+ * isEmpty({ 'a': 1 });
197
197
  * // => false
198
198
  */
199
199
  function isEmpty(value) {
@@ -565,7 +565,7 @@
565
565
  /**
566
566
  * 解析URL查询参数
567
567
  * @param {string} searchStr
568
- * @return {Record<string, string | string[]>}
568
+ * @returns {Record<string, string | string[]>}
569
569
  */
570
570
  function parseQueryParams(searchStr = location.search) {
571
571
  const queryObj = {};
@@ -1369,7 +1369,7 @@
1369
1369
  /**
1370
1370
  * 字符串编码成Base64 (适用于任何环境,包括小程序)
1371
1371
  * @param {string} string
1372
- * @return {string}
1372
+ * @returns {string}
1373
1373
  */
1374
1374
  function weBtoa(string) {
1375
1375
  // 同window.btoa: 字符串编码成Base64
@@ -1391,7 +1391,7 @@
1391
1391
  /**
1392
1392
  * Base64解码为原始字符串(适用于任何环境,包括小程序)
1393
1393
  * @param {string} string
1394
- * @return {string}
1394
+ * @returns {string}
1395
1395
  */
1396
1396
  function weAtob(string) {
1397
1397
  // 同window.atob: Base64解码为原始字符串
@@ -2402,7 +2402,7 @@
2402
2402
  * 树形结构转扁平化
2403
2403
  * @param {any} treeList
2404
2404
  * @param {IFieldOptions} options
2405
- * @return {*}
2405
+ * @returns {*}
2406
2406
  */
2407
2407
  function flatTree(treeList, options = defaultFieldOptions) {
2408
2408
  const { childField, keyField, pidField } = options;
@@ -2428,7 +2428,7 @@
2428
2428
  * @param {any[]} nodes
2429
2429
  * @param {string} query
2430
2430
  * @param {ISearchTreeOpts} options
2431
- * @return {any[]}
2431
+ * @returns {any[]}
2432
2432
  */
2433
2433
  function fuzzySearchTree(nodes, query, options = defaultSearchTreeOptions) {
2434
2434
  const result = [];
@@ -2594,12 +2594,244 @@
2594
2594
  return !isNullOrUnDef(getGlobal('btoa')) ? getGlobal('btoa')(binaryString) : weBtoa(binaryString);
2595
2595
  }
2596
2596
 
2597
+ // 邮箱
2598
+ const EMAIL_REGEX = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
2599
+ /**
2600
+ * 判断字符串是否为邮箱格式,不对邮箱真实性做验证,如域名是否正确等
2601
+ * @param {string} value
2602
+ * @returns {boolean}
2603
+ */
2604
+ const isEmail = (value) => EMAIL_REGEX.test(value);
2605
+ // 手机号码 (中国大陆)
2606
+ // reference: https://www.runoob.com/regexp/regexp-syntax.html (?: 是非捕获元之一)
2607
+ const PHONE_REGEX = /^(?:(?:\+|00)86)?1\d{10}$/;
2608
+ /**
2609
+ * 判断字符串是否为宽松手机格式,即首位为 1 的 11 位数字都属于手机号
2610
+ * @param {string} value
2611
+ * @returns {boolean}
2612
+ */
2613
+ const isPhone = (value) => PHONE_REGEX.test(value);
2614
+ // 身份证号码
2615
+ // http://www.stats.gov.cn/tjsj/tjbz/xzqhdm/
2616
+ // ["北京市", "天津市", "河北省", "山西省", "内蒙古自治区",
2617
+ // "辽宁省", "吉林省", "黑龙江省",
2618
+ // "上海市", "江苏省", "浙江省", "安徽省", "福建省", "江西省", "山东省",
2619
+ // "河南省", "湖北省", "湖南省", "广东省", "广西壮族自治区", "海南省",
2620
+ // "重庆市", "四川省", "贵州省", "云南省", "西藏自治区",
2621
+ // "陕西省", "甘肃省", "青海省","宁夏回族自治区", "新疆维吾尔自治区",
2622
+ // "台湾省",
2623
+ // "香港特别行政区", "澳门特别行政区"]
2624
+ // ["11", "12", "13", "14", "15",
2625
+ // "21", "22", "23",
2626
+ // "31", "32", "33", "34", "35", "36", "37",
2627
+ // "41", "42", "43", "44", "45", "46",
2628
+ // "50", "51", "52", "53", "54",
2629
+ // "61", "62", "63", "64", "65",
2630
+ // "71",
2631
+ // "81", "82"]
2632
+ // 91 国外
2633
+ 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]$/;
2634
+ /**
2635
+ * 判断字符串是否为身份证号码格式
2636
+ * @param {string} value
2637
+ * @returns {boolean}
2638
+ */
2639
+ const isIdNo = (value) => {
2640
+ const isSameFormat = IDNO_RE.test(value);
2641
+ if (!isSameFormat)
2642
+ return false;
2643
+ const year = Number(value.slice(6, 10));
2644
+ const month = Number(value.slice(10, 12));
2645
+ const date = Number(value.slice(12, 14));
2646
+ const d = new Date(year, month - 1, date);
2647
+ const isSameDate = d.getFullYear() === year && d.getMonth() + 1 === month && d.getDate() === date;
2648
+ if (!isSameDate)
2649
+ return false;
2650
+ // 将身份证号码前面的17位数分别乘以不同的系数;
2651
+ // 从第一位到第十七位的系数分别为:7-9-10-5-8-4-2-1-6-3-7-9-10-5-8-4-2
2652
+ // 将这17位数字和系数相乘的结果相加;
2653
+ // 用加出来和除以11,看余数是多少;
2654
+ // 余数只可能有0-1-2-3-4-5-6-7-8-9-10这11个数字;
2655
+ // 其分别对应的最后一位身份证的号码为1-0-X-9-8-7-6-5-4-3-2
2656
+ // 通过上面得知如果余数是2,就会在身份证的第18位数字上出现罗马数字的Ⅹ。如果余数是10,身份证的最后一位号码就是2。
2657
+ const coefficientList = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
2658
+ const residueList = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'];
2659
+ let sum = 0;
2660
+ for (let start = 0; start < 17; start++) {
2661
+ sum += Number(value.slice(start, start + 1)) * coefficientList[start];
2662
+ }
2663
+ return residueList[sum % 11] === value.slice(-1);
2664
+ };
2665
+ const URL_REGEX = /^(https?|ftp):\/\/([^\s/$.?#].[^\s]*)$/i;
2666
+ const HTTP_URL_REGEX = /^https?:\/\/([^\s/$.?#].[^\s]*)$/i;
2667
+ /**
2668
+ * 判断字符串是否为 url 格式,支持 http、https、ftp 协议,支持域名或者 ipV4
2669
+ * @param {string} value
2670
+ * @returns {boolean}
2671
+ */
2672
+ const isUrl = (url, includeFtp = false) => {
2673
+ const regex = includeFtp ? URL_REGEX : HTTP_URL_REGEX;
2674
+ return regex.test(url);
2675
+ };
2676
+ // ipv4
2677
+ 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])$/;
2678
+ // ipv6
2679
+ 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;
2680
+ /**
2681
+ * 判断字符串是否为 IPV4 格式,不对 ip 真实性做验证
2682
+ * @param {string} value
2683
+ * @returns {boolean}
2684
+ */
2685
+ const isIpV4 = (value) => IPV4_REGEX.test(value);
2686
+ /**
2687
+ * 判断字符串是否为 IPV6 格式,不对 ip 真实性做验证
2688
+ * @param {string} value
2689
+ * @returns {boolean}
2690
+ */
2691
+ const isIpV6 = (value) => IPV6_REGEX.test(value);
2692
+ const INTEGER_RE = /^(-?[1-9]\d*|0)$/;
2693
+ /**
2694
+ * 判断字符串是否为整数(自然数),即 ...,-3,-2,-1,0,1,2,3,...
2695
+ * @param {string} value
2696
+ * @returns {boolean}
2697
+ */
2698
+ const isInteger = (value) => INTEGER_RE.test(value);
2699
+ const FLOAT_RE = /^-?([1-9]\d*|0)\.\d*[1-9]$/;
2700
+ /**
2701
+ * 判断字符串是否为浮点数,即必须有小数点的有理数
2702
+ * @param {string} value
2703
+ * @returns {boolean}
2704
+ */
2705
+ const isFloat = (value) => FLOAT_RE.test(value);
2706
+ /**
2707
+ * 判断字符串是否为正确数值,包括整数和浮点数
2708
+ * @param {string} value
2709
+ * @returns {boolean}
2710
+ */
2711
+ const isNumerical = (value) => isInteger(value) || isFloat(value);
2712
+ const DIGIT_RE = /^\d+$/;
2713
+ /**
2714
+ * 判断字符串是否为数字,例如六位数字短信验证码(093031)
2715
+ * @param {string} value
2716
+ * @returns {boolean}
2717
+ */
2718
+ const isDigit = (value) => DIGIT_RE.test(value);
2719
+
2720
+ /**
2721
+ * 去除字符串中重复字符
2722
+ * @param {string} str
2723
+ * @returns string
2724
+ * @example
2725
+ *
2726
+ * uniqueSymbol('1a1bac');
2727
+ * // => '1abc'
2728
+ */
2729
+ function uniqueSymbol(str) {
2730
+ return [...new Set(str.trim().split(''))].join('');
2731
+ }
2732
+ /**
2733
+ * 转义所有特殊字符
2734
+ * @param {string} str 原字符串
2735
+ * reference: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Regular_expressions
2736
+ * @returns string
2737
+ */
2738
+ function escapeRegExp(str) {
2739
+ return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); //$&表示整个被匹配的字符串
2740
+ }
2741
+ /**
2742
+ * 根据左右匹配符号生产解析变量(自动删除变量内的空白)
2743
+ * @param {string} leftMatchSymbol
2744
+ * @param {string} rightMatchSymbol
2745
+ * @returns RegExp
2746
+ */
2747
+ function parseVariableRegExp(leftMatchSymbol, rightMatchSymbol) {
2748
+ return new RegExp(`${escapeRegExp(leftMatchSymbol.trim())}\\s*([^${escapeRegExp(uniqueSymbol(leftMatchSymbol))}${escapeRegExp(uniqueSymbol(rightMatchSymbol))}\\s]*)\\s*${rightMatchSymbol.trim()}`, 'g');
2749
+ }
2750
+ /**
2751
+ * 解析字符串的插值变量
2752
+ * @param {string} str 字符串
2753
+ * @param {string} leftMatchSymbol 变量左侧匹配符号,默认:{
2754
+ * @param {string} rightMatchSymbol 变量右侧匹配符号,默认:}
2755
+ * @returns string[]
2756
+ * @example
2757
+ *
2758
+ * default match symbol {} same as /{\s*([^{}\s]*)\s*}/g
2759
+ */
2760
+ function parseVarFromString(str, leftMatchSymbol = '{', rightMatchSymbol = '}') {
2761
+ return Array.from(str.matchAll(parseVariableRegExp(leftMatchSymbol, rightMatchSymbol))).map(el => el?.[1]);
2762
+ }
2763
+ /**
2764
+ * 替换字符串中的插值变量
2765
+ * @param {string} sourceStr
2766
+ * @param {Record<string, any>} targetObj
2767
+ * @param {string} leftMatchSymbol 变量左侧匹配符号,默认:{
2768
+ * @param {string} rightMatchSymbol 变量右侧匹配符号,默认:}
2769
+ * @returns string
2770
+ */
2771
+ function replaceVarFromString(sourceStr, targetObj, leftMatchSymbol = '{', rightMatchSymbol = '}') {
2772
+ return sourceStr.replace(new RegExp(parseVariableRegExp(leftMatchSymbol, rightMatchSymbol)), function (m, p1) {
2773
+ return objectHas(targetObj, p1) ? targetObj[p1] : m;
2774
+ });
2775
+ }
2776
+ /**
2777
+ * 在指定作用域中执行代码
2778
+ * @param {string} code 要执行的代码(需包含 return 语句或表达式)
2779
+ * @param {Object} scope 作用域对象(键值对形式的变量环境)
2780
+ * @returns 代码执行结果
2781
+ *
2782
+ * @example
2783
+ * // 测试用例 1: 基本变量访问
2784
+ * executeInScope("return a + b;", { a: 1, b: 2 });
2785
+ * // 3
2786
+ *
2787
+ * // 测试用例 2: 支持复杂表达式和运算
2788
+ * executeInScope(
2789
+ * "return Array.from({ length: 3 }, (_, i) => base + i);",
2790
+ * { base: 100 }
2791
+ * );
2792
+ * // [100, 101, 102]
2793
+ *
2794
+ * // 支持外传函数作用域执行
2795
+ * const scope = {
2796
+ * $: {
2797
+ * fun: {
2798
+ * time: {
2799
+ * now: function () {
2800
+ * return new Date();
2801
+ * },
2802
+ * },
2803
+ * },
2804
+ * },
2805
+ * };
2806
+ * executeInScope("return $.fun.time.now()", scope)
2807
+ */
2808
+ function executeInScope(code, scope = {}) {
2809
+ // 提取作用域对象的键和值
2810
+ const keys = Object.keys(scope);
2811
+ const values = keys.map(key => scope[key]);
2812
+ try {
2813
+ // 动态创建函数,将作用域的键作为参数,代码作为函数体
2814
+ const func = new Function(...keys, `return (() => { ${code} })()`);
2815
+ // 调用函数并传入作用域的值
2816
+ return func(...values);
2817
+ }
2818
+ catch (error) {
2819
+ throw new Error(`代码执行失败: ${error.message}`);
2820
+ }
2821
+ }
2822
+
2823
+ exports.EMAIL_REGEX = EMAIL_REGEX;
2597
2824
  exports.HEX_POOL = HEX_POOL;
2825
+ exports.HTTP_URL_REGEX = HTTP_URL_REGEX;
2826
+ exports.IPV4_REGEX = IPV4_REGEX;
2827
+ exports.IPV6_REGEX = IPV6_REGEX;
2828
+ exports.PHONE_REGEX = PHONE_REGEX;
2598
2829
  exports.STRING_ARABIC_NUMERALS = STRING_ARABIC_NUMERALS;
2599
2830
  exports.STRING_LOWERCASE_ALPHA = STRING_LOWERCASE_ALPHA;
2600
2831
  exports.STRING_POOL = STRING_POOL;
2601
2832
  exports.STRING_UPPERCASE_ALPHA = STRING_UPPERCASE_ALPHA;
2602
2833
  exports.UNIQUE_NUMBER_SAFE_LENGTH = UNIQUE_NUMBER_SAFE_LENGTH;
2834
+ exports.URL_REGEX = URL_REGEX;
2603
2835
  exports.add = add;
2604
2836
  exports.addClass = addClass;
2605
2837
  exports.arrayEach = arrayEach;
@@ -2630,6 +2862,8 @@
2630
2862
  exports.downloadHref = downloadHref;
2631
2863
  exports.downloadURL = downloadURL;
2632
2864
  exports.encodeToBase64 = encodeToBase64;
2865
+ exports.escapeRegExp = escapeRegExp;
2866
+ exports.executeInScope = executeInScope;
2633
2867
  exports.flatTree = flatTree;
2634
2868
  exports.forEachDeep = forEachDeep;
2635
2869
  exports.forEachMap = forEachMap;
@@ -2647,22 +2881,32 @@
2647
2881
  exports.isBigInt = isBigInt;
2648
2882
  exports.isBoolean = isBoolean;
2649
2883
  exports.isDate = isDate;
2884
+ exports.isDigit = isDigit;
2650
2885
  exports.isDomReady = isDomReady;
2886
+ exports.isEmail = isEmail;
2651
2887
  exports.isEmpty = isEmpty;
2652
2888
  exports.isError = isError;
2889
+ exports.isFloat = isFloat;
2653
2890
  exports.isFunction = isFunction;
2891
+ exports.isIdNo = isIdNo;
2892
+ exports.isInteger = isInteger;
2893
+ exports.isIpV4 = isIpV4;
2894
+ exports.isIpV6 = isIpV6;
2654
2895
  exports.isJsonString = isJsonString;
2655
2896
  exports.isNaN = isNaN;
2656
2897
  exports.isNull = isNull;
2657
2898
  exports.isNullOrUnDef = isNullOrUnDef;
2658
2899
  exports.isNumber = isNumber;
2900
+ exports.isNumerical = isNumerical;
2659
2901
  exports.isObject = isObject;
2902
+ exports.isPhone = isPhone;
2660
2903
  exports.isPlainObject = isPlainObject;
2661
2904
  exports.isPrimitive = isPrimitive;
2662
2905
  exports.isRegExp = isRegExp;
2663
2906
  exports.isString = isString;
2664
2907
  exports.isSymbol = isSymbol;
2665
2908
  exports.isUndefined = isUndefined;
2909
+ exports.isUrl = isUrl;
2666
2910
  exports.isValidDate = isValidDate;
2667
2911
  exports.multiply = multiply;
2668
2912
  exports.numberAbbr = numberAbbr;
@@ -2680,6 +2924,7 @@
2680
2924
  exports.onDomReady = onDomReady;
2681
2925
  exports.once = once;
2682
2926
  exports.parseQueryParams = parseQueryParams;
2927
+ exports.parseVarFromString = parseVarFromString;
2683
2928
  exports.pathJoin = pathJoin;
2684
2929
  exports.pathNormalize = pathNormalize;
2685
2930
  exports.qsParse = qsParse;
@@ -2688,6 +2933,7 @@
2688
2933
  exports.randomString = randomString;
2689
2934
  exports.randomUuid = randomUuid;
2690
2935
  exports.removeClass = removeClass;
2936
+ exports.replaceVarFromString = replaceVarFromString;
2691
2937
  exports.searchTreeById = searchTreeById;
2692
2938
  exports.setGlobal = setGlobal;
2693
2939
  exports.setStyle = setStyle;
@@ -2706,6 +2952,7 @@
2706
2952
  exports.typeIs = typeIs;
2707
2953
  exports.uniqueNumber = uniqueNumber;
2708
2954
  exports.uniqueString = uniqueString;
2955
+ exports.uniqueSymbol = uniqueSymbol;
2709
2956
  exports.urlDelParams = urlDelParams;
2710
2957
  exports.urlParse = urlParse;
2711
2958
  exports.urlSetParams = urlSetParams;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sculp-js",
3
- "version": "1.6.1",
3
+ "version": "1.7.0",
4
4
  "packageManager": "npm@8.19.2",
5
5
  "description": "js工具库",
6
6
  "scripts": {