sculp-js 1.7.2 → 1.8.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/README.md +5 -3
- package/lib/cjs/array.js +1 -1
- package/lib/cjs/async.js +1 -1
- package/lib/cjs/base64.js +1 -1
- package/lib/cjs/clipboard.js +1 -1
- package/lib/cjs/cookie.js +1 -1
- package/lib/cjs/date.js +1 -1
- package/lib/cjs/dom.js +1 -28
- package/lib/cjs/download.js +1 -1
- package/lib/cjs/easing.js +1 -1
- package/lib/cjs/file.js +1 -1
- package/lib/cjs/func.js +1 -1
- package/lib/cjs/index.js +3 -4
- package/lib/cjs/math.js +1 -1
- package/lib/cjs/number.js +1 -1
- package/lib/cjs/object.js +130 -1
- package/lib/cjs/path.js +1 -1
- package/lib/cjs/qs.js +1 -1
- package/lib/cjs/random.js +1 -1
- package/lib/cjs/string.js +1 -1
- package/lib/cjs/tooltip.js +1 -1
- package/lib/cjs/tree.js +1 -87
- package/lib/cjs/type.js +11 -4
- package/lib/cjs/unique.js +1 -1
- package/lib/cjs/url.js +1 -1
- package/lib/cjs/validator.js +1 -1
- package/lib/cjs/variable.js +1 -1
- package/lib/cjs/watermark.js +1 -1
- package/lib/cjs/we-decode.js +1 -1
- package/lib/es/array.js +1 -1
- package/lib/es/async.js +1 -1
- package/lib/es/base64.js +1 -1
- package/lib/es/clipboard.js +1 -1
- package/lib/es/cookie.js +1 -1
- package/lib/es/date.js +1 -1
- package/lib/es/dom.js +2 -27
- package/lib/es/download.js +1 -1
- package/lib/es/easing.js +1 -1
- package/lib/es/file.js +1 -1
- package/lib/es/func.js +1 -1
- package/lib/es/index.js +5 -5
- package/lib/es/math.js +1 -1
- package/lib/es/number.js +1 -1
- package/lib/es/object.js +130 -2
- package/lib/es/path.js +1 -1
- package/lib/es/qs.js +1 -1
- package/lib/es/random.js +1 -1
- package/lib/es/string.js +1 -1
- package/lib/es/tooltip.js +1 -1
- package/lib/es/tree.js +2 -87
- package/lib/es/type.js +11 -5
- package/lib/es/unique.js +1 -1
- package/lib/es/url.js +1 -1
- package/lib/es/validator.js +1 -1
- package/lib/es/variable.js +1 -1
- package/lib/es/watermark.js +1 -1
- package/lib/es/we-decode.js +1 -1
- package/lib/index.d.ts +24 -46
- package/lib/umd/index.js +140 -117
- package/package.json +3 -10
package/lib/umd/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* sculp-js v1.
|
|
2
|
+
* sculp-js v1.8.0
|
|
3
3
|
* (c) 2023-present chandq
|
|
4
4
|
* Released under the MIT License.
|
|
5
5
|
*/
|
|
@@ -122,11 +122,17 @@
|
|
|
122
122
|
return objectHas(any, 'length');
|
|
123
123
|
}
|
|
124
124
|
/**
|
|
125
|
-
*
|
|
125
|
+
* 判断任意值的数据类型,检查非对象时不如typeof、instanceof的性能高
|
|
126
|
+
*
|
|
127
|
+
* 当检查类对象时是不可靠的,对象可以通过定义 Symbol.toStringTag 属性来更改检查结果
|
|
128
|
+
*
|
|
129
|
+
* 详见:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/toString
|
|
126
130
|
* @param {unknown} any
|
|
127
|
-
* @returns
|
|
131
|
+
* @returns
|
|
128
132
|
*/
|
|
129
|
-
|
|
133
|
+
function typeIs(any) {
|
|
134
|
+
return Object.prototype.toString.call(any).slice(8, -1);
|
|
135
|
+
}
|
|
130
136
|
// 基本数据类型判断
|
|
131
137
|
const isString = (any) => typeof any === 'string';
|
|
132
138
|
const isBoolean = (any) => typeof any === 'boolean';
|
|
@@ -394,6 +400,13 @@
|
|
|
394
400
|
});
|
|
395
401
|
return source;
|
|
396
402
|
}
|
|
403
|
+
/**
|
|
404
|
+
* 获取对象指定层级下的属性值(现在可用ES6+的可选链?.来替代)
|
|
405
|
+
* @param {AnyObject} obj
|
|
406
|
+
* @param {string} path
|
|
407
|
+
* @param {boolean} strict
|
|
408
|
+
* @returns
|
|
409
|
+
*/
|
|
397
410
|
function objectGet(obj, path, strict = false) {
|
|
398
411
|
path = path.replace(/\[(\w+)\]/g, '.$1');
|
|
399
412
|
path = path.replace(/^\./, '');
|
|
@@ -529,6 +542,127 @@
|
|
|
529
542
|
}
|
|
530
543
|
return copy;
|
|
531
544
|
}
|
|
545
|
+
/**
|
|
546
|
+
* 比较两值是否相等,适用所有数据类型
|
|
547
|
+
* @param {Comparable} a
|
|
548
|
+
* @param {Comparable} b
|
|
549
|
+
* @returns {boolean}
|
|
550
|
+
*/
|
|
551
|
+
function isEqual(a, b) {
|
|
552
|
+
return deepEqual(a, b);
|
|
553
|
+
}
|
|
554
|
+
function deepEqual(a, b, compared = new WeakMap()) {
|
|
555
|
+
// 相同值快速返回
|
|
556
|
+
if (Object.is(a, b))
|
|
557
|
+
return true;
|
|
558
|
+
// 类型不同直接返回false
|
|
559
|
+
const typeA = Object.prototype.toString.call(a);
|
|
560
|
+
const typeB = Object.prototype.toString.call(b);
|
|
561
|
+
if (typeA !== typeB)
|
|
562
|
+
return false;
|
|
563
|
+
// 只缓存对象类型
|
|
564
|
+
if (isObject(a) && isObject(b)) {
|
|
565
|
+
if (compared.has(a))
|
|
566
|
+
return compared.get(a) === b;
|
|
567
|
+
compared.set(a, b);
|
|
568
|
+
compared.set(b, a);
|
|
569
|
+
}
|
|
570
|
+
// 处理特殊对象类型
|
|
571
|
+
switch (typeA) {
|
|
572
|
+
case '[object Date]':
|
|
573
|
+
return a.getTime() === b.getTime();
|
|
574
|
+
case '[object RegExp]':
|
|
575
|
+
return a.toString() === b.toString();
|
|
576
|
+
case '[object Map]':
|
|
577
|
+
return compareMap(a, b, compared);
|
|
578
|
+
case '[object Set]':
|
|
579
|
+
return compareSet(a, b, compared);
|
|
580
|
+
case '[object ArrayBuffer]':
|
|
581
|
+
return compareArrayBuffer(a, b);
|
|
582
|
+
case '[object DataView]':
|
|
583
|
+
return compareDataView(a, b, compared);
|
|
584
|
+
case '[object Int8Array]':
|
|
585
|
+
case '[object Uint8Array]':
|
|
586
|
+
case '[object Uint8ClampedArray]':
|
|
587
|
+
case '[object Int16Array]':
|
|
588
|
+
case '[object Uint16Array]':
|
|
589
|
+
case '[object Int32Array]':
|
|
590
|
+
case '[object Uint32Array]':
|
|
591
|
+
case '[object Float32Array]':
|
|
592
|
+
case '[object Float64Array]':
|
|
593
|
+
return compareTypedArray(a, b, compared);
|
|
594
|
+
case '[object Object]':
|
|
595
|
+
return compareObjects(a, b, compared);
|
|
596
|
+
case '[object Array]':
|
|
597
|
+
return compareArrays(a, b, compared);
|
|
598
|
+
}
|
|
599
|
+
return false;
|
|
600
|
+
}
|
|
601
|
+
// 辅助比较函数
|
|
602
|
+
function compareMap(a, b, compared) {
|
|
603
|
+
if (a.size !== b.size)
|
|
604
|
+
return false;
|
|
605
|
+
for (const [key, value] of a) {
|
|
606
|
+
if (!b.has(key) || !deepEqual(value, b.get(key), compared))
|
|
607
|
+
return false;
|
|
608
|
+
}
|
|
609
|
+
return true;
|
|
610
|
+
}
|
|
611
|
+
function compareSet(a, b, compared) {
|
|
612
|
+
if (a.size !== b.size)
|
|
613
|
+
return false;
|
|
614
|
+
for (const value of a) {
|
|
615
|
+
let found = false;
|
|
616
|
+
for (const bValue of b) {
|
|
617
|
+
if (deepEqual(value, bValue, compared)) {
|
|
618
|
+
found = true;
|
|
619
|
+
break;
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
if (!found)
|
|
623
|
+
return false;
|
|
624
|
+
}
|
|
625
|
+
return true;
|
|
626
|
+
}
|
|
627
|
+
function compareArrayBuffer(a, b) {
|
|
628
|
+
if (a.byteLength !== b.byteLength)
|
|
629
|
+
return false;
|
|
630
|
+
return new DataView(a).getInt32(0) === new DataView(b).getInt32(0);
|
|
631
|
+
}
|
|
632
|
+
function compareDataView(a, b, compared) {
|
|
633
|
+
return a.byteLength === b.byteLength && deepEqual(new Uint8Array(a.buffer), new Uint8Array(b.buffer), compared);
|
|
634
|
+
}
|
|
635
|
+
function compareTypedArray(a, b, compared) {
|
|
636
|
+
return a.byteLength === b.byteLength && deepEqual(Array.from(a), Array.from(b), compared);
|
|
637
|
+
}
|
|
638
|
+
function compareObjects(a, b, compared) {
|
|
639
|
+
const keysA = Reflect.ownKeys(a);
|
|
640
|
+
const keysB = Reflect.ownKeys(b);
|
|
641
|
+
if (keysA.length !== keysB.length)
|
|
642
|
+
return false;
|
|
643
|
+
for (const key of keysA) {
|
|
644
|
+
if (!keysB.includes(key))
|
|
645
|
+
return false;
|
|
646
|
+
if (!deepEqual(a[key], b[key], compared))
|
|
647
|
+
return false;
|
|
648
|
+
}
|
|
649
|
+
// 原型链比较
|
|
650
|
+
return Object.getPrototypeOf(a) === Object.getPrototypeOf(b);
|
|
651
|
+
}
|
|
652
|
+
function compareArrays(a, b, compared) {
|
|
653
|
+
// 增加有效索引检查
|
|
654
|
+
const keysA = Object.keys(a).map(Number);
|
|
655
|
+
const keysB = Object.keys(b).map(Number);
|
|
656
|
+
if (keysA.length !== keysB.length)
|
|
657
|
+
return false;
|
|
658
|
+
// 递归比较每个元素
|
|
659
|
+
for (let i = 0; i < a.length; i++) {
|
|
660
|
+
if (!deepEqual(a[i], b[i], compared))
|
|
661
|
+
return false;
|
|
662
|
+
}
|
|
663
|
+
// 比较数组对象的其他属性
|
|
664
|
+
return compareObjects(a, b, compared);
|
|
665
|
+
}
|
|
532
666
|
|
|
533
667
|
/**
|
|
534
668
|
* 将字符串转换为驼峰格式
|
|
@@ -773,31 +907,6 @@
|
|
|
773
907
|
render();
|
|
774
908
|
});
|
|
775
909
|
}
|
|
776
|
-
const domReadyCallbacks = [];
|
|
777
|
-
const eventType = 'DOMContentLoaded';
|
|
778
|
-
const listener = () => {
|
|
779
|
-
domReadyCallbacks.forEach(callback => callback());
|
|
780
|
-
domReadyCallbacks.length = 0;
|
|
781
|
-
document.removeEventListener(eventType, listener);
|
|
782
|
-
};
|
|
783
|
-
document.addEventListener(eventType, listener);
|
|
784
|
-
let readied = false;
|
|
785
|
-
function isDomReady() {
|
|
786
|
-
if (readied)
|
|
787
|
-
return true;
|
|
788
|
-
readied = ['complete', 'loaded', 'interactive'].indexOf(document.readyState) !== -1;
|
|
789
|
-
return readied;
|
|
790
|
-
}
|
|
791
|
-
function onDomReady(callback) {
|
|
792
|
-
// document readied
|
|
793
|
-
if (isDomReady()) {
|
|
794
|
-
setTimeout(callback, 0);
|
|
795
|
-
}
|
|
796
|
-
// listen document to ready
|
|
797
|
-
else {
|
|
798
|
-
domReadyCallbacks.push(callback);
|
|
799
|
-
}
|
|
800
|
-
}
|
|
801
910
|
/**
|
|
802
911
|
* 获取元素样式属性的计算值
|
|
803
912
|
* @param {HTMLElement} el
|
|
@@ -2376,91 +2485,6 @@
|
|
|
2376
2485
|
};
|
|
2377
2486
|
return getIds(toFlatArray(tree));
|
|
2378
2487
|
}
|
|
2379
|
-
/**
|
|
2380
|
-
* 使用迭代函数转换数组
|
|
2381
|
-
* @param {T} array
|
|
2382
|
-
* @param {Function} callback 迭代函数
|
|
2383
|
-
* @returns {Array}
|
|
2384
|
-
*/
|
|
2385
|
-
function flatMap(array, callback) {
|
|
2386
|
-
const result = [];
|
|
2387
|
-
array.forEach((value, index) => {
|
|
2388
|
-
result.push(...callback(value, index, array));
|
|
2389
|
-
});
|
|
2390
|
-
return result;
|
|
2391
|
-
}
|
|
2392
|
-
/**
|
|
2393
|
-
* 根据 idProp 与 parentIdProp 从对象数组中构建对应的树
|
|
2394
|
-
* 当 A[parentIdProp] === B[idProp] 时,对象A会被移动到对象B的children。
|
|
2395
|
-
* 当一个对象的 parentIdProp 不与其他对象的 idProp 字段相等时,该对象被作为树的顶层节点
|
|
2396
|
-
* @param {string} idProp 元素ID
|
|
2397
|
-
* @param {string} parentIdProp 父元素ID
|
|
2398
|
-
* @param {object[]} items 一维数组
|
|
2399
|
-
* @returns {WithChildren<T>[]} 树
|
|
2400
|
-
* @example
|
|
2401
|
-
* const array = [
|
|
2402
|
-
* { id: 'node-1', parent: 'root' },
|
|
2403
|
-
* { id: 'node-2', parent: 'root' },
|
|
2404
|
-
* { id: 'node-3', parent: 'node-2' },
|
|
2405
|
-
* { id: 'node-4', parent: 'node-2' },
|
|
2406
|
-
* { id: 'node-5', parent: 'node-4' },
|
|
2407
|
-
* ]
|
|
2408
|
-
* const tree = buildTree('id', 'parent', array)
|
|
2409
|
-
* expect(tree).toEqual([
|
|
2410
|
-
* { id: 'node-1', parent: 'root' },
|
|
2411
|
-
* {
|
|
2412
|
-
* id: 'node-2',
|
|
2413
|
-
* parent: 'root',
|
|
2414
|
-
* children: [
|
|
2415
|
-
* { id: 'node-3', parent: 'node-2' },
|
|
2416
|
-
* {
|
|
2417
|
-
* id: 'node-4',
|
|
2418
|
-
* parent: 'node-2',
|
|
2419
|
-
* children: [{ id: 'node-5', parent: 'node-4' }],
|
|
2420
|
-
* },
|
|
2421
|
-
* ],
|
|
2422
|
-
* },
|
|
2423
|
-
* ])
|
|
2424
|
-
*/
|
|
2425
|
-
function buildTree(idProp, parentIdProp, items) {
|
|
2426
|
-
const wrapperMap = new Map();
|
|
2427
|
-
const ensure = (id) => {
|
|
2428
|
-
if (wrapperMap.has(id)) {
|
|
2429
|
-
return wrapperMap.get(id);
|
|
2430
|
-
}
|
|
2431
|
-
//@ts-ignore
|
|
2432
|
-
const wrapper = { id, parent: null, item: null, children: [] };
|
|
2433
|
-
wrapperMap.set(id, wrapper);
|
|
2434
|
-
return wrapper;
|
|
2435
|
-
};
|
|
2436
|
-
for (const item of items) {
|
|
2437
|
-
const parentWrapper = ensure(item[parentIdProp]);
|
|
2438
|
-
const itemWrapper = ensure(item[idProp]);
|
|
2439
|
-
//@ts-ignore
|
|
2440
|
-
itemWrapper.parent = parentWrapper;
|
|
2441
|
-
//@ts-ignore
|
|
2442
|
-
parentWrapper.children.push(itemWrapper);
|
|
2443
|
-
//@ts-ignore
|
|
2444
|
-
itemWrapper.item = item;
|
|
2445
|
-
}
|
|
2446
|
-
const topLevelWrappers = flatMap(Array.from(wrapperMap.values()).filter(wrapper => wrapper.parent === null), wrapper => wrapper.children);
|
|
2447
|
-
return unwrapRecursively(topLevelWrappers);
|
|
2448
|
-
function unwrapRecursively(wrapperArray) {
|
|
2449
|
-
const result = [];
|
|
2450
|
-
for (const wrapper of wrapperArray) {
|
|
2451
|
-
if (wrapper.children.length === 0) {
|
|
2452
|
-
result.push(wrapper.item);
|
|
2453
|
-
}
|
|
2454
|
-
else {
|
|
2455
|
-
result.push({
|
|
2456
|
-
...wrapper.item,
|
|
2457
|
-
children: unwrapRecursively(wrapper.children)
|
|
2458
|
-
});
|
|
2459
|
-
}
|
|
2460
|
-
}
|
|
2461
|
-
return result;
|
|
2462
|
-
}
|
|
2463
|
-
}
|
|
2464
2488
|
/**
|
|
2465
2489
|
* 扁平化数组转换成树(效率高于buildTree)
|
|
2466
2490
|
* @param {any[]} list
|
|
@@ -2943,7 +2967,6 @@
|
|
|
2943
2967
|
exports.arrayLike = arrayLike;
|
|
2944
2968
|
exports.arrayRemove = arrayRemove;
|
|
2945
2969
|
exports.asyncMap = asyncMap;
|
|
2946
|
-
exports.buildTree = buildTree;
|
|
2947
2970
|
exports.calculateDate = calculateDate;
|
|
2948
2971
|
exports.calculateDateTime = calculateDateTime;
|
|
2949
2972
|
exports.chooseLocalFile = chooseLocalFile;
|
|
@@ -2984,9 +3007,9 @@
|
|
|
2984
3007
|
exports.isBoolean = isBoolean;
|
|
2985
3008
|
exports.isDate = isDate;
|
|
2986
3009
|
exports.isDigit = isDigit;
|
|
2987
|
-
exports.isDomReady = isDomReady;
|
|
2988
3010
|
exports.isEmail = isEmail;
|
|
2989
3011
|
exports.isEmpty = isEmpty;
|
|
3012
|
+
exports.isEqual = isEqual;
|
|
2990
3013
|
exports.isError = isError;
|
|
2991
3014
|
exports.isFloat = isFloat;
|
|
2992
3015
|
exports.isFunction = isFunction;
|
|
@@ -2998,6 +3021,7 @@
|
|
|
2998
3021
|
exports.isNaN = isNaN;
|
|
2999
3022
|
exports.isNull = isNull;
|
|
3000
3023
|
exports.isNullOrUnDef = isNullOrUnDef;
|
|
3024
|
+
exports.isNullish = isNullOrUnDef;
|
|
3001
3025
|
exports.isNumber = isNumber;
|
|
3002
3026
|
exports.isNumerical = isNumerical;
|
|
3003
3027
|
exports.isObject = isObject;
|
|
@@ -3024,7 +3048,6 @@
|
|
|
3024
3048
|
exports.objectMerge = objectAssign;
|
|
3025
3049
|
exports.objectOmit = objectOmit;
|
|
3026
3050
|
exports.objectPick = objectPick;
|
|
3027
|
-
exports.onDomReady = onDomReady;
|
|
3028
3051
|
exports.once = once;
|
|
3029
3052
|
exports.parseQueryParams = parseQueryParams;
|
|
3030
3053
|
exports.parseVarFromString = parseVarFromString;
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sculp-js",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.8.0",
|
|
4
4
|
"packageManager": "npm@8.19.2",
|
|
5
|
-
"description": "js
|
|
5
|
+
"description": "js utils library, includes function library、class library",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"prepare": "husky install",
|
|
8
8
|
"build": "rollup --bundleConfigAsCjs --config rollup.config.js",
|
|
@@ -19,7 +19,6 @@
|
|
|
19
19
|
"release:major": "standard-version --release-as major",
|
|
20
20
|
"commit": "git-cz"
|
|
21
21
|
},
|
|
22
|
-
"author": "chendq <deqiaochen@gmail.com>",
|
|
23
22
|
"main": "lib/cjs/index.js",
|
|
24
23
|
"module": "lib/es/index.js",
|
|
25
24
|
"browser": "lib/umd/index.js",
|
|
@@ -49,8 +48,7 @@
|
|
|
49
48
|
"license": "MIT",
|
|
50
49
|
"homepage": "https://github.com/chandq/sculp-js#readme",
|
|
51
50
|
"dependencies": {
|
|
52
|
-
"bezier-easing": "^2.1.0"
|
|
53
|
-
"core-js": "^3.33.0"
|
|
51
|
+
"bezier-easing": "^2.1.0"
|
|
54
52
|
},
|
|
55
53
|
"devDependencies": {
|
|
56
54
|
"@babel/core": "^7.23.2",
|
|
@@ -89,11 +87,6 @@
|
|
|
89
87
|
"rollup-plugin-dts": "^6.1.0",
|
|
90
88
|
"rollup-plugin-subpath-externals": "^3.4.0",
|
|
91
89
|
"standard-version": "^9.5.0",
|
|
92
|
-
"stylelint": "14.16",
|
|
93
|
-
"stylelint-config-css-modules": "^4.3.0",
|
|
94
|
-
"stylelint-config-prettier": "^9.0.5",
|
|
95
|
-
"stylelint-config-standard": "^20.0.0",
|
|
96
|
-
"ts-loader": "^9.5.0",
|
|
97
90
|
"typescript": "5.0.4"
|
|
98
91
|
},
|
|
99
92
|
"config": {
|