sculp-js 1.19.3 → 1.19.5
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/dist/cjs/array.cjs +1 -1
- package/dist/cjs/async.cjs +1 -1
- package/dist/cjs/base64.cjs +1 -1
- package/dist/cjs/clipboard.cjs +1 -1
- package/dist/cjs/cloneDeep.cjs +1 -1
- package/dist/cjs/cookie.cjs +1 -1
- package/dist/cjs/date.cjs +17 -65
- package/dist/cjs/dom.cjs +1 -1
- package/dist/cjs/download.cjs +1 -1
- package/dist/cjs/file.cjs +2 -2
- package/dist/cjs/func.cjs +1 -1
- package/dist/cjs/index.cjs +1 -1
- package/dist/cjs/isEqual.cjs +1 -1
- package/dist/cjs/math.cjs +1 -1
- package/dist/cjs/number.cjs +1 -1
- package/dist/cjs/object.cjs +1 -1
- package/dist/cjs/path.cjs +1 -1
- package/dist/cjs/qs.cjs +1 -1
- package/dist/cjs/random.cjs +1 -1
- package/dist/cjs/string.cjs +10 -7
- package/dist/cjs/tooltip.cjs +1 -1
- package/dist/cjs/tree.cjs +159 -180
- package/dist/cjs/type.cjs +1 -1
- package/dist/cjs/unicodeToolkit.cjs +3 -3
- package/dist/cjs/unique.cjs +1 -1
- package/dist/cjs/url.cjs +1 -1
- package/dist/cjs/validator.cjs +1 -1
- package/dist/cjs/variable.cjs +1 -1
- package/dist/cjs/watermark.cjs +1 -1
- package/dist/esm/array.mjs +1 -1
- package/dist/esm/async.mjs +1 -1
- package/dist/esm/base64.mjs +1 -1
- package/dist/esm/clipboard.mjs +1 -1
- package/dist/esm/cloneDeep.mjs +1 -1
- package/dist/esm/cookie.mjs +1 -1
- package/dist/esm/date.mjs +17 -65
- package/dist/esm/dom.mjs +1 -1
- package/dist/esm/download.mjs +1 -1
- package/dist/esm/file.mjs +2 -2
- package/dist/esm/func.mjs +1 -1
- package/dist/esm/index.mjs +1 -1
- package/dist/esm/isEqual.mjs +1 -1
- package/dist/esm/math.mjs +1 -1
- package/dist/esm/number.mjs +1 -1
- package/dist/esm/object.mjs +1 -1
- package/dist/esm/path.mjs +1 -1
- package/dist/esm/qs.mjs +1 -1
- package/dist/esm/random.mjs +1 -1
- package/dist/esm/string.mjs +10 -7
- package/dist/esm/tooltip.mjs +1 -1
- package/dist/esm/tree.mjs +159 -180
- package/dist/esm/type.mjs +1 -1
- package/dist/esm/unicodeToolkit.mjs +3 -3
- package/dist/esm/unique.mjs +1 -1
- package/dist/esm/url.mjs +1 -1
- package/dist/esm/validator.mjs +1 -1
- package/dist/esm/variable.mjs +1 -1
- package/dist/esm/watermark.mjs +1 -1
- package/dist/sculp-js.d.ts +2275 -0
- package/dist/types/date.d.ts +21 -57
- package/dist/types/file.d.ts +1 -1
- package/dist/types/tree.d.ts +12 -12
- package/dist/types/tsdoc-metadata.json +11 -0
- package/dist/types/unicodeToolkit.d.ts +2 -2
- package/dist/umd/index.min.js +2 -2
- package/package.json +147 -117
package/dist/esm/tree.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* sculp-js v1.19.
|
|
2
|
+
* sculp-js v1.19.5
|
|
3
3
|
* (c) 2023-present chandq
|
|
4
4
|
* Released under the MIT License.
|
|
5
5
|
*/
|
|
@@ -14,10 +14,15 @@ const defaultSearchTreeOptions = {
|
|
|
14
14
|
removeEmptyChild: false,
|
|
15
15
|
ignoreCase: true
|
|
16
16
|
};
|
|
17
|
+
function getChildNodes(item, childField, isDomNode) {
|
|
18
|
+
const child = item[childField];
|
|
19
|
+
if (!child) return null;
|
|
20
|
+
return isDomNode && isNodeList(child) ? Array.from(child) : Array.isArray(child) ? child : null;
|
|
21
|
+
}
|
|
17
22
|
/**
|
|
18
|
-
*
|
|
23
|
+
* 深度遍历函数 (支持 continue 和 break 操作), 可用于遍历 Array 和 NodeList 类型的数据
|
|
19
24
|
* @param {ArrayLike<V>} tree 树形数据
|
|
20
|
-
* @param {Function} iterator
|
|
25
|
+
* @param {Function} iterator 迭代函数,返回值为 true 时 continue, 返回值为 false 时 break
|
|
21
26
|
* @param {options} options 支持定制子元素名称、反向遍历、广度优先遍历,默认{
|
|
22
27
|
childField: 'children',
|
|
23
28
|
reverse: false,
|
|
@@ -44,93 +49,56 @@ function forEachDeep(
|
|
|
44
49
|
} = isObject(options) ? options : {};
|
|
45
50
|
let isBreak = false;
|
|
46
51
|
const queue = [];
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
const item = arr[index];
|
|
53
|
-
// 广度优先
|
|
54
|
-
if (breadthFirst) {
|
|
55
|
-
queue.push({ item, index, array: arr, tree, parent, level });
|
|
56
|
-
} else {
|
|
57
|
-
const re = iterator(item, index, arr, tree, parent, level);
|
|
58
|
-
if (re === false) {
|
|
59
|
-
isBreak = true;
|
|
60
|
-
break;
|
|
61
|
-
} else if (re === true) {
|
|
62
|
-
continue;
|
|
63
|
-
}
|
|
64
|
-
if (item && (isDomNode ? isNodeList(item[childField]) : Array.isArray(item[childField]))) {
|
|
65
|
-
reverseWalk(item[childField], item, level + 1);
|
|
66
|
-
}
|
|
67
|
-
}
|
|
52
|
+
const processNode = (item, index, arr, parent, level) => {
|
|
53
|
+
const re = iterator(item, index, arr, tree, parent, level);
|
|
54
|
+
if (re === false) {
|
|
55
|
+
isBreak = true;
|
|
56
|
+
return;
|
|
68
57
|
}
|
|
69
|
-
if (
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
const
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
break;
|
|
78
|
-
} else if (re === true) {
|
|
79
|
-
continue;
|
|
80
|
-
}
|
|
81
|
-
if (item && (isDomNode ? isNodeList(item[childField]) : Array.isArray(item[childField]))) {
|
|
82
|
-
reverseWalk(item[childField], item, level + 1);
|
|
58
|
+
if (re === true) return;
|
|
59
|
+
const childNodes = getChildNodes(item, childField, isDomNode);
|
|
60
|
+
if (childNodes) {
|
|
61
|
+
if (breadthFirst) {
|
|
62
|
+
// BFS: 将子节点加入队列
|
|
63
|
+
const childLen = childNodes.length;
|
|
64
|
+
for (let i = 0; i < childLen; i++) {
|
|
65
|
+
queue.push({ item: childNodes[i], index: i, array: childNodes, tree, parent: item, level: level + 1 });
|
|
83
66
|
}
|
|
67
|
+
} else {
|
|
68
|
+
// DFS: 立即递归处理子节点
|
|
69
|
+
walk(childNodes, item, level + 1);
|
|
84
70
|
}
|
|
85
71
|
}
|
|
86
72
|
};
|
|
87
|
-
const walk = (arr, parent, level
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
if (breadthFirst) {
|
|
94
|
-
// 广度优先
|
|
95
|
-
queue.push({ item, index: index, array: arr, tree, parent, level });
|
|
96
|
-
} else {
|
|
97
|
-
// 深度优先
|
|
98
|
-
const re = iterator(item, index, arr, tree, parent, level);
|
|
99
|
-
if (re === false) {
|
|
100
|
-
isBreak = true;
|
|
101
|
-
break;
|
|
102
|
-
} else if (re === true) {
|
|
103
|
-
continue;
|
|
104
|
-
}
|
|
105
|
-
if (item && (isDomNode ? isNodeList(item[childField]) : Array.isArray(item[childField]))) {
|
|
106
|
-
walk(item[childField], item, level + 1);
|
|
107
|
-
}
|
|
73
|
+
const walk = (arr, parent, level) => {
|
|
74
|
+
const len = arr.length;
|
|
75
|
+
if (reverse) {
|
|
76
|
+
for (let i = len - 1; i >= 0; i--) {
|
|
77
|
+
if (isBreak) break;
|
|
78
|
+
processNode(arr[i], i, arr, parent, level);
|
|
108
79
|
}
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
if (!current) break;
|
|
114
|
-
const { item, index, array, tree, parent, level } = current;
|
|
115
|
-
const re = iterator(item, index, array, tree, parent, level);
|
|
116
|
-
if (re === false) {
|
|
117
|
-
isBreak = true;
|
|
118
|
-
break;
|
|
119
|
-
} else if (re === true) {
|
|
120
|
-
continue;
|
|
121
|
-
}
|
|
122
|
-
if (item && (isDomNode ? isNodeList(item[childField]) : Array.isArray(item[childField]))) {
|
|
123
|
-
walk(item[childField], item, level + 1);
|
|
124
|
-
}
|
|
80
|
+
} else {
|
|
81
|
+
for (let i = 0; i < len; i++) {
|
|
82
|
+
if (isBreak) break;
|
|
83
|
+
processNode(arr[i], i, arr, parent, level);
|
|
125
84
|
}
|
|
126
85
|
}
|
|
127
86
|
};
|
|
128
|
-
|
|
87
|
+
// 先处理根节点
|
|
88
|
+
walk(tree, null, 0);
|
|
89
|
+
// BFS: 处理队列中的节点
|
|
90
|
+
if (breadthFirst) {
|
|
91
|
+
let queueIndex = 0;
|
|
92
|
+
while (queueIndex < queue.length && !isBreak) {
|
|
93
|
+
const { item, index, array, parent, level } = queue[queueIndex++];
|
|
94
|
+
processNode(item, index, array, parent, level);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
129
97
|
// @ts-ignore
|
|
130
98
|
tree = null;
|
|
131
99
|
}
|
|
132
100
|
/**
|
|
133
|
-
*
|
|
101
|
+
* 树查找函数,可用于查找 Array 和 NodeList 类型的数据
|
|
134
102
|
* @param {ArrayLike<V>} tree 树形数据
|
|
135
103
|
* @param {Function} predicate 断言函数
|
|
136
104
|
* @param {options} options 支持定制子元素名称、反向遍历、广度优先遍历,默认{
|
|
@@ -165,7 +133,7 @@ function findDeep(
|
|
|
165
133
|
return result;
|
|
166
134
|
}
|
|
167
135
|
/**
|
|
168
|
-
*
|
|
136
|
+
* 树过滤函数,可用于过滤 Array 和 NodeList 类型的数据
|
|
169
137
|
* @param {ArrayLike<V>} tree 树形数据
|
|
170
138
|
* @param {Function} predicate 断言函数
|
|
171
139
|
* @param {options} options 支持定制子元素名称、反向遍历、广度优先遍历,默认{
|
|
@@ -199,11 +167,11 @@ function filterDeep(
|
|
|
199
167
|
return result;
|
|
200
168
|
}
|
|
201
169
|
/**
|
|
202
|
-
*
|
|
170
|
+
* 创建一个新数组,深度优先遍历的 Map 函数 (支持 continue 和 break 操作), 可用于 insert tree item 和 remove tree item
|
|
203
171
|
*
|
|
204
172
|
* 可遍历任何带有 length 属性和数字键的类数组对象
|
|
205
173
|
* @param {ArrayLike<V>} tree 树形数据
|
|
206
|
-
* @param {Function} iterator
|
|
174
|
+
* @param {Function} iterator 迭代函数,返回值为 true 时 continue, 返回值为 false 时 break
|
|
207
175
|
* @param {options} options 支持定制子元素名称、反向遍历,默认{
|
|
208
176
|
childField: 'children',
|
|
209
177
|
reverse: false,
|
|
@@ -221,54 +189,46 @@ function mapDeep(
|
|
|
221
189
|
const { childField = 'children', reverse = false } = isObject(options) ? options : {};
|
|
222
190
|
let isBreak = false;
|
|
223
191
|
const newTree = [];
|
|
224
|
-
const walk = (arr, parent,
|
|
192
|
+
const walk = (arr, parent, output, level) => {
|
|
225
193
|
if (reverse) {
|
|
226
194
|
for (let i = arr.length - 1; i >= 0; i--) {
|
|
227
|
-
if (isBreak)
|
|
228
|
-
break;
|
|
229
|
-
}
|
|
195
|
+
if (isBreak) break;
|
|
230
196
|
const item = arr[i];
|
|
231
197
|
const re = iterator(item, i, arr, tree, parent, level);
|
|
232
198
|
if (re === false) {
|
|
233
199
|
isBreak = true;
|
|
234
200
|
break;
|
|
235
|
-
} else if (re === true) {
|
|
236
|
-
continue;
|
|
237
201
|
}
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
202
|
+
if (re === true) continue;
|
|
203
|
+
const newItem = objectOmit(re, [childField]);
|
|
204
|
+
output.push(newItem);
|
|
205
|
+
const children = item[childField];
|
|
206
|
+
if (Array.isArray(children)) {
|
|
207
|
+
newItem[childField] = [];
|
|
208
|
+
walk(children, item, newItem[childField], level + 1);
|
|
245
209
|
}
|
|
246
210
|
}
|
|
247
211
|
} else {
|
|
248
212
|
for (let i = 0; i < arr.length; i++) {
|
|
249
|
-
if (isBreak)
|
|
250
|
-
break;
|
|
251
|
-
}
|
|
213
|
+
if (isBreak) break;
|
|
252
214
|
const item = arr[i];
|
|
253
215
|
const re = iterator(item, i, arr, tree, parent, level);
|
|
254
216
|
if (re === false) {
|
|
255
217
|
isBreak = true;
|
|
256
218
|
break;
|
|
257
|
-
} else if (re === true) {
|
|
258
|
-
continue;
|
|
259
219
|
}
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
220
|
+
if (re === true) continue;
|
|
221
|
+
const newItem = objectOmit(re, [childField]);
|
|
222
|
+
output.push(newItem);
|
|
223
|
+
const children = item[childField];
|
|
224
|
+
if (Array.isArray(children)) {
|
|
225
|
+
newItem[childField] = [];
|
|
226
|
+
walk(children, item, newItem[childField], level + 1);
|
|
267
227
|
}
|
|
268
228
|
}
|
|
269
229
|
}
|
|
270
230
|
};
|
|
271
|
-
walk(tree, null, newTree);
|
|
231
|
+
walk(tree, null, newTree, 0);
|
|
272
232
|
// @ts-ignore
|
|
273
233
|
tree = null;
|
|
274
234
|
return newTree;
|
|
@@ -277,40 +237,51 @@ function mapDeep(
|
|
|
277
237
|
* 在树中找到 id 为某个值的节点,并返回上游的所有父级节点
|
|
278
238
|
*
|
|
279
239
|
* @param {ArrayLike<T>} tree - 树形数据
|
|
280
|
-
* @param {number | string} nodeId - 目标元素ID
|
|
281
|
-
* @param {ITreeConf} options -
|
|
282
|
-
* @returns {[(number | string)[], V[]]} - 由parentId...childId, parentObject-childObject组成的二维数组
|
|
240
|
+
* @param {number | string} nodeId - 目标元素 ID
|
|
241
|
+
* @param {ITreeConf} options - 迭代配置项,默认:{ children = 'children', id = 'id' }
|
|
242
|
+
* @returns {[(number | string)[], V[]]} - 由 parentId...childId, parentObject-childObject 组成的二维数组
|
|
283
243
|
*/
|
|
284
244
|
function searchTreeById(tree, nodeId, options = { childField: 'children', keyField: 'id' }) {
|
|
285
245
|
const { childField = 'children', keyField = 'id' } = isObject(options) ? options : {};
|
|
286
|
-
const
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
nodes = [child.parent, ...nodes];
|
|
304
|
-
child = flatArray.find(_ => _[keyField] === child.parentId); // eslint-disable-line
|
|
246
|
+
const flatMap = {};
|
|
247
|
+
// 扁平化 - 使用迭代而非递归,避免栈溢出
|
|
248
|
+
const stack = [];
|
|
249
|
+
const len = tree.length;
|
|
250
|
+
for (let i = 0; i < len; i++) {
|
|
251
|
+
stack.push({ node: tree[i] });
|
|
252
|
+
}
|
|
253
|
+
while (stack.length > 0) {
|
|
254
|
+
const { node, parentId, parent } = stack.pop();
|
|
255
|
+
const id = node[keyField];
|
|
256
|
+
flatMap[id] = { node, parentId, parent };
|
|
257
|
+
const children = node[childField];
|
|
258
|
+
if (Array.isArray(children)) {
|
|
259
|
+
const childLen = children.length;
|
|
260
|
+
for (let i = 0; i < childLen; i++) {
|
|
261
|
+
stack.push({ node: children[i], parentId: id, parent: node });
|
|
262
|
+
}
|
|
305
263
|
}
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
264
|
+
}
|
|
265
|
+
// 回溯路径
|
|
266
|
+
const ids = [];
|
|
267
|
+
const nodes = [];
|
|
268
|
+
let current = flatMap[nodeId];
|
|
269
|
+
if (!current) return [[], []];
|
|
270
|
+
ids.push(nodeId);
|
|
271
|
+
nodes.push(current.node);
|
|
272
|
+
while (current && current.parentId !== undefined) {
|
|
273
|
+
ids.unshift(current.parentId);
|
|
274
|
+
const parent = flatMap[current.parentId];
|
|
275
|
+
if (!parent) break;
|
|
276
|
+
nodes.unshift(parent.node);
|
|
277
|
+
current = parent;
|
|
278
|
+
}
|
|
279
|
+
return [ids, nodes];
|
|
309
280
|
}
|
|
310
281
|
/**
|
|
311
282
|
* 扁平化数组转换成树
|
|
312
283
|
* @param {any[]} list
|
|
313
|
-
* @param {IFieldOptions} options 定制id字段名,子元素字段名,父元素字段名,默认
|
|
284
|
+
* @param {IFieldOptions} options 定制 id 字段名,子元素字段名,父元素字段名,默认
|
|
314
285
|
* { keyField: 'key', childField: 'children', pidField: 'pid' }
|
|
315
286
|
* @returns {any[]}
|
|
316
287
|
*/
|
|
@@ -318,11 +289,13 @@ function formatTree(list, options = defaultFieldOptions) {
|
|
|
318
289
|
const { keyField = 'key', childField = 'children', pidField = 'pid' } = isObject(options) ? options : {};
|
|
319
290
|
const treeArr = [];
|
|
320
291
|
const sourceMap = {};
|
|
321
|
-
|
|
292
|
+
const len = list.length;
|
|
293
|
+
// 先克隆所有对象,避免修改源数据
|
|
294
|
+
for (let i = 0; i < len; i++) {
|
|
322
295
|
const item = list[i];
|
|
323
296
|
sourceMap[item[keyField]] = item;
|
|
324
297
|
}
|
|
325
|
-
for (let i = 0
|
|
298
|
+
for (let i = 0; i < len; i++) {
|
|
326
299
|
const item = list[i];
|
|
327
300
|
const parent = sourceMap[item[pidField]];
|
|
328
301
|
if (parent) {
|
|
@@ -338,29 +311,32 @@ function formatTree(list, options = defaultFieldOptions) {
|
|
|
338
311
|
/**
|
|
339
312
|
* 树形结构转扁平化
|
|
340
313
|
* @param {any[]} treeList
|
|
341
|
-
* @param {IFieldOptions} options 定制id字段名,子元素字段名,父元素字段名,默认
|
|
314
|
+
* @param {IFieldOptions} options 定制 id 字段名,子元素字段名,父元素字段名,默认
|
|
342
315
|
* { keyField: 'key', childField: 'children', pidField: 'pid' }
|
|
343
316
|
* @returns {any[]}
|
|
344
317
|
*/
|
|
345
318
|
function flatTree(treeList, options = defaultFieldOptions) {
|
|
346
319
|
const { keyField = 'key', childField = 'children', pidField = 'pid' } = isObject(options) ? options : {};
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
const
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
320
|
+
const res = [];
|
|
321
|
+
const walk = nodes => {
|
|
322
|
+
const len = nodes.length;
|
|
323
|
+
for (let i = 0; i < len; i++) {
|
|
324
|
+
const node = nodes[i];
|
|
325
|
+
const item = { ...node };
|
|
326
|
+
delete item[childField];
|
|
327
|
+
res.push(item);
|
|
328
|
+
const children = node[childField];
|
|
329
|
+
if (Array.isArray(children)) {
|
|
330
|
+
// 创建新的子节点数组,不修改原数据
|
|
331
|
+
const newChildren = children.map(child => ({
|
|
332
|
+
...child,
|
|
333
|
+
[pidField]: node[keyField] !== undefined ? node[keyField] : child.pid
|
|
334
|
+
}));
|
|
335
|
+
walk(newChildren);
|
|
336
|
+
}
|
|
362
337
|
}
|
|
363
|
-
}
|
|
338
|
+
};
|
|
339
|
+
walk(treeList);
|
|
364
340
|
return res;
|
|
365
341
|
}
|
|
366
342
|
/**
|
|
@@ -387,41 +363,44 @@ function fuzzySearchTree(nodes, filterCondition, options = defaultSearchTreeOpti
|
|
|
387
363
|
return nodes;
|
|
388
364
|
}
|
|
389
365
|
const result = [];
|
|
366
|
+
const { childField, nameField, removeEmptyChild, ignoreCase } = options;
|
|
367
|
+
const hasFilter = objectHas(filterCondition, 'filter');
|
|
368
|
+
const filterFn = filterCondition.filter;
|
|
369
|
+
const keyword = filterCondition.keyword;
|
|
390
370
|
for (let i = 0, len = nodes.length; i < len; i++) {
|
|
391
371
|
const node = nodes[i];
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
372
|
+
const children = node[childField];
|
|
373
|
+
// 递归处理子节点
|
|
374
|
+
const matchedChildren = children && children.length > 0 ? fuzzySearchTree(children, filterCondition, options) : [];
|
|
375
|
+
// 判断当前节点是否匹配
|
|
376
|
+
let isMatch = false;
|
|
377
|
+
if (hasFilter && filterFn) {
|
|
378
|
+
isMatch = filterFn(node);
|
|
379
|
+
} else if (keyword !== undefined && keyword !== null) {
|
|
380
|
+
const nodeValue = String(node[nameField] || '');
|
|
381
|
+
const searchValue = String(keyword);
|
|
382
|
+
isMatch = ignoreCase
|
|
383
|
+
? nodeValue.toLowerCase().includes(searchValue.toLowerCase())
|
|
384
|
+
: nodeValue.includes(searchValue);
|
|
385
|
+
}
|
|
386
|
+
// 如果当前节点匹配或有匹配的子节点,则加入结果
|
|
387
|
+
if (isMatch || matchedChildren.length > 0) {
|
|
388
|
+
if (childField in node) {
|
|
389
|
+
// 节点有 children 字段
|
|
408
390
|
if (matchedChildren.length > 0) {
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
result.push(other);
|
|
391
|
+
// 有匹配的子节点
|
|
392
|
+
result.push({ ...node, [childField]: matchedChildren });
|
|
393
|
+
} else if (removeEmptyChild) {
|
|
394
|
+
// 无匹配子节点且需要移除空 children
|
|
395
|
+
const { [childField]: _, ...rest } = node;
|
|
396
|
+
result.push(rest);
|
|
416
397
|
} else {
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
[options.childField]: []
|
|
420
|
-
});
|
|
398
|
+
// 无匹配子节点但保留 children 字段(设为空数组)
|
|
399
|
+
result.push({ ...node, [childField]: [] });
|
|
421
400
|
}
|
|
422
401
|
} else {
|
|
423
|
-
|
|
424
|
-
result.push(
|
|
402
|
+
// 节点没有 children 字段,直接返回
|
|
403
|
+
result.push(node);
|
|
425
404
|
}
|
|
426
405
|
}
|
|
427
406
|
}
|
package/dist/esm/type.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* sculp-js v1.19.
|
|
2
|
+
* sculp-js v1.19.5
|
|
3
3
|
* (c) 2023-present chandq
|
|
4
4
|
* Released under the MIT License.
|
|
5
5
|
*/
|
|
@@ -19,12 +19,12 @@ class UnicodeToolkit {
|
|
|
19
19
|
* UnicodeToolkit.encode('Hi 你好 😀')
|
|
20
20
|
* // => 'Hi \u4F60\u597D \u{1F600}'
|
|
21
21
|
* @example
|
|
22
|
-
* // 全部Unicode 编码
|
|
22
|
+
* // 全部 Unicode 编码
|
|
23
23
|
* UnicodeToolkit.encode('Hi 你好 😀','unicode', true)
|
|
24
24
|
* // => '\u0048\u0069\u0020\u4F60\u597D\u0020\u{1F600}'
|
|
25
25
|
* @example
|
|
26
26
|
* // HTML 实体编码
|
|
27
|
-
* UnicodeToolkit.encode('<
|
|
27
|
+
* UnicodeToolkit.encode('<scr' + 'ipt>', 'html',true)
|
|
28
28
|
* // => '<script>&'
|
|
29
29
|
*/
|
|
30
30
|
static encode(str, mode = 'unicode', encodeAll = false) {
|
package/dist/esm/unique.mjs
CHANGED
package/dist/esm/url.mjs
CHANGED
package/dist/esm/validator.mjs
CHANGED
package/dist/esm/variable.mjs
CHANGED
package/dist/esm/watermark.mjs
CHANGED