sculp-js 1.7.2 → 1.8.1
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 +6 -4
- 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 +133 -4
- package/lib/cjs/path.js +3 -3
- 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 +12 -96
- 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 +7 -6
- package/lib/es/array.js +6 -4
- 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 +133 -5
- package/lib/es/path.js +3 -3
- 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 +13 -96
- 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 +7 -6
- package/lib/index.d.ts +27 -49
- package/lib/umd/index.js +166 -139
- package/package.json +3 -10
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
# sculp-js
|
|
9
9
|
|
|
10
|
-
[API
|
|
10
|
+
[API Doc](https://chandq.github.io/sculp-js/)
|
|
11
11
|
|
|
12
12
|
> TS + Rollup, native implementation, without relying on any third-party libraries, outputs products of three module modes: ESM, CJS, and UMD. sculp-js only used to Web environment, @sculp/core can be used to Web、Node.js、Mini Program.
|
|
13
13
|
|
|
@@ -29,13 +29,14 @@
|
|
|
29
29
|
- isNumber
|
|
30
30
|
- isUndefined
|
|
31
31
|
- isNull
|
|
32
|
-
-
|
|
32
|
+
- isNullish
|
|
33
33
|
- isPrimitive
|
|
34
34
|
- isFunction
|
|
35
35
|
- isObject
|
|
36
36
|
- isArray
|
|
37
37
|
- typeIs
|
|
38
38
|
- isJsonString
|
|
39
|
+
- isEmpty
|
|
39
40
|
|
|
40
41
|
- encode/decode
|
|
41
42
|
|
|
@@ -60,11 +61,12 @@
|
|
|
60
61
|
|
|
61
62
|
- isPlainObject
|
|
62
63
|
- objectHas
|
|
63
|
-
- objectAssign
|
|
64
|
+
- objectAssign
|
|
64
65
|
- objectEach
|
|
65
66
|
- objectEachAsync
|
|
66
67
|
- objectGet
|
|
67
68
|
- cloneDeep
|
|
69
|
+
- isEqual
|
|
68
70
|
|
|
69
71
|
- Number
|
|
70
72
|
|
package/lib/cjs/array.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* sculp-js v1.
|
|
2
|
+
* sculp-js v1.8.1
|
|
3
3
|
* (c) 2023-present chandq
|
|
4
4
|
* Released under the MIT License.
|
|
5
5
|
*/
|
|
@@ -26,7 +26,7 @@ function arrayEach(array, iterator, reverse = false) {
|
|
|
26
26
|
}
|
|
27
27
|
}
|
|
28
28
|
else {
|
|
29
|
-
for (let idx = 0
|
|
29
|
+
for (let idx = 0, len = array.length; idx < len; idx++) {
|
|
30
30
|
const val = array[idx];
|
|
31
31
|
const re = iterator(val, idx, array);
|
|
32
32
|
if (re === false)
|
|
@@ -51,7 +51,7 @@ async function arrayEachAsync(array, iterator, reverse = false) {
|
|
|
51
51
|
}
|
|
52
52
|
}
|
|
53
53
|
else {
|
|
54
|
-
for (let idx = 0
|
|
54
|
+
for (let idx = 0, len = array.length; idx < len; idx++) {
|
|
55
55
|
const val = array[idx];
|
|
56
56
|
if ((await iterator(val, idx)) === false)
|
|
57
57
|
break;
|
|
@@ -88,7 +88,9 @@ function arrayRemove(array, expect) {
|
|
|
88
88
|
if (_expect(val, idx))
|
|
89
89
|
indexes.push(idx);
|
|
90
90
|
});
|
|
91
|
-
indexes
|
|
91
|
+
arrayEach(indexes, (val, idx) => {
|
|
92
|
+
array.splice(val - idx, 1);
|
|
93
|
+
});
|
|
92
94
|
return array;
|
|
93
95
|
}
|
|
94
96
|
|
package/lib/cjs/async.js
CHANGED
package/lib/cjs/base64.js
CHANGED
package/lib/cjs/clipboard.js
CHANGED
package/lib/cjs/cookie.js
CHANGED
package/lib/cjs/date.js
CHANGED
package/lib/cjs/dom.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* sculp-js v1.
|
|
2
|
+
* sculp-js v1.8.1
|
|
3
3
|
* (c) 2023-present chandq
|
|
4
4
|
* Released under the MIT License.
|
|
5
5
|
*/
|
|
@@ -118,31 +118,6 @@ function smoothScroll(options) {
|
|
|
118
118
|
render();
|
|
119
119
|
});
|
|
120
120
|
}
|
|
121
|
-
const domReadyCallbacks = [];
|
|
122
|
-
const eventType = 'DOMContentLoaded';
|
|
123
|
-
const listener = () => {
|
|
124
|
-
domReadyCallbacks.forEach(callback => callback());
|
|
125
|
-
domReadyCallbacks.length = 0;
|
|
126
|
-
document.removeEventListener(eventType, listener);
|
|
127
|
-
};
|
|
128
|
-
document.addEventListener(eventType, listener);
|
|
129
|
-
let readied = false;
|
|
130
|
-
function isDomReady() {
|
|
131
|
-
if (readied)
|
|
132
|
-
return true;
|
|
133
|
-
readied = ['complete', 'loaded', 'interactive'].indexOf(document.readyState) !== -1;
|
|
134
|
-
return readied;
|
|
135
|
-
}
|
|
136
|
-
function onDomReady(callback) {
|
|
137
|
-
// document readied
|
|
138
|
-
if (isDomReady()) {
|
|
139
|
-
setTimeout(callback, 0);
|
|
140
|
-
}
|
|
141
|
-
// listen document to ready
|
|
142
|
-
else {
|
|
143
|
-
domReadyCallbacks.push(callback);
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
121
|
/**
|
|
147
122
|
* 获取元素样式属性的计算值
|
|
148
123
|
* @param {HTMLElement} el
|
|
@@ -190,8 +165,6 @@ exports.getComputedCssVal = getComputedCssVal;
|
|
|
190
165
|
exports.getStrWidthPx = getStrWidthPx;
|
|
191
166
|
exports.getStyle = getStyle;
|
|
192
167
|
exports.hasClass = hasClass;
|
|
193
|
-
exports.isDomReady = isDomReady;
|
|
194
|
-
exports.onDomReady = onDomReady;
|
|
195
168
|
exports.removeClass = removeClass;
|
|
196
169
|
exports.setStyle = setStyle;
|
|
197
170
|
exports.smoothScroll = smoothScroll;
|
package/lib/cjs/download.js
CHANGED
package/lib/cjs/easing.js
CHANGED
package/lib/cjs/file.js
CHANGED
package/lib/cjs/func.js
CHANGED
package/lib/cjs/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* sculp-js v1.
|
|
2
|
+
* sculp-js v1.8.1
|
|
3
3
|
* (c) 2023-present chandq
|
|
4
4
|
* Released under the MIT License.
|
|
5
5
|
*/
|
|
@@ -55,8 +55,6 @@ exports.getComputedCssVal = dom.getComputedCssVal;
|
|
|
55
55
|
exports.getStrWidthPx = dom.getStrWidthPx;
|
|
56
56
|
exports.getStyle = dom.getStyle;
|
|
57
57
|
exports.hasClass = dom.hasClass;
|
|
58
|
-
exports.isDomReady = dom.isDomReady;
|
|
59
|
-
exports.onDomReady = dom.onDomReady;
|
|
60
58
|
exports.removeClass = dom.removeClass;
|
|
61
59
|
exports.setStyle = dom.setStyle;
|
|
62
60
|
exports.smoothScroll = dom.smoothScroll;
|
|
@@ -66,6 +64,7 @@ exports.downloadData = download.downloadData;
|
|
|
66
64
|
exports.downloadHref = download.downloadHref;
|
|
67
65
|
exports.downloadURL = download.downloadURL;
|
|
68
66
|
exports.cloneDeep = object.cloneDeep;
|
|
67
|
+
exports.isEqual = object.isEqual;
|
|
69
68
|
exports.isPlainObject = object.isPlainObject;
|
|
70
69
|
exports.objectAssign = object.objectAssign;
|
|
71
70
|
exports.objectEach = object.objectEach;
|
|
@@ -102,6 +101,7 @@ exports.isJsonString = type.isJsonString;
|
|
|
102
101
|
exports.isNaN = type.isNaN;
|
|
103
102
|
exports.isNull = type.isNull;
|
|
104
103
|
exports.isNullOrUnDef = type.isNullOrUnDef;
|
|
104
|
+
exports.isNullish = type.isNullOrUnDef;
|
|
105
105
|
exports.isNumber = type.isNumber;
|
|
106
106
|
exports.isObject = type.isObject;
|
|
107
107
|
exports.isPrimitive = type.isPrimitive;
|
|
@@ -138,7 +138,6 @@ exports.UNIQUE_NUMBER_SAFE_LENGTH = unique.UNIQUE_NUMBER_SAFE_LENGTH;
|
|
|
138
138
|
exports.uniqueNumber = unique.uniqueNumber;
|
|
139
139
|
exports.uniqueString = unique.uniqueString;
|
|
140
140
|
exports.tooltipEvent = tooltip.tooltipEvent;
|
|
141
|
-
exports.buildTree = tree.buildTree;
|
|
142
141
|
exports.flatTree = tree.flatTree;
|
|
143
142
|
exports.forEachDeep = tree.forEachDeep;
|
|
144
143
|
exports.formatTree = tree.formatTree;
|
package/lib/cjs/math.js
CHANGED
package/lib/cjs/number.js
CHANGED
package/lib/cjs/object.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* sculp-js v1.
|
|
2
|
+
* sculp-js v1.8.1
|
|
3
3
|
* (c) 2023-present chandq
|
|
4
4
|
* Released under the MIT License.
|
|
5
5
|
*/
|
|
@@ -143,7 +143,7 @@ const merge = (map, source, target) => {
|
|
|
143
143
|
*/
|
|
144
144
|
function objectAssign(source, ...targets) {
|
|
145
145
|
const map = new Map();
|
|
146
|
-
for (let i = 0
|
|
146
|
+
for (let i = 0, len = targets.length; i < len; i++) {
|
|
147
147
|
const target = targets[i];
|
|
148
148
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
149
149
|
// @ts-ignore
|
|
@@ -168,6 +168,13 @@ function objectFill(source, target, fillable) {
|
|
|
168
168
|
});
|
|
169
169
|
return source;
|
|
170
170
|
}
|
|
171
|
+
/**
|
|
172
|
+
* 获取对象指定层级下的属性值(现在可用ES6+的可选链?.来替代)
|
|
173
|
+
* @param {AnyObject} obj
|
|
174
|
+
* @param {string} path
|
|
175
|
+
* @param {boolean} strict
|
|
176
|
+
* @returns
|
|
177
|
+
*/
|
|
171
178
|
function objectGet(obj, path, strict = false) {
|
|
172
179
|
path = path.replace(/\[(\w+)\]/g, '.$1');
|
|
173
180
|
path = path.replace(/^\./, '');
|
|
@@ -261,10 +268,10 @@ function cloneDeep(source, map = new WeakMap()) {
|
|
|
261
268
|
}
|
|
262
269
|
// 处理数组 (包含稀疏数组)
|
|
263
270
|
if (Array.isArray(source)) {
|
|
264
|
-
const copy = Array
|
|
271
|
+
const copy = new Array(source.length);
|
|
265
272
|
map.set(source, copy);
|
|
266
273
|
// 克隆所有有效索引
|
|
267
|
-
for (let i = 0
|
|
274
|
+
for (let i = 0, len = source.length; i < len; i++) {
|
|
268
275
|
if (i in source) {
|
|
269
276
|
// 保留空位
|
|
270
277
|
copy[i] = cloneDeep(source[i], map);
|
|
@@ -303,8 +310,130 @@ function cloneDeep(source, map = new WeakMap()) {
|
|
|
303
310
|
}
|
|
304
311
|
return copy;
|
|
305
312
|
}
|
|
313
|
+
/**
|
|
314
|
+
* 比较两值是否相等,适用所有数据类型
|
|
315
|
+
* @param {Comparable} a
|
|
316
|
+
* @param {Comparable} b
|
|
317
|
+
* @returns {boolean}
|
|
318
|
+
*/
|
|
319
|
+
function isEqual(a, b) {
|
|
320
|
+
return deepEqual(a, b);
|
|
321
|
+
}
|
|
322
|
+
function deepEqual(a, b, compared = new WeakMap()) {
|
|
323
|
+
// 相同值快速返回
|
|
324
|
+
if (Object.is(a, b))
|
|
325
|
+
return true;
|
|
326
|
+
// 类型不同直接返回false
|
|
327
|
+
const typeA = Object.prototype.toString.call(a);
|
|
328
|
+
const typeB = Object.prototype.toString.call(b);
|
|
329
|
+
if (typeA !== typeB)
|
|
330
|
+
return false;
|
|
331
|
+
// 只缓存对象类型
|
|
332
|
+
if (type.isObject(a) && type.isObject(b)) {
|
|
333
|
+
if (compared.has(a))
|
|
334
|
+
return compared.get(a) === b;
|
|
335
|
+
compared.set(a, b);
|
|
336
|
+
compared.set(b, a);
|
|
337
|
+
}
|
|
338
|
+
// 处理特殊对象类型
|
|
339
|
+
switch (typeA) {
|
|
340
|
+
case '[object Date]':
|
|
341
|
+
return a.getTime() === b.getTime();
|
|
342
|
+
case '[object RegExp]':
|
|
343
|
+
return a.toString() === b.toString();
|
|
344
|
+
case '[object Map]':
|
|
345
|
+
return compareMap(a, b, compared);
|
|
346
|
+
case '[object Set]':
|
|
347
|
+
return compareSet(a, b, compared);
|
|
348
|
+
case '[object ArrayBuffer]':
|
|
349
|
+
return compareArrayBuffer(a, b);
|
|
350
|
+
case '[object DataView]':
|
|
351
|
+
return compareDataView(a, b, compared);
|
|
352
|
+
case '[object Int8Array]':
|
|
353
|
+
case '[object Uint8Array]':
|
|
354
|
+
case '[object Uint8ClampedArray]':
|
|
355
|
+
case '[object Int16Array]':
|
|
356
|
+
case '[object Uint16Array]':
|
|
357
|
+
case '[object Int32Array]':
|
|
358
|
+
case '[object Uint32Array]':
|
|
359
|
+
case '[object Float32Array]':
|
|
360
|
+
case '[object Float64Array]':
|
|
361
|
+
return compareTypedArray(a, b, compared);
|
|
362
|
+
case '[object Object]':
|
|
363
|
+
return compareObjects(a, b, compared);
|
|
364
|
+
case '[object Array]':
|
|
365
|
+
return compareArrays(a, b, compared);
|
|
366
|
+
}
|
|
367
|
+
return false;
|
|
368
|
+
}
|
|
369
|
+
// 辅助比较函数
|
|
370
|
+
function compareMap(a, b, compared) {
|
|
371
|
+
if (a.size !== b.size)
|
|
372
|
+
return false;
|
|
373
|
+
for (const [key, value] of a) {
|
|
374
|
+
if (!b.has(key) || !deepEqual(value, b.get(key), compared))
|
|
375
|
+
return false;
|
|
376
|
+
}
|
|
377
|
+
return true;
|
|
378
|
+
}
|
|
379
|
+
function compareSet(a, b, compared) {
|
|
380
|
+
if (a.size !== b.size)
|
|
381
|
+
return false;
|
|
382
|
+
for (const value of a) {
|
|
383
|
+
let found = false;
|
|
384
|
+
for (const bValue of b) {
|
|
385
|
+
if (deepEqual(value, bValue, compared)) {
|
|
386
|
+
found = true;
|
|
387
|
+
break;
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
if (!found)
|
|
391
|
+
return false;
|
|
392
|
+
}
|
|
393
|
+
return true;
|
|
394
|
+
}
|
|
395
|
+
function compareArrayBuffer(a, b) {
|
|
396
|
+
if (a.byteLength !== b.byteLength)
|
|
397
|
+
return false;
|
|
398
|
+
return new DataView(a).getInt32(0) === new DataView(b).getInt32(0);
|
|
399
|
+
}
|
|
400
|
+
function compareDataView(a, b, compared) {
|
|
401
|
+
return a.byteLength === b.byteLength && deepEqual(new Uint8Array(a.buffer), new Uint8Array(b.buffer), compared);
|
|
402
|
+
}
|
|
403
|
+
function compareTypedArray(a, b, compared) {
|
|
404
|
+
return a.byteLength === b.byteLength && deepEqual(Array.from(a), Array.from(b), compared);
|
|
405
|
+
}
|
|
406
|
+
function compareObjects(a, b, compared) {
|
|
407
|
+
const keysA = Reflect.ownKeys(a);
|
|
408
|
+
const keysB = Reflect.ownKeys(b);
|
|
409
|
+
if (keysA.length !== keysB.length)
|
|
410
|
+
return false;
|
|
411
|
+
for (const key of keysA) {
|
|
412
|
+
if (!keysB.includes(key))
|
|
413
|
+
return false;
|
|
414
|
+
if (!deepEqual(a[key], b[key], compared))
|
|
415
|
+
return false;
|
|
416
|
+
}
|
|
417
|
+
// 原型链比较
|
|
418
|
+
return Object.getPrototypeOf(a) === Object.getPrototypeOf(b);
|
|
419
|
+
}
|
|
420
|
+
function compareArrays(a, b, compared) {
|
|
421
|
+
// 增加有效索引检查
|
|
422
|
+
const keysA = Object.keys(a).map(Number);
|
|
423
|
+
const keysB = Object.keys(b).map(Number);
|
|
424
|
+
if (keysA.length !== keysB.length)
|
|
425
|
+
return false;
|
|
426
|
+
// 递归比较每个元素
|
|
427
|
+
for (let i = 0, len = a.length; i < len; i++) {
|
|
428
|
+
if (!deepEqual(a[i], b[i], compared))
|
|
429
|
+
return false;
|
|
430
|
+
}
|
|
431
|
+
// 比较数组对象的其他属性
|
|
432
|
+
return compareObjects(a, b, compared);
|
|
433
|
+
}
|
|
306
434
|
|
|
307
435
|
exports.cloneDeep = cloneDeep;
|
|
436
|
+
exports.isEqual = isEqual;
|
|
308
437
|
exports.isPlainObject = isPlainObject;
|
|
309
438
|
exports.objectAssign = objectAssign;
|
|
310
439
|
exports.objectEach = objectEach;
|
package/lib/cjs/path.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* sculp-js v1.
|
|
2
|
+
* sculp-js v1.8.1
|
|
3
3
|
* (c) 2023-present chandq
|
|
4
4
|
* Released under the MIT License.
|
|
5
5
|
*/
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* @returns {string}
|
|
13
13
|
*/
|
|
14
14
|
const pathNormalize = (path) => {
|
|
15
|
-
const
|
|
15
|
+
const slices = path
|
|
16
16
|
.replace(/\\/g, '/')
|
|
17
17
|
.replace(/\/{2,}/g, '/')
|
|
18
18
|
.replace(/\.{3,}/g, '..')
|
|
@@ -37,7 +37,7 @@ const pathNormalize = (path) => {
|
|
|
37
37
|
points.pop();
|
|
38
38
|
}
|
|
39
39
|
};
|
|
40
|
-
|
|
40
|
+
slices.forEach(slice => {
|
|
41
41
|
const isCurrent = isCurrentSlice(slice);
|
|
42
42
|
const isParent = isParentSlice(slice);
|
|
43
43
|
// 未进入实际路径
|
package/lib/cjs/qs.js
CHANGED
package/lib/cjs/random.js
CHANGED
package/lib/cjs/string.js
CHANGED
package/lib/cjs/tooltip.js
CHANGED
package/lib/cjs/tree.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* sculp-js v1.
|
|
2
|
+
* sculp-js v1.8.1
|
|
3
3
|
* (c) 2023-present chandq
|
|
4
4
|
* Released under the MIT License.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
'use strict';
|
|
8
8
|
|
|
9
|
+
var array = require('./array.js');
|
|
9
10
|
var object = require('./object.js');
|
|
10
11
|
var type = require('./type.js');
|
|
11
12
|
|
|
@@ -48,7 +49,7 @@ function forEachDeep(tree, iterator, children = 'children', isReverse = false) {
|
|
|
48
49
|
}
|
|
49
50
|
}
|
|
50
51
|
else {
|
|
51
|
-
for (let i = 0
|
|
52
|
+
for (let i = 0, len = arr.length; i < len; i++) {
|
|
52
53
|
if (isBreak) {
|
|
53
54
|
break;
|
|
54
55
|
}
|
|
@@ -174,92 +175,7 @@ function searchTreeById(tree, nodeId, config) {
|
|
|
174
175
|
return getIds(toFlatArray(tree));
|
|
175
176
|
}
|
|
176
177
|
/**
|
|
177
|
-
*
|
|
178
|
-
* @param {T} array
|
|
179
|
-
* @param {Function} callback 迭代函数
|
|
180
|
-
* @returns {Array}
|
|
181
|
-
*/
|
|
182
|
-
function flatMap(array, callback) {
|
|
183
|
-
const result = [];
|
|
184
|
-
array.forEach((value, index) => {
|
|
185
|
-
result.push(...callback(value, index, array));
|
|
186
|
-
});
|
|
187
|
-
return result;
|
|
188
|
-
}
|
|
189
|
-
/**
|
|
190
|
-
* 根据 idProp 与 parentIdProp 从对象数组中构建对应的树
|
|
191
|
-
* 当 A[parentIdProp] === B[idProp] 时,对象A会被移动到对象B的children。
|
|
192
|
-
* 当一个对象的 parentIdProp 不与其他对象的 idProp 字段相等时,该对象被作为树的顶层节点
|
|
193
|
-
* @param {string} idProp 元素ID
|
|
194
|
-
* @param {string} parentIdProp 父元素ID
|
|
195
|
-
* @param {object[]} items 一维数组
|
|
196
|
-
* @returns {WithChildren<T>[]} 树
|
|
197
|
-
* @example
|
|
198
|
-
* const array = [
|
|
199
|
-
* { id: 'node-1', parent: 'root' },
|
|
200
|
-
* { id: 'node-2', parent: 'root' },
|
|
201
|
-
* { id: 'node-3', parent: 'node-2' },
|
|
202
|
-
* { id: 'node-4', parent: 'node-2' },
|
|
203
|
-
* { id: 'node-5', parent: 'node-4' },
|
|
204
|
-
* ]
|
|
205
|
-
* const tree = buildTree('id', 'parent', array)
|
|
206
|
-
* expect(tree).toEqual([
|
|
207
|
-
* { id: 'node-1', parent: 'root' },
|
|
208
|
-
* {
|
|
209
|
-
* id: 'node-2',
|
|
210
|
-
* parent: 'root',
|
|
211
|
-
* children: [
|
|
212
|
-
* { id: 'node-3', parent: 'node-2' },
|
|
213
|
-
* {
|
|
214
|
-
* id: 'node-4',
|
|
215
|
-
* parent: 'node-2',
|
|
216
|
-
* children: [{ id: 'node-5', parent: 'node-4' }],
|
|
217
|
-
* },
|
|
218
|
-
* ],
|
|
219
|
-
* },
|
|
220
|
-
* ])
|
|
221
|
-
*/
|
|
222
|
-
function buildTree(idProp, parentIdProp, items) {
|
|
223
|
-
const wrapperMap = new Map();
|
|
224
|
-
const ensure = (id) => {
|
|
225
|
-
if (wrapperMap.has(id)) {
|
|
226
|
-
return wrapperMap.get(id);
|
|
227
|
-
}
|
|
228
|
-
//@ts-ignore
|
|
229
|
-
const wrapper = { id, parent: null, item: null, children: [] };
|
|
230
|
-
wrapperMap.set(id, wrapper);
|
|
231
|
-
return wrapper;
|
|
232
|
-
};
|
|
233
|
-
for (const item of items) {
|
|
234
|
-
const parentWrapper = ensure(item[parentIdProp]);
|
|
235
|
-
const itemWrapper = ensure(item[idProp]);
|
|
236
|
-
//@ts-ignore
|
|
237
|
-
itemWrapper.parent = parentWrapper;
|
|
238
|
-
//@ts-ignore
|
|
239
|
-
parentWrapper.children.push(itemWrapper);
|
|
240
|
-
//@ts-ignore
|
|
241
|
-
itemWrapper.item = item;
|
|
242
|
-
}
|
|
243
|
-
const topLevelWrappers = flatMap(Array.from(wrapperMap.values()).filter(wrapper => wrapper.parent === null), wrapper => wrapper.children);
|
|
244
|
-
return unwrapRecursively(topLevelWrappers);
|
|
245
|
-
function unwrapRecursively(wrapperArray) {
|
|
246
|
-
const result = [];
|
|
247
|
-
for (const wrapper of wrapperArray) {
|
|
248
|
-
if (wrapper.children.length === 0) {
|
|
249
|
-
result.push(wrapper.item);
|
|
250
|
-
}
|
|
251
|
-
else {
|
|
252
|
-
result.push({
|
|
253
|
-
...wrapper.item,
|
|
254
|
-
children: unwrapRecursively(wrapper.children)
|
|
255
|
-
});
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
return result;
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
/**
|
|
262
|
-
* 扁平化数组转换成树(效率高于buildTree)
|
|
178
|
+
* 扁平化数组转换成树
|
|
263
179
|
* @param {any[]} list
|
|
264
180
|
* @param {IFieldOptions} options
|
|
265
181
|
* @returns {any[]}
|
|
@@ -268,10 +184,10 @@ function formatTree(list, options = defaultFieldOptions) {
|
|
|
268
184
|
const { keyField, childField, pidField } = options;
|
|
269
185
|
const treeArr = [];
|
|
270
186
|
const sourceMap = {};
|
|
271
|
-
|
|
187
|
+
array.arrayEach(list, item => {
|
|
272
188
|
sourceMap[item[keyField]] = item;
|
|
273
189
|
});
|
|
274
|
-
|
|
190
|
+
array.arrayEach(list, item => {
|
|
275
191
|
const parent = sourceMap[item[pidField]];
|
|
276
192
|
if (parent) {
|
|
277
193
|
(parent[childField] || (parent[childField] = [])).push(item);
|
|
@@ -290,7 +206,8 @@ function formatTree(list, options = defaultFieldOptions) {
|
|
|
290
206
|
*/
|
|
291
207
|
function flatTree(treeList, options = defaultFieldOptions) {
|
|
292
208
|
const { childField, keyField, pidField } = options;
|
|
293
|
-
|
|
209
|
+
let res = [];
|
|
210
|
+
array.arrayEach(treeList, node => {
|
|
294
211
|
const item = {
|
|
295
212
|
...node,
|
|
296
213
|
[childField]: [] // 清空子级
|
|
@@ -304,8 +221,8 @@ function flatTree(treeList, options = defaultFieldOptions) {
|
|
|
304
221
|
}));
|
|
305
222
|
res = res.concat(flatTree(children, options));
|
|
306
223
|
}
|
|
307
|
-
|
|
308
|
-
|
|
224
|
+
});
|
|
225
|
+
return res;
|
|
309
226
|
}
|
|
310
227
|
/**
|
|
311
228
|
* 模糊搜索函数,返回包含搜索字符的节点及其祖先节点, 适用于树型组件的字符过滤功能
|
|
@@ -327,7 +244,7 @@ function fuzzySearchTree(nodes, filterCondition, options = defaultSearchTreeOpti
|
|
|
327
244
|
return nodes;
|
|
328
245
|
}
|
|
329
246
|
const result = [];
|
|
330
|
-
|
|
247
|
+
array.arrayEach(nodes, node => {
|
|
331
248
|
// 递归检查子节点是否匹配
|
|
332
249
|
const matchedChildren = node[options.childField] && node[options.childField].length > 0
|
|
333
250
|
? fuzzySearchTree(node[options.childField] || [], filterCondition, options)
|
|
@@ -367,11 +284,10 @@ function fuzzySearchTree(nodes, filterCondition, options = defaultSearchTreeOpti
|
|
|
367
284
|
});
|
|
368
285
|
}
|
|
369
286
|
}
|
|
370
|
-
}
|
|
287
|
+
});
|
|
371
288
|
return result;
|
|
372
289
|
}
|
|
373
290
|
|
|
374
|
-
exports.buildTree = buildTree;
|
|
375
291
|
exports.flatTree = flatTree;
|
|
376
292
|
exports.forEachDeep = forEachDeep;
|
|
377
293
|
exports.formatTree = formatTree;
|
package/lib/cjs/type.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* sculp-js v1.
|
|
2
|
+
* sculp-js v1.8.1
|
|
3
3
|
* (c) 2023-present chandq
|
|
4
4
|
* Released under the MIT License.
|
|
5
5
|
*/
|
|
@@ -34,11 +34,17 @@ function arrayLike(any) {
|
|
|
34
34
|
return objectHas(any, 'length');
|
|
35
35
|
}
|
|
36
36
|
/**
|
|
37
|
-
*
|
|
37
|
+
* 判断任意值的数据类型,检查非对象时不如typeof、instanceof的性能高
|
|
38
|
+
*
|
|
39
|
+
* 当检查类对象时是不可靠的,对象可以通过定义 Symbol.toStringTag 属性来更改检查结果
|
|
40
|
+
*
|
|
41
|
+
* 详见:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/toString
|
|
38
42
|
* @param {unknown} any
|
|
39
|
-
* @returns
|
|
43
|
+
* @returns
|
|
40
44
|
*/
|
|
41
|
-
|
|
45
|
+
function typeIs(any) {
|
|
46
|
+
return Object.prototype.toString.call(any).slice(8, -1);
|
|
47
|
+
}
|
|
42
48
|
// 基本数据类型判断
|
|
43
49
|
const isString = (any) => typeof any === 'string';
|
|
44
50
|
const isBoolean = (any) => typeof any === 'boolean';
|
|
@@ -131,6 +137,7 @@ exports.isJsonString = isJsonString;
|
|
|
131
137
|
exports.isNaN = isNaN;
|
|
132
138
|
exports.isNull = isNull;
|
|
133
139
|
exports.isNullOrUnDef = isNullOrUnDef;
|
|
140
|
+
exports.isNullish = isNullOrUnDef;
|
|
134
141
|
exports.isNumber = isNumber;
|
|
135
142
|
exports.isObject = isObject;
|
|
136
143
|
exports.isPrimitive = isPrimitive;
|