tree-processor 0.7.0 → 0.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 CHANGED
@@ -1,30 +1,104 @@
1
1
  # tree-processor
2
2
 
3
- 一个轻量级的树结构数据处理工具库,使用 TypeScript 编写,支持 tree-shaking,每个格式打包体积约 **3-4 KB**(ESM: 3.25 KB,CJS: 3.42 KB,UMD: 3.56 KB)。
4
-
5
- 目前已支持 mapTree、forEachTree、filterTree、findTree、pushTree、unshiftTree、popTree、shiftTree、someTree、everyTree、includesTree、atTree、indexOfTree、atIndexOfTree、dedupTree、removeTree、getParentTree、getChildrenTree、getSiblingsTree、getNodeDepthMap、getNodeDepth、isEmptyTreeData、isEmptySingleTreeData、isSingleTreeData 和 isTreeData。每个方法的最后一个参数可以自定义 children 和 id 的属性名。
3
+ <div align="center">
4
+
5
+ ![npm version](https://img.shields.io/npm/v/tree-processor?style=flat-square)
6
+ ![npm downloads](https://img.shields.io/npm/dm/tree-processor?style=flat-square)
7
+ ![bundle size](https://img.shields.io/badge/bundle-6.6KB-blue?style=flat-square)
8
+ ![TypeScript](https://img.shields.io/badge/TypeScript-5.7-blue?style=flat-square)
9
+ ![License](https://img.shields.io/badge/license-MIT-green?style=flat-square)
10
+ ![test coverage](https://img.shields.io/badge/coverage-272%20tests-brightgreen?style=flat-square)
11
+
12
+ 一个轻量级的树结构数据处理工具库,使用 TypeScript 编写,支持 tree-shaking,每个格式打包体积约 **6-7 KB**(ESM: 6.39 KB,CJS: 6.64 KB,UMD: 6.68 KB)。
13
+
14
+
15
+ </div>
16
+
17
+ ## 📋 目录
18
+
19
+ - [特性](#-特性)
20
+ - [使用场景](#-使用场景)
21
+ - [安装](#-安装)
22
+ - [快速开始](#-快速开始)
23
+ - [API 文档](#-api-文档)
24
+ - [遍历方法](#遍历方法)
25
+ - [查找方法](#查找方法)
26
+ - [修改方法](#修改方法)
27
+ - [判断方法](#判断方法)
28
+ - [工具方法](#工具方法)
29
+ - [自定义字段名](#自定义字段名)
30
+ - [测试](#测试)
31
+ - [开发](#开发)
32
+ - [技术栈](#技术栈)
33
+ - [贡献](#-贡献)
34
+ - [更新日志](#-更新日志)
35
+ - [许可证](#-许可证)
36
+ - [相关链接](#-相关链接)
6
37
 
7
38
  ## ✨ 特性
8
39
 
9
- - 🚀 **轻量级** - 每个格式约 3-4 KB(ESM: 3.25 KB,CJS: 3.42 KB,UMD: 3.56 KB
10
- - 📦 **支持 Tree-shaking** - 按需导入,只打包使用的代码
11
- - 🔧 **TypeScript 支持** - 完整的类型定义和类型提示
12
- - 🎯 **类似数组 API** - 提供 map、filter、find 等熟悉的数组方法
13
- - ⚙️ **自定义字段名** - 支持自定义 children 和 id 字段名
14
- - **零依赖** - 无外部依赖,开箱即用
15
- - 🧪 **完善的测试覆盖** - 包含 200 个测试用例,覆盖基础功能、边界情况、异常处理、复杂场景、npm 包导入等
40
+ - **轻量级** - 每个格式打包体积仅 6-7 KB(ESM: 6.39 KB,CJS: 6.64 KB,UMD: 6.68 KB),对项目体积影响极小
41
+ - **支持 Tree-shaking** - 支持按需导入,只打包实际使用的代码,进一步减小打包体积
42
+ - **完整的 TypeScript 支持** - 提供完整的类型定义和智能提示,提升开发体验
43
+ - **灵活的自定义字段名** - 支持自定义 children id 字段名,适配各种数据结构
44
+ - **零依赖** - 无任何外部依赖,开箱即用,无需担心依赖冲突
45
+ - **完善的测试覆盖** - 包含 272 个测试用例,覆盖基础功能、边界情况、异常处理、复杂场景等
46
+ - **丰富的 API** - 提供 30+ 个方法,包含类似数组的 API(map、filter、find、some、every、includes、at、indexOf 等),以及树结构特有的操作(获取父子节点、深度计算、数据验证等),涵盖遍历、查找、修改、判断等完整场景
47
+
48
+ **已支持的方法:** mapTree、forEachTree、filterTree、findTree、pushTree、unshiftTree、popTree、shiftTree、someTree、everyTree、includesTree、atTree、indexOfTree、atIndexOfTree、dedupTree、removeTree、getParentTree、getChildrenTree、getSiblingsTree、getNodeDepthMap、getNodeDepth、isLeafNode、isRootNode、isEmptyTreeData、isEmptySingleTreeData、isTreeData、isSingleTreeData、isValidTreeNode、isTreeNodeWithCircularCheck、isSafeTreeDepth。每个方法的最后一个参数可以自定义 children 和 id 的属性名。
49
+
50
+ ### 💡 使用场景
51
+
52
+ - **导航系统** - 多级菜单、路由配置的展开、折叠、搜索、过滤
53
+ - **文件系统** - 文件目录的遍历、查找、移动、删除
54
+ - **权限系统** - 组织架构、角色权限的树形结构管理和验证
55
+ - **框架开发** - 组件树、路由树等树形结构的构建和管理
56
+ - **数据管理** - 分类管理、评论系统、树形选择器等数据操作
16
57
 
17
58
  ## 📦 安装
18
59
 
19
60
  ```bash
61
+ npm install tree-processor
62
+ # 或
20
63
  yarn add tree-processor
21
64
  # 或
22
- npm i tree-processor
65
+ pnpm add tree-processor
23
66
  ```
24
67
 
25
- ## 使用说明
68
+ ## 🚀 快速开始
26
69
 
27
- ### 引入
70
+ ```javascript
71
+ import { mapTree, findTree, filterTree } from 'tree-processor'
72
+
73
+ const treeData = [
74
+ {
75
+ id: 1,
76
+ name: 'node1',
77
+ children: [
78
+ { id: 2, name: 'node2' },
79
+ { id: 3, name: 'node3' },
80
+ ],
81
+ },
82
+ ]
83
+
84
+ // 获取所有节点名称
85
+ const names = mapTree(treeData, (node) => node.name)
86
+ console.log(names) // ['node1', 'node2', 'node3']
87
+
88
+ // 查找节点
89
+ const node = findTree(treeData, (n) => n.id === 2)
90
+ console.log(node) // { id: 2, name: 'node2' }
91
+
92
+ // 过滤节点
93
+ const filtered = filterTree(treeData, (n) => n.id > 1)
94
+ console.log(filtered) // [{ id: 2, name: 'node2' }, { id: 3, name: 'node3' }]
95
+ ```
96
+
97
+ ## 📖 API 文档
98
+
99
+ ### 引入方式
100
+
101
+ #### 默认导入(推荐用于需要多个方法的场景)
28
102
 
29
103
  #### 默认导入(推荐用于需要多个方法的场景)
30
104
 
@@ -59,7 +133,7 @@ const { mapTree, filterTree } = require('tree-processor')
59
133
  - 只有在需要显式声明变量类型时才需要引入类型(如 `const treeData: TreeData = [...]`)
60
134
  - 使用 `import type` 导入类型不会增加运行时体积(类型在编译时会被移除)
61
135
 
62
- ### 示例树结构数据
136
+ ### 示例数据
63
137
 
64
138
  以下示例数据将用于后续所有方法的演示:
65
139
 
@@ -87,7 +161,11 @@ const treeData = [
87
161
  ];
88
162
  ```
89
163
 
90
- ### mapTree(遍历树结构数据的方法)
164
+ ---
165
+
166
+ ## 遍历方法
167
+
168
+ ### mapTree
91
169
 
92
170
  遍历树结构数据,对每个节点执行回调函数,返回映射后的数组。
93
171
 
@@ -108,7 +186,7 @@ const modifiedNodes = t.mapTree(treeData, (node) => ({
108
186
  console.log(modifiedNodes) // 返回包含 label 字段的新数组
109
187
  ```
110
188
 
111
- ### forEachTree(遍历树结构数据的方法,不返回值)
189
+ ### forEachTree
112
190
 
113
191
  遍历树结构数据,对每个节点执行回调函数。与 mapTree 的区别是不返回值,性能更好,适合只需要遍历而不需要返回结果的场景。
114
192
 
@@ -132,7 +210,7 @@ t.forEachTree(treeData, () => {
132
210
  console.log(nodeCount) // 节点总数
133
211
  ```
134
212
 
135
- ### filterTree(树结构数据的filter方法)
213
+ ### filterTree
136
214
 
137
215
  过滤树结构数据,返回满足条件的节点。
138
216
 
@@ -154,7 +232,11 @@ const leafNodes = t.filterTree(treeData, (node) => {
154
232
  console.log(leafNodes) // 返回所有叶子节点
155
233
  ```
156
234
 
157
- ### findTree(树结构数据的find方法)
235
+ ---
236
+
237
+ ## 查找方法
238
+
239
+ ### findTree
158
240
 
159
241
  查找树结构数据中满足条件的第一个节点。如果未找到,返回 null。
160
242
 
@@ -172,85 +254,7 @@ const nodeNotFound = t.findTree(treeData, (node) => node.id === 999)
172
254
  console.log(nodeNotFound) // null
173
255
  ```
174
256
 
175
- ### pushTree(在指定节点下添加子节点到末尾)
176
-
177
- 在指定节点下添加子节点到末尾。返回 true 表示添加成功,false 表示未找到目标节点。
178
-
179
- ```javascript
180
- // 在ID为1的节点下添加新子节点
181
- const addSuccess = t.pushTree(treeData, 1, { id: 7, name: 'node7' })
182
- console.log(addSuccess) // true
183
- console.log(treeData) // 新节点已添加到 children 数组末尾
184
-
185
- // 尝试在不存在的节点下添加
186
- const addFailed = t.pushTree(treeData, 999, { id: 8, name: 'node8' })
187
- console.log(addFailed) // false,未找到目标节点
188
- ```
189
-
190
- ### unshiftTree(在指定节点下添加子节点到开头)
191
-
192
- 在指定节点下添加子节点到开头。返回 true 表示添加成功,false 表示未找到目标节点。
193
-
194
- ```javascript
195
- // 在ID为1的节点下添加新子节点到开头
196
- const unshiftSuccess = t.unshiftTree(treeData, 1, { id: 7, name: 'node7' })
197
- console.log(unshiftSuccess) // true
198
- console.log(treeData) // 新节点已添加到 children 数组开头
199
- ```
200
-
201
- ### popTree(删除指定节点下的最后一个子节点)
202
-
203
- 删除指定节点下的最后一个子节点。返回被删除的节点,如果节点不存在或没有子节点则返回 false。
204
-
205
- ```javascript
206
- // 删除ID为1的节点下的最后一个子节点
207
- const removedNode = t.popTree(treeData, 1)
208
- console.log(removedNode) // 返回被删除的节点对象,或 false
209
-
210
- // 尝试删除不存在的节点下的子节点
211
- const popFailed = t.popTree(treeData, 999)
212
- console.log(popFailed) // false
213
- ```
214
-
215
- ### shiftTree(删除指定节点下的第一个子节点)
216
-
217
- 删除指定节点下的第一个子节点。返回被删除的节点,如果节点不存在或没有子节点则返回 false。
218
-
219
- ```javascript
220
- // 删除ID为1的节点下的第一个子节点
221
- const shiftedNode = t.shiftTree(treeData, 1)
222
- console.log(shiftedNode) // 返回被删除的节点对象,或 false
223
- ```
224
-
225
- ### someTree(树结构数据的some方法)
226
-
227
- 检查树结构数据中是否存在满足条件的节点。只要有一个节点满足条件就返回 true。
228
-
229
- ```javascript
230
- // 检查是否存在名称为 'node2' 的节点
231
- const hasNode2 = t.someTree(treeData, node => node.name === 'node2')
232
- console.log(hasNode2) // true
233
-
234
- // 检查是否存在ID大于10的节点
235
- const hasLargeId = t.someTree(treeData, node => node.id > 10)
236
- console.log(hasLargeId) // false
237
- ```
238
-
239
- ### everyTree(树结构数据的every方法)
240
-
241
- 检查树结构数据中是否所有节点都满足条件。只有所有节点都满足条件才返回 true。
242
-
243
- ```javascript
244
- // 检查所有节点的ID是否都大于0
245
- const allIdsPositive = t.everyTree(treeData, node => node.id > 0)
246
- console.log(allIdsPositive) // true
247
-
248
- // 检查所有节点是否都有 name 属性
249
- const allHaveName = t.everyTree(treeData, node => node.name)
250
- console.log(allHaveName) // 根据实际数据返回 true 或 false
251
- ```
252
-
253
- ### includesTree(检查树中是否包含指定节点)
257
+ ### includesTree
254
258
 
255
259
  检查树结构数据中是否包含指定ID的节点。
256
260
 
@@ -261,7 +265,7 @@ const hasNode = t.includesTree(treeData, nodeId)
261
265
  console.log(hasNode) // true 表示包含该节点,false 表示不包含
262
266
  ```
263
267
 
264
- ### atTree(根据父节点ID和子节点索引获取节点)
268
+ ### atTree
265
269
 
266
270
  根据父节点ID和子节点索引获取节点。支持负数索引,和数组的 at 方法一样。未找到返回 null。
267
271
 
@@ -279,7 +283,7 @@ const nodeNotFound = t.atTree(treeData, 1, 10)
279
283
  console.log(nodeNotFound) // null
280
284
  ```
281
285
 
282
- ### indexOfTree(返回从根节点到目标节点的索引路径)
286
+ ### indexOfTree
283
287
 
284
288
  返回一个数组,值为从根节点开始到 targetId 所在节点的索引路径。未找到返回 null。返回值可以传入 atIndexOfTree 的第二个参数进行取值。
285
289
 
@@ -298,7 +302,7 @@ const nodeByPath = t.atIndexOfTree(treeData, indexPath)
298
302
  console.log(nodeByPath) // 获取到ID为4的节点
299
303
  ```
300
304
 
301
- ### atIndexOfTree(根据索引路径获取节点)
305
+ ### atIndexOfTree
302
306
 
303
307
  根据索引路径获取节点。路径无效或超出范围返回 null。
304
308
 
@@ -317,7 +321,73 @@ const invalidPath = t.atIndexOfTree(treeData, [999])
317
321
  console.log(invalidPath) // null
318
322
  ```
319
323
 
320
- ### dedupTree(树结构对象数组去重方法)
324
+ ---
325
+
326
+ ## 修改方法
327
+
328
+ ### pushTree
329
+
330
+ 在指定节点下添加子节点到末尾。返回 true 表示添加成功,false 表示未找到目标节点。
331
+
332
+ ```javascript
333
+ // 在ID为1的节点下添加新子节点
334
+ const addSuccess = t.pushTree(treeData, 1, { id: 7, name: 'node7' })
335
+ console.log(addSuccess) // true
336
+ console.log(treeData) // 新节点已添加到 children 数组末尾
337
+
338
+ // 尝试在不存在的节点下添加
339
+ const addFailed = t.pushTree(treeData, 999, { id: 8, name: 'node8' })
340
+ console.log(addFailed) // false,未找到目标节点
341
+ ```
342
+
343
+ ### unshiftTree
344
+
345
+ 在指定节点下添加子节点到开头。返回 true 表示添加成功,false 表示未找到目标节点。
346
+
347
+ ```javascript
348
+ // 在ID为1的节点下添加新子节点到开头
349
+ const unshiftSuccess = t.unshiftTree(treeData, 1, { id: 7, name: 'node7' })
350
+ console.log(unshiftSuccess) // true
351
+ console.log(treeData) // 新节点已添加到 children 数组开头
352
+ ```
353
+
354
+ ### popTree
355
+
356
+ 删除指定节点下的最后一个子节点。返回被删除的节点,如果节点不存在或没有子节点则返回 false。
357
+
358
+ ```javascript
359
+ // 删除ID为1的节点下的最后一个子节点
360
+ const removedNode = t.popTree(treeData, 1)
361
+ console.log(removedNode) // 返回被删除的节点对象,或 false
362
+
363
+ // 尝试删除不存在的节点下的子节点
364
+ const popFailed = t.popTree(treeData, 999)
365
+ console.log(popFailed) // false
366
+ ```
367
+
368
+ ### shiftTree
369
+
370
+ 删除指定节点下的第一个子节点。返回被删除的节点,如果节点不存在或没有子节点则返回 false。
371
+
372
+ ```javascript
373
+ // 删除ID为1的节点下的第一个子节点
374
+ const shiftedNode = t.shiftTree(treeData, 1)
375
+ console.log(shiftedNode) // 返回被删除的节点对象,或 false
376
+ ```
377
+
378
+ ### removeTree
379
+
380
+ 删除树结构数据中指定ID的节点,包括根节点和子节点。
381
+
382
+ ```javascript
383
+ const nodeIdToRemove = 2
384
+ const removeSuccess = t.removeTree(treeData, nodeIdToRemove)
385
+
386
+ console.log(removeSuccess) // true 表示删除成功,false 表示未找到节点
387
+ console.log(treeData) // 删除后的树结构
388
+ ```
389
+
390
+ ### dedupTree
321
391
 
322
392
  树结构对象数组去重方法,根据指定的键去除重复节点。保留第一次出现的节点。
323
393
 
@@ -331,19 +401,39 @@ const uniqueByNameTree = t.dedupTree(treeData, 'name')
331
401
  console.log(uniqueByNameTree) // 返回根据 name 去重后的数据
332
402
  ```
333
403
 
334
- ### removeTree(删除指定节点)
404
+ ---
335
405
 
336
- 删除树结构数据中指定ID的节点,包括根节点和子节点。
406
+ ## 判断方法
407
+
408
+ ### someTree
409
+
410
+ 检查树结构数据中是否存在满足条件的节点。只要有一个节点满足条件就返回 true。
337
411
 
338
412
  ```javascript
339
- const nodeIdToRemove = 2
340
- const removeSuccess = t.removeTree(treeData, nodeIdToRemove)
413
+ // 检查是否存在名称为 'node2' 的节点
414
+ const hasNode2 = t.someTree(treeData, node => node.name === 'node2')
415
+ console.log(hasNode2) // true
341
416
 
342
- console.log(removeSuccess) // true 表示删除成功,false 表示未找到节点
343
- console.log(treeData) // 删除后的树结构
417
+ // 检查是否存在ID大于10的节点
418
+ const hasLargeId = t.someTree(treeData, node => node.id > 10)
419
+ console.log(hasLargeId) // false
344
420
  ```
345
421
 
346
- ### getParentTree(获取节点的父节点)
422
+ ### everyTree
423
+
424
+ 检查树结构数据中是否所有节点都满足条件。只有所有节点都满足条件才返回 true。
425
+
426
+ ```javascript
427
+ // 检查所有节点的ID是否都大于0
428
+ const allIdsPositive = t.everyTree(treeData, node => node.id > 0)
429
+ console.log(allIdsPositive) // true
430
+
431
+ // 检查所有节点是否都有 name 属性
432
+ const allHaveName = t.everyTree(treeData, node => node.name)
433
+ console.log(allHaveName) // 根据实际数据返回 true 或 false
434
+ ```
435
+
436
+ ### getParentTree
347
437
 
348
438
  获取指定节点的父节点。如果节点是根节点或未找到,返回 null。
349
439
 
@@ -361,7 +451,7 @@ const parentNotFound = t.getParentTree(treeData, 999)
361
451
  console.log(parentNotFound) // null
362
452
  ```
363
453
 
364
- ### getChildrenTree(获取节点的所有直接子节点)
454
+ ### getChildrenTree
365
455
 
366
456
  获取指定节点的所有直接子节点。如果未找到节点或没有子节点,返回空数组。
367
457
 
@@ -394,7 +484,7 @@ const customChildren = t.getChildrenTree(customTree, 1, fieldNames)
394
484
  console.log(customChildren) // 返回子节点数组
395
485
  ```
396
486
 
397
- ### getSiblingsTree(获取节点的所有兄弟节点)
487
+ ### getSiblingsTree
398
488
 
399
489
  获取指定节点的所有兄弟节点(包括自己)。如果未找到节点,返回空数组。根节点的兄弟节点是其他根节点。
400
490
 
@@ -432,7 +522,11 @@ const customSiblings = t.getSiblingsTree(customTree, 2, fieldNames)
432
522
  console.log(customSiblings) // 返回兄弟节点数组(包括自己)
433
523
  ```
434
524
 
435
- ### getNodeDepthMap(返回节点ID到深度的映射)
525
+ ---
526
+
527
+ ## 工具方法
528
+
529
+ ### getNodeDepthMap
436
530
 
437
531
  返回一个字典,键代表节点的 id,值代表该节点在数据的第几层。深度从1开始,根节点深度为1。
438
532
 
@@ -450,7 +544,7 @@ const emptyDepthMap = t.getNodeDepthMap([])
450
544
  console.log(emptyDepthMap) // {}
451
545
  ```
452
546
 
453
- ### getNodeDepth(获取单个节点的深度)
547
+ ### getNodeDepth
454
548
 
455
549
  获取指定节点的深度。深度从1开始,根节点深度为1。
456
550
 
@@ -490,7 +584,107 @@ console.log(depth) // 2
490
584
  - `getNodeDepthMap` - 批量获取所有节点的深度(一次性计算所有节点)
491
585
  - `getNodeDepth` - 只获取单个节点的深度(只计算目标节点,效率更高)
492
586
 
493
- ### isEmptyTreeData(检查树结构数据是否为空)
587
+ ### isLeafNode
588
+
589
+ 检查节点是否是叶子节点(没有子节点)。轻量级方法,只检查节点本身,不遍历树。
590
+
591
+ ```javascript
592
+ // 没有 children 字段的节点是叶子节点
593
+ const leafNode1 = { id: 1, name: 'node1' };
594
+ console.log(t.isLeafNode(leafNode1)) // true
595
+
596
+ // children 为空数组的节点是叶子节点
597
+ const leafNode2 = { id: 2, name: 'node2', children: [] };
598
+ console.log(t.isLeafNode(leafNode2)) // true
599
+
600
+ // 有子节点的节点不是叶子节点
601
+ const parentNode = {
602
+ id: 3,
603
+ name: 'node3',
604
+ children: [{ id: 4, name: 'node4' }],
605
+ };
606
+ console.log(t.isLeafNode(parentNode)) // false
607
+
608
+ // 在 filterTree 中使用(过滤出所有叶子节点)
609
+ const leafNodes = t.filterTree(treeData, (node) => t.isLeafNode(node))
610
+ console.log(leafNodes) // 返回所有叶子节点
611
+
612
+ // 在 forEachTree 中使用
613
+ t.forEachTree(treeData, (node) => {
614
+ if (t.isLeafNode(node)) {
615
+ console.log('叶子节点:', node.name)
616
+ }
617
+ })
618
+
619
+ // 支持自定义字段名
620
+ const customNode = {
621
+ nodeId: 1,
622
+ name: 'node1',
623
+ subNodes: [],
624
+ };
625
+ const fieldNames = { children: 'subNodes', id: 'nodeId' };
626
+ console.log(t.isLeafNode(customNode, fieldNames)) // true
627
+ ```
628
+
629
+ **与现有方法的区别:**
630
+ - `isLeafNode` - 只检查单个节点,轻量级(O(1)),适合在遍历时使用
631
+ - `getChildrenTree` - 获取子节点数组,需要传入 tree 和 nodeId,需要查找节点(O(n))
632
+
633
+ ### isRootNode
634
+
635
+ 检查节点是否是根节点(没有父节点)。根节点是树结构数据数组中的顶层节点。
636
+
637
+ ```javascript
638
+ // 检查根节点
639
+ const treeData = [
640
+ {
641
+ id: 1,
642
+ name: 'root1',
643
+ children: [{ id: 2, name: 'child1' }],
644
+ },
645
+ ];
646
+ console.log(t.isRootNode(treeData, 1)) // true
647
+ console.log(t.isRootNode(treeData, 2)) // false
648
+
649
+ // 多个根节点的情况
650
+ const multiRoot = [
651
+ { id: 1, name: 'root1' },
652
+ { id: 2, name: 'root2' },
653
+ { id: 3, name: 'root3' },
654
+ ];
655
+ console.log(t.isRootNode(multiRoot, 1)) // true
656
+ console.log(t.isRootNode(multiRoot, 2)) // true
657
+ console.log(t.isRootNode(multiRoot, 3)) // true
658
+
659
+ // 在遍历时使用
660
+ t.forEachTree(treeData, (node) => {
661
+ if (t.isRootNode(treeData, node.id)) {
662
+ console.log('根节点:', node.name)
663
+ }
664
+ })
665
+
666
+ // 支持自定义字段名
667
+ const customTree = [
668
+ {
669
+ nodeId: 1,
670
+ name: 'root1',
671
+ subNodes: [{ nodeId: 2, name: 'child1' }],
672
+ },
673
+ ];
674
+ const fieldNames = { children: 'subNodes', id: 'nodeId' };
675
+ console.log(t.isRootNode(customTree, 1, fieldNames)) // true
676
+ console.log(t.isRootNode(customTree, 2, fieldNames)) // false
677
+
678
+ // 节点不存在时返回 false
679
+ console.log(t.isRootNode(treeData, 999)) // false
680
+ ```
681
+
682
+ **与现有方法的区别:**
683
+ - `isRootNode` - 语义化方法,直接返回布尔值
684
+ - `getParentTree` - 返回父节点对象,需要判断是否为 null
685
+ - `getNodeDepth` - 返回深度,需要判断是否等于 1
686
+
687
+ ### isEmptyTreeData
494
688
 
495
689
  检查树结构数据(数组)是否为空。空数组、null、undefined 都视为空。此函数支持 fieldNames 参数以保持 API 一致性,但该参数不生效(因为只检查数组是否为空,不访问 children 或 id 字段)。
496
690
 
@@ -513,7 +707,7 @@ const isEmptyWithFieldNames = t.isEmptyTreeData(treeData, fieldNames)
513
707
  console.log(isEmptyWithFieldNames) // false(结果与不传 fieldNames 相同)
514
708
  ```
515
709
 
516
- ### isEmptySingleTreeData(检查单个树结构数据是否为空)
710
+ ### isEmptySingleTreeData
517
711
 
518
712
  检查单个树结构数据是否为空。如果数据不是有效的单个树结构数据、没有 children 字段,或者 children 是空数组,则视为空。如果有子节点(children 数组不为空),即使子节点本身是空的,树也不为空。
519
713
 
@@ -566,7 +760,56 @@ const isEmptyCustom = t.isEmptySingleTreeData(customTree, fieldNames)
566
760
  console.log(isEmptyCustom) // true
567
761
  ```
568
762
 
569
- ### isSingleTreeData(判断数据是否是单个树结构数据)
763
+ ### isTreeData
764
+
765
+ 判断数据是否是树结构数据(数组)。树结构数据必须是一个数组,数组中的每个元素都必须是有效的单个树结构数据。
766
+
767
+ ```javascript
768
+ // 有效的树结构数据(森林)
769
+ const forest = [
770
+ {
771
+ id: 1,
772
+ name: 'node1',
773
+ children: [{ id: 2, name: 'node2' }],
774
+ },
775
+ {
776
+ id: 3,
777
+ name: 'node3',
778
+ children: [{ id: 4, name: 'node4' }],
779
+ },
780
+ ];
781
+ console.log(t.isTreeData(forest)) // true
782
+
783
+ // 空数组也是有效的树结构数据(空森林)
784
+ console.log(t.isTreeData([])) // true
785
+
786
+ // 单个对象不是树结构数据(应该用 isSingleTreeData)
787
+ console.log(t.isTreeData({ id: 1 })) // false
788
+
789
+ // 数组包含非树结构元素,返回 false
790
+ const invalidForest = [
791
+ { id: 1, children: [{ id: 2 }] },
792
+ 'not a tree', // 无效元素
793
+ ];
794
+ console.log(t.isTreeData(invalidForest)) // false
795
+
796
+ // null 或 undefined 不是有效的树结构数据
797
+ console.log(t.isTreeData(null)) // false
798
+ console.log(t.isTreeData(undefined)) // false
799
+
800
+ // 支持自定义字段名
801
+ const customForest = [
802
+ {
803
+ nodeId: 1,
804
+ name: 'node1',
805
+ subNodes: [{ nodeId: 2, name: 'node2' }],
806
+ },
807
+ ];
808
+ const fieldNames = { children: 'subNodes', id: 'nodeId' };
809
+ console.log(t.isTreeData(customForest, fieldNames)) // true
810
+ ```
811
+
812
+ ### isSingleTreeData
570
813
 
571
814
  判断数据是否是单个树结构数据(单个对象)。树结构数据必须是一个对象(不能是数组、null、undefined 或基本类型),如果存在 children 字段,必须是数组类型,并且会递归检查所有子节点。
572
815
 
@@ -608,55 +851,136 @@ const fieldNames = { children: 'subNodes', id: 'nodeId' };
608
851
  console.log(t.isSingleTreeData(customTree, fieldNames)) // true
609
852
  ```
610
853
 
611
- ### isTreeData(判断数据是否是树结构数据)
854
+ ### isValidTreeNode
612
855
 
613
- 判断数据是否是树结构数据(数组)。树结构数据必须是一个数组,数组中的每个元素都必须是有效的单个树结构数据。
856
+ 检查单个节点是否是有效的树节点结构(轻量级,不递归检查子节点)。只检查节点本身的结构,不检查子节点。
614
857
 
615
858
  ```javascript
616
- // 有效的树结构数据(森林)
617
- const forest = [
859
+ // 有效的树节点(有 children 数组)
860
+ const node1 = {
861
+ id: 1,
862
+ name: 'node1',
863
+ children: [{ id: 2 }],
864
+ };
865
+ console.log(t.isValidTreeNode(node1)) // true
866
+
867
+ // 有效的树节点(没有 children 字段)
868
+ const node2 = { id: 1, name: 'node1' };
869
+ console.log(t.isValidTreeNode(node2)) // true
870
+
871
+ // 无效的树节点(children 不是数组)
872
+ const invalidNode = {
873
+ id: 1,
874
+ children: 'not an array',
875
+ };
876
+ console.log(t.isValidTreeNode(invalidNode)) // false
877
+
878
+ // 支持自定义字段名
879
+ const customNode = {
880
+ nodeId: 1,
881
+ subNodes: [{ nodeId: 2 }],
882
+ };
883
+ const fieldNames = { children: 'subNodes', id: 'nodeId' };
884
+ console.log(t.isValidTreeNode(customNode, fieldNames)) // true
885
+ ```
886
+
887
+ **与 isSingleTreeData 的区别:**
888
+ - `isValidTreeNode` - 只检查单个节点的基本结构,不递归检查子节点(轻量级)
889
+ - `isSingleTreeData` - 递归检查整个树结构,确保所有子节点都是有效的树结构
890
+
891
+ ### isTreeNodeWithCircularCheck
892
+
893
+ 检查节点是否是有效的树节点结构,并检测循环引用。使用 WeakSet 跟踪已访问的节点,如果发现循环引用则返回 false。
894
+
895
+ ```javascript
896
+ // 有效的树节点(无循环引用)
897
+ const validNode = {
898
+ id: 1,
899
+ children: [
900
+ { id: 2, children: [{ id: 3 }] },
901
+ ],
902
+ };
903
+ console.log(t.isTreeNodeWithCircularCheck(validNode)) // true
904
+
905
+ // 检测循环引用
906
+ const node1 = { id: 1, children: [] };
907
+ const node2 = { id: 2, children: [] };
908
+ node1.children.push(node2);
909
+ node2.children.push(node1); // 循环引用
910
+ console.log(t.isTreeNodeWithCircularCheck(node1)) // false
911
+
912
+ // 检测自引用
913
+ const selfRefNode = { id: 1, children: [] };
914
+ selfRefNode.children.push(selfRefNode); // 自引用
915
+ console.log(t.isTreeNodeWithCircularCheck(selfRefNode)) // false
916
+
917
+ // 支持自定义字段名
918
+ const customNode = {
919
+ nodeId: 1,
920
+ subNodes: [{ nodeId: 2 }],
921
+ };
922
+ const fieldNames = { children: 'subNodes', id: 'nodeId' };
923
+ console.log(t.isTreeNodeWithCircularCheck(customNode, fieldNames)) // true
924
+ ```
925
+
926
+ **使用场景:**
927
+ - 在接收用户输入或外部数据时,检查是否有循环引用
928
+ - 数据验证,防止无限递归
929
+ - 调试时检查数据结构是否正确
930
+
931
+ ### isSafeTreeDepth
932
+
933
+ 检查树结构数据的深度是否安全(防止递归爆栈)。如果树的深度超过 `maxDepth`,返回 false。
934
+
935
+ ```javascript
936
+ // 深度安全的树
937
+ const safeTree = [
618
938
  {
619
939
  id: 1,
620
- name: 'node1',
621
- children: [{ id: 2, name: 'node2' }],
940
+ children: [
941
+ { id: 2, children: [{ id: 3 }] },
942
+ ],
622
943
  },
944
+ ];
945
+ console.log(t.isSafeTreeDepth(safeTree, 10)) // true(深度为3,小于10)
946
+
947
+ // 深度超过最大深度
948
+ const deepTree = [
623
949
  {
624
- id: 3,
625
- name: 'node3',
626
- children: [{ id: 4, name: 'node4' }],
950
+ id: 1,
951
+ children: [
952
+ { id: 2, children: [{ id: 3 }] },
953
+ ],
627
954
  },
628
955
  ];
629
- console.log(t.isTreeData(forest)) // true
956
+ console.log(t.isSafeTreeDepth(deepTree, 2)) // false(深度为3,超过2)
630
957
 
631
- // 空数组也是有效的树结构数据(空森林)
632
- console.log(t.isTreeData([])) // true
958
+ // 空树总是安全的
959
+ console.log(t.isSafeTreeDepth([], 10)) // true
633
960
 
634
- // 单个对象不是树结构数据(应该用 isSingleTreeData)
635
- console.log(t.isTreeData({ id: 1 })) // false
636
-
637
- // 数组包含非树结构元素,返回 false
638
- const invalidForest = [
639
- { id: 1, children: [{ id: 2 }] },
640
- 'not a tree', // 无效元素
641
- ];
642
- console.log(t.isTreeData(invalidForest)) // false
643
-
644
- // null 或 undefined 不是有效的树结构数据
645
- console.log(t.isTreeData(null)) // false
646
- console.log(t.isTreeData(undefined)) // false
961
+ // 单层树
962
+ const singleLayer = [{ id: 1 }, { id: 2 }];
963
+ console.log(t.isSafeTreeDepth(singleLayer, 1)) // true
647
964
 
648
965
  // 支持自定义字段名
649
- const customForest = [
966
+ const customTree = [
650
967
  {
651
968
  nodeId: 1,
652
- name: 'node1',
653
- subNodes: [{ nodeId: 2, name: 'node2' }],
969
+ subNodes: [
970
+ { nodeId: 2, subNodes: [{ nodeId: 3 }] },
971
+ ],
654
972
  },
655
973
  ];
656
974
  const fieldNames = { children: 'subNodes', id: 'nodeId' };
657
- console.log(t.isTreeData(customForest, fieldNames)) // true
975
+ console.log(t.isSafeTreeDepth(customTree, 3, fieldNames)) // true
976
+ console.log(t.isSafeTreeDepth(customTree, 2, fieldNames)) // false
658
977
  ```
659
978
 
979
+ **使用场景:**
980
+ - 在处理大型树之前,先检查深度是否安全
981
+ - 防止递归调用栈溢出
982
+ - 性能优化,避免处理过深的树结构
983
+
660
984
  ## 自定义字段名
661
985
 
662
986
  所有方法都支持自定义 children 和 id 的属性名,通过最后一个参数传入配置对象:
@@ -670,7 +994,7 @@ const fieldNames = { children: 'subNodes', id: 'nodeId' };
670
994
  const foundNode2 = t.findTree(customTreeData, (node) => node.nodeId === 2, fieldNames);
671
995
  ```
672
996
 
673
- **注意:** 所有 25 个函数都支持 `fieldNames` 参数,保持 API 一致性。即使某些函数(如 `isEmptyTreeData`)中该参数不生效,也可以传入以保持代码风格一致。
997
+ **注意:** 所有 30 个函数都支持 `fieldNames` 参数,保持 API 一致性。即使某些函数(如 `isEmptyTreeData`)中该参数不生效,也可以传入以保持代码风格一致。
674
998
 
675
999
  ## 测试
676
1000
 
@@ -707,6 +1031,36 @@ npm run build
707
1031
  - **Terser** - JavaScript 压缩工具
708
1032
  - **TypeScript** - 类型支持
709
1033
 
710
- ## License
1034
+ ## 🤝 贡献
1035
+
1036
+ 欢迎贡献!如果你有任何想法或发现问题,请:
1037
+
1038
+ 1. Fork 本仓库
1039
+ 2. 创建你的特性分支 (`git checkout -b feature/AmazingFeature`)
1040
+ 3. 提交你的更改 (`git commit -m 'Add some AmazingFeature'`)
1041
+ 4. 推送到分支 (`git push origin feature/AmazingFeature`)
1042
+ 5. 开启一个 Pull Request
1043
+
1044
+ ## 📝 更新日志
1045
+
1046
+ 查看 [CHANGELOG.md](./CHANGELOG.md) 了解详细的版本更新记录。
1047
+
1048
+ ## 📄 许可证
1049
+
1050
+ 本项目采用 [MIT](./LICENSE) 许可证。
1051
+
1052
+ ## 🔗 相关链接
1053
+
1054
+ - [GitHub 仓库](https://github.com/knott11/tree-processor)
1055
+ - [npm 包](https://www.npmjs.com/package/tree-processor)
1056
+ - [问题反馈](https://github.com/knott11/tree-processor/issues)
1057
+
1058
+ ---
1059
+
1060
+ <div align="center">
1061
+
1062
+ 如果这个项目对你有帮助,请给它一个 ⭐️
1063
+
1064
+ Made with ❤️ by [knott11](https://github.com/knott11)
711
1065
 
712
- MIT
1066
+ </div>
package/dist/index.d.ts CHANGED
@@ -29,6 +29,11 @@ export declare function getParentTree(tree: TreeData, targetId: any, fieldNames?
29
29
  export declare function includesTree(tree: TreeData, targetId: any, fieldNames?: FieldNames): boolean;
30
30
  export declare function isSingleTreeData(data: any, fieldNames?: FieldNames): boolean;
31
31
  export declare function isTreeData(data: any, fieldNames?: FieldNames): boolean;
32
+ export declare function isValidTreeNode(value: unknown, fieldNames?: FieldNames): value is TreeNode;
33
+ export declare function isTreeNodeWithCircularCheck(value: unknown, fieldNames?: FieldNames, visited?: WeakSet<object>): boolean;
34
+ export declare function isSafeTreeDepth(tree: TreeData, maxDepth: number, fieldNames?: FieldNames): boolean;
35
+ export declare function isLeafNode(node: TreeNode, fieldNames?: FieldNames): boolean;
36
+ export declare function isRootNode(tree: TreeData, nodeId: any, fieldNames?: FieldNames): boolean;
32
37
  declare const treeProcessor: {
33
38
  mapTree: typeof mapTree;
34
39
  filterTree: typeof filterTree;
@@ -55,6 +60,11 @@ declare const treeProcessor: {
55
60
  includesTree: typeof includesTree;
56
61
  isSingleTreeData: typeof isSingleTreeData;
57
62
  isTreeData: typeof isTreeData;
63
+ isValidTreeNode: typeof isValidTreeNode;
64
+ isTreeNodeWithCircularCheck: typeof isTreeNodeWithCircularCheck;
65
+ isSafeTreeDepth: typeof isSafeTreeDepth;
66
+ isLeafNode: typeof isLeafNode;
67
+ isRootNode: typeof isRootNode;
58
68
  };
59
69
  export default treeProcessor;
60
70
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/stats.html CHANGED
@@ -4929,7 +4929,7 @@ var drawChart = (function (exports) {
4929
4929
  </script>
4930
4930
  <script>
4931
4931
  /*<!--*/
4932
- const data = {"version":2,"tree":{"name":"root","children":[{"name":"tree-processor.esm.js","children":[{"name":"src/index.ts","uid":"f5d7d230-1"}]}],"isRoot":true},"nodeParts":{"f5d7d230-1":{"renderedLength":14963,"gzipLength":1892,"brotliLength":1670,"metaUid":"f5d7d230-0"}},"nodeMetas":{"f5d7d230-0":{"id":"\\src\\index.ts","moduleParts":{"tree-processor.esm.js":"f5d7d230-1"},"imported":[],"importedBy":[],"isEntry":true}},"env":{"rollup":"4.56.0"},"options":{"gzip":true,"brotli":true,"sourcemap":false}};
4932
+ const data = {"version":2,"tree":{"name":"root","children":[{"name":"tree-processor.cjs.js","children":[{"name":"src/index.ts","uid":"7eca4295-1"}]}],"isRoot":true},"nodeParts":{"7eca4295-1":{"renderedLength":17081,"gzipLength":2155,"brotliLength":1901,"metaUid":"7eca4295-0"}},"nodeMetas":{"7eca4295-0":{"id":"\\src\\index.ts","moduleParts":{"tree-processor.cjs.js":"7eca4295-1"},"imported":[],"importedBy":[],"isEntry":true}},"env":{"rollup":"4.56.0"},"options":{"gzip":true,"brotli":true,"sourcemap":false}};
4933
4933
 
4934
4934
  const run = () => {
4935
4935
  const width = window.innerWidth;
@@ -1,88 +1,100 @@
1
1
  "use strict"
2
2
  Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})
3
3
  const r={children:"children",id:"id"}
4
- function n(n,e,t=r){const i=[]
5
- return function r(n){for(const o of n){i.push(e(o))
6
- const n=o[t.children]
7
- Array.isArray(n)&&n.length>0&&r(n)}}(n),i}function e(n,e,t=r){const i=[]
8
- return function r(n){n.forEach((n,o)=>{e(n,o)&&i.push(n)
9
- const u=n[t.children]
10
- Array.isArray(u)&&u.length>0&&r(u,o)})}(n),i}function t(n,e,i=r){for(const r of n){if(e(r))return r
11
- const n=r[i.children]
12
- if(Array.isArray(n)&&n.length>0){const r=t(n,e,i)
13
- if(r)return r}}return null}function i(n,e,t,i=r){return function r(n){for(const o of n){if(o[i.id]===e)return o[i.children]||(o[i.children]=[]),o[i.children].push(t),!0
14
- const n=o[i.children]
15
- if(Array.isArray(n)&&n.length>0&&r(n))return!0}return!1}(n)}function o(n,e,t,i=r){return function r(n){for(const o of n){if(o[i.id]===e)return o[i.children]||(o[i.children]=[]),o[i.children].unshift(t),!0
16
- const n=o[i.children]
17
- if(Array.isArray(n)&&n.length>0&&r(n))return!0}return!1}(n)}function u(n,e,t=r){return function r(n){for(const i of n){if(i[t.id]===e){const r=i[t.children]
18
- return!!(Array.isArray(r)&&r.length>0)&&(r.pop(),!0)}const n=i[t.children]
19
- if(Array.isArray(n)&&n.length>0&&r(n))return!0}return!1}(n)}function s(n,e,t=r){return function r(n){for(const i of n){if(i[t.id]===e){const r=i[t.children]
20
- return!!(Array.isArray(r)&&r.length>0)&&(r.shift(),!0)}const n=i[t.children]
21
- if(Array.isArray(n)&&n.length>0&&r(n))return!0}return!1}(n)}function c(n,e,t=r){for(const r of n){if(e(r))return!0
22
- const n=r[t.children]
23
- if(Array.isArray(n)&&n.length>0&&c(n,e,t))return!0}return!1}function f(n,e,t=r){for(const r of n){if(!e(r))return!1
24
- const n=r[t.children]
25
- if(Array.isArray(n)&&n.length>0&&!f(n,e,t))return!1}return!0}function l(n,e,t,i=r){const o=function r(n){for(const t of n){if(t[i.id]===e)return t
26
- const n=t[i.children]
27
- if(Array.isArray(n)&&n.length>0){const e=r(n)
28
- if(e)return e}}return null}(n)
4
+ function e(e,n,t=r){const i=[]
5
+ return function r(e){for(const o of e){i.push(n(o))
6
+ const e=o[t.children]
7
+ Array.isArray(e)&&e.length>0&&r(e)}}(e),i}function n(e,n,t=r){const i=[]
8
+ return function r(e){e.forEach((e,o)=>{n(e,o)&&i.push(e)
9
+ const u=e[t.children]
10
+ Array.isArray(u)&&u.length>0&&r(u,o)})}(e),i}function t(e,n,i=r){for(const r of e){if(n(r))return r
11
+ const e=r[i.children]
12
+ if(Array.isArray(e)&&e.length>0){const r=t(e,n,i)
13
+ if(r)return r}}return null}function i(e,n,t,i=r){return function r(e){for(const o of e){if(o[i.id]===n)return o[i.children]||(o[i.children]=[]),o[i.children].push(t),!0
14
+ const e=o[i.children]
15
+ if(Array.isArray(e)&&e.length>0&&r(e))return!0}return!1}(e)}function o(e,n,t,i=r){return function r(e){for(const o of e){if(o[i.id]===n)return o[i.children]||(o[i.children]=[]),o[i.children].unshift(t),!0
16
+ const e=o[i.children]
17
+ if(Array.isArray(e)&&e.length>0&&r(e))return!0}return!1}(e)}function u(e,n,t=r){return function r(e){for(const i of e){if(i[t.id]===n){const r=i[t.children]
18
+ return!!(Array.isArray(r)&&r.length>0)&&(r.pop(),!0)}const e=i[t.children]
19
+ if(Array.isArray(e)&&e.length>0&&r(e))return!0}return!1}(e)}function s(e,n,t=r){return function r(e){for(const i of e){if(i[t.id]===n){const r=i[t.children]
20
+ return!!(Array.isArray(r)&&r.length>0)&&(r.shift(),!0)}const e=i[t.children]
21
+ if(Array.isArray(e)&&e.length>0&&r(e))return!0}return!1}(e)}function f(e,n,t=r){for(const r of e){if(n(r))return!0
22
+ const e=r[t.children]
23
+ if(Array.isArray(e)&&e.length>0&&f(e,n,t))return!0}return!1}function c(e,n,t=r){for(const r of e){if(!n(r))return!1
24
+ const e=r[t.children]
25
+ if(Array.isArray(e)&&e.length>0&&!c(e,n,t))return!1}return!0}function l(e,n,t,i=r){const o=function r(e){for(const t of e){if(t[i.id]===n)return t
26
+ const e=t[i.children]
27
+ if(Array.isArray(e)&&e.length>0){const n=r(e)
28
+ if(n)return n}}return null}(e)
29
29
  if(!o)return null
30
30
  const u=o[i.children]
31
31
  if(!Array.isArray(u)||0===u.length)return null
32
32
  const s=t>=0?t:u.length+t
33
- return s>=0&&s<u.length?u[s]:null}function a(n,e,t=r){return function r(n,i=[]){for(let o=0;o<n.length;o++){const u=n[o],s=[...i,o]
34
- if(u[t.id]===e)return s
35
- const c=u[t.children]
36
- if(Array.isArray(c)&&c.length>0){const n=r(c,s)
37
- if(n)return n}}return null}(n)}function h(n,e,t=r){if(!Array.isArray(e)||0===e.length)return null
38
- let i=n
39
- for(let r=0;r<e.length;r++){const n=e[r]
40
- if(!Array.isArray(i)||n<0||n>=i.length)return null
41
- const o=i[n]
42
- if(r===e.length-1)return o
33
+ return s>=0&&s<u.length?u[s]:null}function a(e,n,t=r){return function r(e,i=[]){for(let o=0;o<e.length;o++){const u=e[o],s=[...i,o]
34
+ if(u[t.id]===n)return s
35
+ const f=u[t.children]
36
+ if(Array.isArray(f)&&f.length>0){const e=r(f,s)
37
+ if(e)return e}}return null}(e)}function h(e,n,t=r){if(!Array.isArray(n)||0===n.length)return null
38
+ let i=e
39
+ for(let r=0;r<n.length;r++){const e=n[r]
40
+ if(!Array.isArray(i)||e<0||e>=i.length)return null
41
+ const o=i[e]
42
+ if(r===n.length-1)return o
43
43
  const u=o[t.children]
44
44
  if(!Array.isArray(u))return null
45
- i=u}return null}function d(n,e=r){const t={}
46
- return function r(n,i=1){for(const o of n){t[o[e.id]]=i
47
- const n=o[e.children]
48
- Array.isArray(n)&&n.length>0&&r(n,i+1)}}(n),t}function y(n,e,t=r){return function r(n,i=1){for(const o of n){if(o[t.id]===e)return i
49
- const n=o[t.children]
50
- if(Array.isArray(n)&&n.length>0){const e=r(n,i+1)
51
- if(null!==e)return e}}return null}(n)}function A(n,e,t=r){const i=new Set
52
- return function r(n){const o=[]
53
- for(const u of n){const n=u[e]
54
- if(null!=n){if(i.has(n))continue
55
- i.add(n)}const s={...u},c=u[t.children]
56
- Array.isArray(c)&&c.length>0&&(s[t.children]=r(c)),o.push(s)}return o}(n)}function p(n,e,t=r){return function r(n){for(let i=0;i<n.length;i++){const o=n[i]
57
- if(o[t.id]===e)return n.splice(i,1),!0
45
+ i=u}return null}function d(e,n=r){const t={}
46
+ return function r(e,i=1){for(const o of e){t[o[n.id]]=i
47
+ const e=o[n.children]
48
+ Array.isArray(e)&&e.length>0&&r(e,i+1)}}(e),t}function y(e,n,t=r){return function r(e,i=1){for(const o of e){if(o[t.id]===n)return i
49
+ const e=o[t.children]
50
+ if(Array.isArray(e)&&e.length>0){const n=r(e,i+1)
51
+ if(null!==n)return n}}return null}(e)}function A(e,n,t=r){const i=new Set
52
+ return function r(e){const o=[]
53
+ for(const u of e){const e=u[n]
54
+ if(null!=e){if(i.has(e))continue
55
+ i.add(e)}const s={...u},f=u[t.children]
56
+ Array.isArray(f)&&f.length>0&&(s[t.children]=r(f)),o.push(s)}return o}(e)}function p(e,n,t=r){return function r(e){for(let i=0;i<e.length;i++){const o=e[i]
57
+ if(o[t.id]===n)return e.splice(i,1),!0
58
58
  const u=o[t.children]
59
- if(Array.isArray(u)&&u.length>0&&r(u))return!0}return!1}(n)}function g(n,e,t=r){!function r(n){for(const i of n){e(i)
60
- const n=i[t.children]
61
- Array.isArray(n)&&n.length>0&&r(n)}}(n)}function T(r){return!Array.isArray(r)||0===r.length}function x(n,e=r){if(!E(n,e))return!0
62
- const t=n[e.children]
63
- return void 0===t||(!Array.isArray(t)||0===t.length)}function D(n,e,t=r){const i=function r(n){for(const i of n){if(i[t.id]===e)return i
64
- const n=i[t.children]
65
- if(Array.isArray(n)&&n.length>0){const e=r(n)
66
- if(null!==e)return e}}return null}(n)
59
+ if(Array.isArray(u)&&u.length>0&&r(u))return!0}return!1}(e)}function g(e,n,t=r){!function r(e){for(const i of e){n(i)
60
+ const e=i[t.children]
61
+ Array.isArray(e)&&e.length>0&&r(e)}}(e)}function T(r){return!Array.isArray(r)||0===r.length}function x(e,n=r){if(!v(e,n))return!0
62
+ const t=e[n.children]
63
+ return void 0===t||(!Array.isArray(t)||0===t.length)}function D(e,n,t=r){const i=function r(e){for(const i of e){if(i[t.id]===n)return i
64
+ const e=i[t.children]
65
+ if(Array.isArray(e)&&e.length>0){const n=r(e)
66
+ if(null!==n)return n}}return null}(e)
67
67
  if(!i)return[]
68
68
  const o=i[t.children]
69
- return Array.isArray(o)?o:[]}function m(n,e,t=r){const i=function r(n,i=null){for(const o of n){if(o[t.id]===e)return{node:o,parent:i}
70
- const n=o[t.children]
71
- if(Array.isArray(n)&&n.length>0){const e=r(n,o)
72
- if(null!==e)return e}}return null}(n)
69
+ return Array.isArray(o)?o:[]}function N(e,n,t=r){const i=function r(e,i=null){for(const o of e){if(o[t.id]===n)return{node:o,parent:i}
70
+ const e=o[t.children]
71
+ if(Array.isArray(e)&&e.length>0){const n=r(e,o)
72
+ if(null!==n)return n}}return null}(e)
73
73
  if(!i)return[]
74
- if(null===i.parent)return n
74
+ if(null===i.parent)return e
75
75
  const o=i.parent[t.children]
76
- return Array.isArray(o)?o:[]}function S(n,e,t=r){return function r(n,i=null){for(const o of n){if(o[t.id]===e)return i
77
- const n=o[t.children]
78
- if(Array.isArray(n)&&n.length>0){const e=r(n,o)
79
- if(null!==e)return e}}return null}(n)}function v(n,e,t=r){for(const r of n){if(r[t.id]===e)return!0
80
- const n=r[t.children]
81
- if(Array.isArray(n)&&n.length>0&&v(n,e,t))return!0}return!1}function E(n,e=r){if(!n||"object"!=typeof n||Array.isArray(n))return!1
82
- const t=n[e.children]
76
+ return Array.isArray(o)?o:[]}function S(e,n,t=r){return function r(e,i=null){for(const o of e){if(o[t.id]===n)return i
77
+ const e=o[t.children]
78
+ if(Array.isArray(e)&&e.length>0){const n=r(e,o)
79
+ if(null!==n)return n}}return null}(e)}function m(e,n,t=r){for(const r of e){if(r[t.id]===n)return!0
80
+ const e=r[t.children]
81
+ if(Array.isArray(e)&&e.length>0&&m(e,n,t))return!0}return!1}function v(e,n=r){if(!e||"object"!=typeof e||Array.isArray(e))return!1
82
+ const t=e[n.children]
83
83
  if(void 0!==t){if(null===t)return!1
84
84
  if(!Array.isArray(t))return!1
85
- for(const r of t)if(!E(r,e))return!1}return!0}function b(n,e=r){if(!Array.isArray(n))return!1
86
- for(const r of n)if(!E(r,e))return!1
87
- return!0}const O={mapTree:n,filterTree:e,findTree:t,pushTree:i,unshiftTree:o,popTree:u,shiftTree:s,someTree:c,everyTree:f,atTree:l,indexOfTree:a,atIndexOfTree:h,getNodeDepthMap:d,getNodeDepth:y,dedupTree:A,removeTree:p,forEachTree:g,isEmptyTreeData:T,isEmptySingleTreeData:x,getParentTree:S,getChildrenTree:D,getSiblingsTree:m,includesTree:v,isSingleTreeData:E,isTreeData:b}
88
- exports.atIndexOfTree=h,exports.atTree=l,exports.dedupTree=A,exports.default=O,exports.everyTree=f,exports.filterTree=e,exports.findTree=t,exports.forEachTree=g,exports.getChildrenTree=D,exports.getNodeDepth=y,exports.getNodeDepthMap=d,exports.getParentTree=S,exports.getSiblingsTree=m,exports.includesTree=v,exports.indexOfTree=a,exports.isEmptySingleTreeData=x,exports.isEmptyTreeData=T,exports.isSingleTreeData=E,exports.isTreeData=b,exports.mapTree=n,exports.popTree=u,exports.pushTree=i,exports.removeTree=p,exports.shiftTree=s,exports.someTree=c,exports.unshiftTree=o
85
+ for(const r of t)if(!v(r,n))return!1}return!0}function b(e,n=r){if(!Array.isArray(e))return!1
86
+ for(const r of e)if(!v(r,n))return!1
87
+ return!0}function E(e,n=r){if(!e||"object"!=typeof e||Array.isArray(e))return!1
88
+ const t=e[n.children]
89
+ return void 0===t||Array.isArray(t)}function C(e,n=r,t=new WeakSet){if(!e||"object"!=typeof e||Array.isArray(e))return!1
90
+ if(t.has(e))return!1
91
+ t.add(e)
92
+ const i=e[n.children]
93
+ if(void 0!==i){if(null===i)return!1
94
+ if(!Array.isArray(i))return!1
95
+ for(const r of i)if(!C(r,n,t))return!1}return!0}function O(e,n,t=r){if(n<=0)return!1
96
+ return function r(e,i){if(i>n)return!1
97
+ for(const n of e){const e=n[t.children]
98
+ if(Array.isArray(e)&&e.length>0&&!r(e,i+1))return!1}return!0}(e,1)}function j(e,n=r){const t=e[n.children]
99
+ return void 0===t||!Array.isArray(t)||0===t.length}function M(e,n,t=r){return!!m(e,n,t)&&null===S(e,n,t)}const k={mapTree:e,filterTree:n,findTree:t,pushTree:i,unshiftTree:o,popTree:u,shiftTree:s,someTree:f,everyTree:c,atTree:l,indexOfTree:a,atIndexOfTree:h,getNodeDepthMap:d,getNodeDepth:y,dedupTree:A,removeTree:p,forEachTree:g,isEmptyTreeData:T,isEmptySingleTreeData:x,getParentTree:S,getChildrenTree:D,getSiblingsTree:N,includesTree:m,isSingleTreeData:v,isTreeData:b,isValidTreeNode:E,isTreeNodeWithCircularCheck:C,isSafeTreeDepth:O,isLeafNode:j,isRootNode:M}
100
+ exports.atIndexOfTree=h,exports.atTree=l,exports.dedupTree=A,exports.default=k,exports.everyTree=c,exports.filterTree=n,exports.findTree=t,exports.forEachTree=g,exports.getChildrenTree=D,exports.getNodeDepth=y,exports.getNodeDepthMap=d,exports.getParentTree=S,exports.getSiblingsTree=N,exports.includesTree=m,exports.indexOfTree=a,exports.isEmptySingleTreeData=x,exports.isEmptyTreeData=T,exports.isLeafNode=j,exports.isRootNode=M,exports.isSafeTreeDepth=O,exports.isSingleTreeData=v,exports.isTreeData=b,exports.isTreeNodeWithCircularCheck=C,exports.isValidTreeNode=E,exports.mapTree=e,exports.popTree=u,exports.pushTree=i,exports.removeTree=p,exports.shiftTree=s,exports.someTree=f,exports.unshiftTree=o
@@ -56,31 +56,43 @@ if(o[e.id]===t)return n.splice(i,1),!0
56
56
  const u=o[e.children]
57
57
  if(Array.isArray(u)&&u.length>0&&r(u))return!0}return!1}(n)}function T(n,t,e=r){!function r(n){for(const i of n){t(i)
58
58
  const n=i[e.children]
59
- Array.isArray(n)&&n.length>0&&r(n)}}(n)}function p(r){return!Array.isArray(r)||0===r.length}function D(n,t=r){if(!x(n,t))return!0
59
+ Array.isArray(n)&&n.length>0&&r(n)}}(n)}function p(r){return!Array.isArray(r)||0===r.length}function v(n,t=r){if(!b(n,t))return!0
60
60
  const e=n[t.children]
61
- return void 0===e||(!Array.isArray(e)||0===e.length)}function m(n,t,e=r){const i=function r(n){for(const i of n){if(i[e.id]===t)return i
61
+ return void 0===e||(!Array.isArray(e)||0===e.length)}function D(n,t,e=r){const i=function r(n){for(const i of n){if(i[e.id]===t)return i
62
62
  const n=i[e.children]
63
63
  if(Array.isArray(n)&&n.length>0){const t=r(n)
64
64
  if(null!==t)return t}}return null}(n)
65
65
  if(!i)return[]
66
66
  const o=i[e.children]
67
- return Array.isArray(o)?o:[]}function v(n,t,e=r){const i=function r(n,i=null){for(const o of n){if(o[e.id]===t)return{node:o,parent:i}
67
+ return Array.isArray(o)?o:[]}function N(n,t,e=r){const i=function r(n,i=null){for(const o of n){if(o[e.id]===t)return{node:o,parent:i}
68
68
  const n=o[e.children]
69
69
  if(Array.isArray(n)&&n.length>0){const t=r(n,o)
70
70
  if(null!==t)return t}}return null}(n)
71
71
  if(!i)return[]
72
72
  if(null===i.parent)return n
73
73
  const o=i.parent[e.children]
74
- return Array.isArray(o)?o:[]}function E(n,t,e=r){return function r(n,i=null){for(const o of n){if(o[e.id]===t)return i
74
+ return Array.isArray(o)?o:[]}function S(n,t,e=r){return function r(n,i=null){for(const o of n){if(o[e.id]===t)return i
75
75
  const n=o[e.children]
76
76
  if(Array.isArray(n)&&n.length>0){const t=r(n,o)
77
- if(null!==t)return t}}return null}(n)}function S(n,t,e=r){for(const r of n){if(r[e.id]===t)return!0
77
+ if(null!==t)return t}}return null}(n)}function m(n,t,e=r){for(const r of n){if(r[e.id]===t)return!0
78
78
  const n=r[e.children]
79
- if(Array.isArray(n)&&n.length>0&&S(n,t,e))return!0}return!1}function x(n,t=r){if(!n||"object"!=typeof n||Array.isArray(n))return!1
79
+ if(Array.isArray(n)&&n.length>0&&m(n,t,e))return!0}return!1}function b(n,t=r){if(!n||"object"!=typeof n||Array.isArray(n))return!1
80
80
  const e=n[t.children]
81
81
  if(void 0!==e){if(null===e)return!1
82
82
  if(!Array.isArray(e))return!1
83
- for(const r of e)if(!x(r,t))return!1}return!0}function b(n,t=r){if(!Array.isArray(n))return!1
84
- for(const r of n)if(!x(r,t))return!1
85
- return!0}const N={mapTree:n,filterTree:t,findTree:e,pushTree:i,unshiftTree:o,popTree:u,shiftTree:c,someTree:f,everyTree:l,atTree:s,indexOfTree:a,atIndexOfTree:h,getNodeDepthMap:y,getNodeDepth:d,dedupTree:A,removeTree:g,forEachTree:T,isEmptyTreeData:p,isEmptySingleTreeData:D,getParentTree:E,getChildrenTree:m,getSiblingsTree:v,includesTree:S,isSingleTreeData:x,isTreeData:b}
86
- export{h as atIndexOfTree,s as atTree,A as dedupTree,N as default,l as everyTree,t as filterTree,e as findTree,T as forEachTree,m as getChildrenTree,d as getNodeDepth,y as getNodeDepthMap,E as getParentTree,v as getSiblingsTree,S as includesTree,a as indexOfTree,D as isEmptySingleTreeData,p as isEmptyTreeData,x as isSingleTreeData,b as isTreeData,n as mapTree,u as popTree,i as pushTree,g as removeTree,c as shiftTree,f as someTree,o as unshiftTree}
83
+ for(const r of e)if(!b(r,t))return!1}return!0}function E(n,t=r){if(!Array.isArray(n))return!1
84
+ for(const r of n)if(!b(r,t))return!1
85
+ return!0}function j(n,t=r){if(!n||"object"!=typeof n||Array.isArray(n))return!1
86
+ const e=n[t.children]
87
+ return void 0===e||Array.isArray(e)}function x(n,t=r,e=new WeakSet){if(!n||"object"!=typeof n||Array.isArray(n))return!1
88
+ if(e.has(n))return!1
89
+ e.add(n)
90
+ const i=n[t.children]
91
+ if(void 0!==i){if(null===i)return!1
92
+ if(!Array.isArray(i))return!1
93
+ for(const r of i)if(!x(r,t,e))return!1}return!0}function C(n,t,e=r){if(t<=0)return!1
94
+ return function r(n,i){if(i>t)return!1
95
+ for(const t of n){const n=t[e.children]
96
+ if(Array.isArray(n)&&n.length>0&&!r(n,i+1))return!1}return!0}(n,1)}function k(n,t=r){const e=n[t.children]
97
+ return void 0===e||!Array.isArray(e)||0===e.length}function w(n,t,e=r){return!!m(n,t,e)&&null===S(n,t,e)}const O={mapTree:n,filterTree:t,findTree:e,pushTree:i,unshiftTree:o,popTree:u,shiftTree:c,someTree:f,everyTree:l,atTree:s,indexOfTree:a,atIndexOfTree:h,getNodeDepthMap:y,getNodeDepth:d,dedupTree:A,removeTree:g,forEachTree:T,isEmptyTreeData:p,isEmptySingleTreeData:v,getParentTree:S,getChildrenTree:D,getSiblingsTree:N,includesTree:m,isSingleTreeData:b,isTreeData:E,isValidTreeNode:j,isTreeNodeWithCircularCheck:x,isSafeTreeDepth:C,isLeafNode:k,isRootNode:w}
98
+ export{h as atIndexOfTree,s as atTree,A as dedupTree,O as default,l as everyTree,t as filterTree,e as findTree,T as forEachTree,D as getChildrenTree,d as getNodeDepth,y as getNodeDepthMap,S as getParentTree,N as getSiblingsTree,m as includesTree,a as indexOfTree,v as isEmptySingleTreeData,p as isEmptyTreeData,k as isLeafNode,w as isRootNode,C as isSafeTreeDepth,b as isSingleTreeData,E as isTreeData,x as isTreeNodeWithCircularCheck,j as isValidTreeNode,n as mapTree,u as popTree,i as pushTree,g as removeTree,c as shiftTree,f as someTree,o as unshiftTree}
@@ -5,67 +5,67 @@ return function r(n){for(const o of n){i.push(e(o))
5
5
  const n=o[t.children]
6
6
  Array.isArray(n)&&n.length>0&&r(n)}}(r),i}function t(r,e,t=n){const i=[]
7
7
  return function r(n){n.forEach((n,o)=>{e(n,o)&&i.push(n)
8
- const u=n[t.children]
9
- Array.isArray(u)&&u.length>0&&r(u,o)})}(r),i}function i(r,e,t=n){for(const n of r){if(e(n))return n
8
+ const f=n[t.children]
9
+ Array.isArray(f)&&f.length>0&&r(f,o)})}(r),i}function i(r,e,t=n){for(const n of r){if(e(n))return n
10
10
  const r=n[t.children]
11
11
  if(Array.isArray(r)&&r.length>0){const n=i(r,e,t)
12
12
  if(n)return n}}return null}function o(r,e,t,i=n){return function r(n){for(const o of n){if(o[i.id]===e)return o[i.children]||(o[i.children]=[]),o[i.children].push(t),!0
13
13
  const n=o[i.children]
14
- if(Array.isArray(n)&&n.length>0&&r(n))return!0}return!1}(r)}function u(r,e,t,i=n){return function r(n){for(const o of n){if(o[i.id]===e)return o[i.children]||(o[i.children]=[]),o[i.children].unshift(t),!0
14
+ if(Array.isArray(n)&&n.length>0&&r(n))return!0}return!1}(r)}function f(r,e,t,i=n){return function r(n){for(const o of n){if(o[i.id]===e)return o[i.children]||(o[i.children]=[]),o[i.children].unshift(t),!0
15
15
  const n=o[i.children]
16
- if(Array.isArray(n)&&n.length>0&&r(n))return!0}return!1}(r)}function f(r,e,t=n){return function r(n){for(const i of n){if(i[t.id]===e){const r=i[t.children]
16
+ if(Array.isArray(n)&&n.length>0&&r(n))return!0}return!1}(r)}function u(r,e,t=n){return function r(n){for(const i of n){if(i[t.id]===e){const r=i[t.children]
17
17
  return!!(Array.isArray(r)&&r.length>0)&&(r.pop(),!0)}const n=i[t.children]
18
18
  if(Array.isArray(n)&&n.length>0&&r(n))return!0}return!1}(r)}function c(r,e,t=n){return function r(n){for(const i of n){if(i[t.id]===e){const r=i[t.children]
19
19
  return!!(Array.isArray(r)&&r.length>0)&&(r.shift(),!0)}const n=i[t.children]
20
- if(Array.isArray(n)&&n.length>0&&r(n))return!0}return!1}(r)}function l(r,e,t=n){for(const n of r){if(e(n))return!0
20
+ if(Array.isArray(n)&&n.length>0&&r(n))return!0}return!1}(r)}function s(r,e,t=n){for(const n of r){if(e(n))return!0
21
21
  const r=n[t.children]
22
- if(Array.isArray(r)&&r.length>0&&l(r,e,t))return!0}return!1}function s(r,e,t=n){for(const n of r){if(!e(n))return!1
22
+ if(Array.isArray(r)&&r.length>0&&s(r,e,t))return!0}return!1}function l(r,e,t=n){for(const n of r){if(!e(n))return!1
23
23
  const r=n[t.children]
24
- if(Array.isArray(r)&&r.length>0&&!s(r,e,t))return!1}return!0}function a(r,e,t,i=n){const o=function r(n){for(const t of n){if(t[i.id]===e)return t
24
+ if(Array.isArray(r)&&r.length>0&&!l(r,e,t))return!1}return!0}function a(r,e,t,i=n){const o=function r(n){for(const t of n){if(t[i.id]===e)return t
25
25
  const n=t[i.children]
26
26
  if(Array.isArray(n)&&n.length>0){const e=r(n)
27
27
  if(e)return e}}return null}(r)
28
28
  if(!o)return null
29
- const u=o[i.children]
30
- if(!Array.isArray(u)||0===u.length)return null
31
- const f=t>=0?t:u.length+t
32
- return f>=0&&f<u.length?u[f]:null}function h(r,e,t=n){return function r(n,i=[]){for(let o=0;o<n.length;o++){const u=n[o],f=[...i,o]
33
- if(u[t.id]===e)return f
34
- const c=u[t.children]
35
- if(Array.isArray(c)&&c.length>0){const n=r(c,f)
29
+ const f=o[i.children]
30
+ if(!Array.isArray(f)||0===f.length)return null
31
+ const u=t>=0?t:f.length+t
32
+ return u>=0&&u<f.length?f[u]:null}function h(r,e,t=n){return function r(n,i=[]){for(let o=0;o<n.length;o++){const f=n[o],u=[...i,o]
33
+ if(f[t.id]===e)return u
34
+ const c=f[t.children]
35
+ if(Array.isArray(c)&&c.length>0){const n=r(c,u)
36
36
  if(n)return n}}return null}(r)}function d(r,e,t=n){if(!Array.isArray(e)||0===e.length)return null
37
37
  let i=r
38
38
  for(let r=0;r<e.length;r++){const n=e[r]
39
39
  if(!Array.isArray(i)||n<0||n>=i.length)return null
40
40
  const o=i[n]
41
41
  if(r===e.length-1)return o
42
- const u=o[t.children]
43
- if(!Array.isArray(u))return null
44
- i=u}return null}function y(r,e=n){const t={}
42
+ const f=o[t.children]
43
+ if(!Array.isArray(f))return null
44
+ i=f}return null}function y(r,e=n){const t={}
45
45
  return function r(n,i=1){for(const o of n){t[o[e.id]]=i
46
46
  const n=o[e.children]
47
47
  Array.isArray(n)&&n.length>0&&r(n,i+1)}}(r),t}function A(r,e,t=n){return function r(n,i=1){for(const o of n){if(o[t.id]===e)return i
48
48
  const n=o[t.children]
49
49
  if(Array.isArray(n)&&n.length>0){const e=r(n,i+1)
50
- if(null!==e)return e}}return null}(r)}function g(r,e,t=n){const i=new Set
50
+ if(null!==e)return e}}return null}(r)}function T(r,e,t=n){const i=new Set
51
51
  return function r(n){const o=[]
52
- for(const u of n){const n=u[e]
52
+ for(const f of n){const n=f[e]
53
53
  if(null!=n){if(i.has(n))continue
54
- i.add(n)}const f={...u},c=u[t.children]
55
- Array.isArray(c)&&c.length>0&&(f[t.children]=r(c)),o.push(f)}return o}(r)}function T(r,e,t=n){return function r(n){for(let i=0;i<n.length;i++){const o=n[i]
54
+ i.add(n)}const u={...f},c=f[t.children]
55
+ Array.isArray(c)&&c.length>0&&(u[t.children]=r(c)),o.push(u)}return o}(r)}function g(r,e,t=n){return function r(n){for(let i=0;i<n.length;i++){const o=n[i]
56
56
  if(o[t.id]===e)return n.splice(i,1),!0
57
- const u=o[t.children]
58
- if(Array.isArray(u)&&u.length>0&&r(u))return!0}return!1}(r)}function p(r,e,t=n){!function r(n){for(const i of n){e(i)
57
+ const f=o[t.children]
58
+ if(Array.isArray(f)&&f.length>0&&r(f))return!0}return!1}(r)}function p(r,e,t=n){!function r(n){for(const i of n){e(i)
59
59
  const n=i[t.children]
60
- Array.isArray(n)&&n.length>0&&r(n)}}(r)}function m(r){return!Array.isArray(r)||0===r.length}function D(r,e=n){if(!E(r,e))return!0
60
+ Array.isArray(n)&&n.length>0&&r(n)}}(r)}function D(r){return!Array.isArray(r)||0===r.length}function m(r,e=n){if(!x(r,e))return!0
61
61
  const t=r[e.children]
62
- return void 0===t||(!Array.isArray(t)||0===t.length)}function S(r,e,t=n){const i=function r(n){for(const i of n){if(i[t.id]===e)return i
62
+ return void 0===t||(!Array.isArray(t)||0===t.length)}function N(r,e,t=n){const i=function r(n){for(const i of n){if(i[t.id]===e)return i
63
63
  const n=i[t.children]
64
64
  if(Array.isArray(n)&&n.length>0){const e=r(n)
65
65
  if(null!==e)return e}}return null}(r)
66
66
  if(!i)return[]
67
67
  const o=i[t.children]
68
- return Array.isArray(o)?o:[]}function b(r,e,t=n){const i=function r(n,i=null){for(const o of n){if(o[t.id]===e)return{node:o,parent:i}
68
+ return Array.isArray(o)?o:[]}function S(r,e,t=n){const i=function r(n,i=null){for(const o of n){if(o[t.id]===e)return{node:o,parent:i}
69
69
  const n=o[t.children]
70
70
  if(Array.isArray(n)&&n.length>0){const e=r(n,o)
71
71
  if(null!==e)return e}}return null}(r)
@@ -75,13 +75,25 @@ const o=i.parent[t.children]
75
75
  return Array.isArray(o)?o:[]}function v(r,e,t=n){return function r(n,i=null){for(const o of n){if(o[t.id]===e)return i
76
76
  const n=o[t.children]
77
77
  if(Array.isArray(n)&&n.length>0){const e=r(n,o)
78
- if(null!==e)return e}}return null}(r)}function x(r,e,t=n){for(const n of r){if(n[t.id]===e)return!0
78
+ if(null!==e)return e}}return null}(r)}function b(r,e,t=n){for(const n of r){if(n[t.id]===e)return!0
79
79
  const r=n[t.children]
80
- if(Array.isArray(r)&&r.length>0&&x(r,e,t))return!0}return!1}function E(r,e=n){if(!r||"object"!=typeof r||Array.isArray(r))return!1
80
+ if(Array.isArray(r)&&r.length>0&&b(r,e,t))return!0}return!1}function x(r,e=n){if(!r||"object"!=typeof r||Array.isArray(r))return!1
81
81
  const t=r[e.children]
82
82
  if(void 0!==t){if(null===t)return!1
83
83
  if(!Array.isArray(t))return!1
84
- for(const r of t)if(!E(r,e))return!1}return!0}function O(r,e=n){if(!Array.isArray(r))return!1
85
- for(const n of r)if(!E(n,e))return!1
86
- return!0}const M={mapTree:e,filterTree:t,findTree:i,pushTree:o,unshiftTree:u,popTree:f,shiftTree:c,someTree:l,everyTree:s,atTree:a,indexOfTree:h,atIndexOfTree:d,getNodeDepthMap:y,getNodeDepth:A,dedupTree:g,removeTree:T,forEachTree:p,isEmptyTreeData:m,isEmptySingleTreeData:D,getParentTree:v,getChildrenTree:S,getSiblingsTree:b,includesTree:x,isSingleTreeData:E,isTreeData:O}
87
- r.atIndexOfTree=d,r.atTree=a,r.dedupTree=g,r.default=M,r.everyTree=s,r.filterTree=t,r.findTree=i,r.forEachTree=p,r.getChildrenTree=S,r.getNodeDepth=A,r.getNodeDepthMap=y,r.getParentTree=v,r.getSiblingsTree=b,r.includesTree=x,r.indexOfTree=h,r.isEmptySingleTreeData=D,r.isEmptyTreeData=m,r.isSingleTreeData=E,r.isTreeData=O,r.mapTree=e,r.popTree=f,r.pushTree=o,r.removeTree=T,r.shiftTree=c,r.someTree=l,r.unshiftTree=u,Object.defineProperties(r,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})})
84
+ for(const r of t)if(!x(r,e))return!1}return!0}function E(r,e=n){if(!Array.isArray(r))return!1
85
+ for(const n of r)if(!x(n,e))return!1
86
+ return!0}function C(r,e=n){if(!r||"object"!=typeof r||Array.isArray(r))return!1
87
+ const t=r[e.children]
88
+ return void 0===t||Array.isArray(t)}function j(r,e=n,t=new WeakSet){if(!r||"object"!=typeof r||Array.isArray(r))return!1
89
+ if(t.has(r))return!1
90
+ t.add(r)
91
+ const i=r[e.children]
92
+ if(void 0!==i){if(null===i)return!1
93
+ if(!Array.isArray(i))return!1
94
+ for(const r of i)if(!j(r,e,t))return!1}return!0}function O(r,e,t=n){if(e<=0)return!1
95
+ return function r(n,i){if(i>e)return!1
96
+ for(const e of n){const n=e[t.children]
97
+ if(Array.isArray(n)&&n.length>0&&!r(n,i+1))return!1}return!0}(r,1)}function M(r,e=n){const t=r[e.children]
98
+ return void 0===t||!Array.isArray(t)||0===t.length}function P(r,e,t=n){return!!b(r,e,t)&&null===v(r,e,t)}const k={mapTree:e,filterTree:t,findTree:i,pushTree:o,unshiftTree:f,popTree:u,shiftTree:c,someTree:s,everyTree:l,atTree:a,indexOfTree:h,atIndexOfTree:d,getNodeDepthMap:y,getNodeDepth:A,dedupTree:T,removeTree:g,forEachTree:p,isEmptyTreeData:D,isEmptySingleTreeData:m,getParentTree:v,getChildrenTree:N,getSiblingsTree:S,includesTree:b,isSingleTreeData:x,isTreeData:E,isValidTreeNode:C,isTreeNodeWithCircularCheck:j,isSafeTreeDepth:O,isLeafNode:M,isRootNode:P}
99
+ r.atIndexOfTree=d,r.atTree=a,r.dedupTree=T,r.default=k,r.everyTree=l,r.filterTree=t,r.findTree=i,r.forEachTree=p,r.getChildrenTree=N,r.getNodeDepth=A,r.getNodeDepthMap=y,r.getParentTree=v,r.getSiblingsTree=S,r.includesTree=b,r.indexOfTree=h,r.isEmptySingleTreeData=m,r.isEmptyTreeData=D,r.isLeafNode=M,r.isRootNode=P,r.isSafeTreeDepth=O,r.isSingleTreeData=x,r.isTreeData=E,r.isTreeNodeWithCircularCheck=j,r.isValidTreeNode=C,r.mapTree=e,r.popTree=u,r.pushTree=o,r.removeTree=g,r.shiftTree=c,r.someTree=s,r.unshiftTree=f,Object.defineProperties(r,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})})
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tree-processor",
3
- "version": "0.7.0",
3
+ "version": "0.8.1",
4
4
  "description": "A lightweight TypeScript library for processing tree-structured data with comprehensive methods (map, filter, find, push, pop, remove, getParent, includes, etc.), supporting tree-shaking and custom field names",
5
5
  "main": "dist/tree-processor.cjs.js",
6
6
  "module": "dist/tree-processor.esm.js",
@@ -42,7 +42,16 @@
42
42
  "every",
43
43
  "at",
44
44
  "indexOf",
45
+ "depth",
45
46
  "deduplicate",
47
+ "menu",
48
+ "navigation",
49
+ "file-tree",
50
+ "directory",
51
+ "category",
52
+ "comment",
53
+ "permission",
54
+ "tree-select",
46
55
  "tree-processor"
47
56
  ],
48
57
  "author": "",