tree-processor 0.8.0 → 0.8.2

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,105 @@
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)。
3
+ <div align="right">
4
4
 
5
- 目前已支持 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 的属性名。
5
+ [English](https://github.com/knott11/tree-processor/blob/main/README.en.md) | [中文](https://github.com/knott11/tree-processor/blob/main/README.md)
6
+
7
+ </div>
8
+
9
+ <div align="center">
10
+
11
+ ![npm version](https://img.shields.io/npm/v/tree-processor?style=flat-square)
12
+ ![npm downloads](https://img.shields.io/npm/dm/tree-processor?style=flat-square)
13
+ ![bundle size](https://img.shields.io/badge/bundle-6.6KB-blue?style=flat-square)
14
+ ![License](https://img.shields.io/badge/license-MIT-green?style=flat-square)
15
+ ![coverage](https://img.shields.io/badge/coverage-99%25-brightgreen?style=flat-square)
16
+
17
+ 一个轻量级的树结构数据处理工具库,使用 TypeScript 编写,支持 tree-shaking,每个格式打包体积约 **6-7 KB**(ESM: 6.39 KB,CJS: 6.64 KB,UMD: 6.68 KB)。
18
+
19
+
20
+ </div>
21
+
22
+ ## 📋 目录
23
+
24
+ - [特性](#-特性)
25
+ - [使用场景](#-使用场景)
26
+ - [安装](#-安装)
27
+ - [快速开始](#-快速开始)
28
+ - [API 文档](#-api-文档)
29
+ - [遍历方法](#遍历方法)
30
+ - [查找方法](#查找方法)
31
+ - [访问方法](#访问方法)
32
+ - [修改方法](#修改方法)
33
+ - [查询方法](#查询方法)
34
+ - [验证方法](#验证方法)
35
+ - [自定义字段名](#自定义字段名)
36
+ - [测试](#测试)
37
+ - [开发](#开发)
6
38
 
7
39
  ## ✨ 特性
8
40
 
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
- - 🧪 **完善的测试覆盖** - 包含 272 个测试用例,覆盖基础功能、边界情况、异常处理、复杂场景、npm 包导入等
41
+ - **轻量级** - 每个格式打包体积仅 6-7 KB(ESM: 6.39 KB,CJS: 6.64 KB,UMD: 6.68 KB),对项目体积影响极小
42
+ - **支持 Tree-shaking** - 支持按需导入,只打包实际使用的代码,进一步减小打包体积
43
+ - **完整的 TypeScript 支持** - 提供完整的类型定义和智能提示,提升开发体验
44
+ - **灵活的自定义字段名** - 支持自定义 children id 字段名,适配各种数据结构
45
+ - **零依赖** - 无任何外部依赖,开箱即用,无需担心依赖冲突
46
+ - **完善的测试覆盖** - 包含 290 个测试用例,测试覆盖率达到 99%+(语句覆盖率 99.67%,分支覆盖率 99.32%,函数覆盖率 100%),覆盖基础功能、边界情况、异常处理、复杂场景等
47
+ - **丰富的 API** - 提供 30+ 个方法,包含类似数组的 API(map、filter、find、some、every、includes、at、indexOf 等),以及树结构特有的操作(获取父子节点、深度计算、数据验证等),涵盖遍历、查找、修改、判断等完整场景
48
+
49
+ **已支持的方法:** 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 的属性名。
50
+
51
+ ### 💡 使用场景
52
+
53
+ - **导航系统** - 多级菜单、路由配置的展开、折叠、搜索、过滤
54
+ - **文件系统** - 文件目录的遍历、查找、移动、删除
55
+ - **权限系统** - 组织架构、角色权限的树形结构管理和验证
56
+ - **框架开发** - 组件树、路由树等树形结构的构建和管理
57
+ - **数据管理** - 分类管理、评论系统、树形选择器等数据操作
16
58
 
17
59
  ## 📦 安装
18
60
 
19
61
  ```bash
62
+ npm install tree-processor
63
+ # 或
20
64
  yarn add tree-processor
21
65
  # 或
22
- npm i tree-processor
66
+ pnpm add tree-processor
23
67
  ```
24
68
 
25
- ## 使用说明
69
+ ## 🚀 快速开始
26
70
 
27
- ### 引入
71
+ ```javascript
72
+ import { mapTree, findTree, filterTree } from 'tree-processor'
73
+
74
+ const treeData = [
75
+ {
76
+ id: 1,
77
+ name: 'node1',
78
+ children: [
79
+ { id: 2, name: 'node2' },
80
+ { id: 3, name: 'node3' },
81
+ ],
82
+ },
83
+ ]
84
+
85
+ // 获取所有节点名称
86
+ const names = mapTree(treeData, (node) => node.name)
87
+ console.log(names) // ['node1', 'node2', 'node3']
88
+
89
+ // 查找节点
90
+ const node = findTree(treeData, (n) => n.id === 2)
91
+ console.log(node) // { id: 2, name: 'node2' }
92
+
93
+ // 过滤节点
94
+ const filtered = filterTree(treeData, (n) => n.id > 1)
95
+ console.log(filtered) // [{ id: 2, name: 'node2' }, { id: 3, name: 'node3' }]
96
+ ```
97
+
98
+ ## 📖 API 文档
99
+
100
+ ### 引入方式
101
+
102
+ #### 默认导入(推荐用于需要多个方法的场景)
28
103
 
29
104
  #### 默认导入(推荐用于需要多个方法的场景)
30
105
 
@@ -49,17 +124,7 @@ import type { TreeNode, TreeData, FieldNames } from 'tree-processor'
49
124
  const { mapTree, filterTree } = require('tree-processor')
50
125
  ```
51
126
 
52
- **按需导入的优势:**
53
- - ✅ 支持 tree-shaking,只打包使用的代码,减小打包体积
54
- - ✅ 更好的代码提示和类型检查
55
- - ✅ 更清晰的依赖关系
56
-
57
- **关于类型导入:**
58
- - TypeScript 会自动从函数签名推断类型,**大多数情况下不需要显式引入类型**
59
- - 只有在需要显式声明变量类型时才需要引入类型(如 `const treeData: TreeData = [...]`)
60
- - 使用 `import type` 导入类型不会增加运行时体积(类型在编译时会被移除)
61
-
62
- ### 示例树结构数据
127
+ ### 示例数据
63
128
 
64
129
  以下示例数据将用于后续所有方法的演示:
65
130
 
@@ -87,7 +152,11 @@ const treeData = [
87
152
  ];
88
153
  ```
89
154
 
90
- ### mapTree(遍历树结构数据的方法)
155
+ ---
156
+
157
+ ## 遍历方法
158
+
159
+ ### mapTree
91
160
 
92
161
  遍历树结构数据,对每个节点执行回调函数,返回映射后的数组。
93
162
 
@@ -108,7 +177,7 @@ const modifiedNodes = t.mapTree(treeData, (node) => ({
108
177
  console.log(modifiedNodes) // 返回包含 label 字段的新数组
109
178
  ```
110
179
 
111
- ### forEachTree(遍历树结构数据的方法,不返回值)
180
+ ### forEachTree
112
181
 
113
182
  遍历树结构数据,对每个节点执行回调函数。与 mapTree 的区别是不返回值,性能更好,适合只需要遍历而不需要返回结果的场景。
114
183
 
@@ -132,7 +201,11 @@ t.forEachTree(treeData, () => {
132
201
  console.log(nodeCount) // 节点总数
133
202
  ```
134
203
 
135
- ### filterTree(树结构数据的filter方法)
204
+ ---
205
+
206
+ ## 查找方法
207
+
208
+ ### filterTree
136
209
 
137
210
  过滤树结构数据,返回满足条件的节点。
138
211
 
@@ -154,7 +227,7 @@ const leafNodes = t.filterTree(treeData, (node) => {
154
227
  console.log(leafNodes) // 返回所有叶子节点
155
228
  ```
156
229
 
157
- ### findTree(树结构数据的find方法)
230
+ ### findTree
158
231
 
159
232
  查找树结构数据中满足条件的第一个节点。如果未找到,返回 null。
160
233
 
@@ -172,57 +245,18 @@ const nodeNotFound = t.findTree(treeData, (node) => node.id === 999)
172
245
  console.log(nodeNotFound) // null
173
246
  ```
174
247
 
175
- ### pushTree(在指定节点下添加子节点到末尾)
248
+ ### includesTree
176
249
 
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。
250
+ 检查树结构数据中是否包含指定ID的节点。
204
251
 
205
252
  ```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。
253
+ const nodeId = 2
254
+ const hasNode = t.includesTree(treeData, nodeId)
218
255
 
219
- ```javascript
220
- // 删除ID为1的节点下的第一个子节点
221
- const shiftedNode = t.shiftTree(treeData, 1)
222
- console.log(shiftedNode) // 返回被删除的节点对象,或 false
256
+ console.log(hasNode) // true 表示包含该节点,false 表示不包含
223
257
  ```
224
258
 
225
- ### someTree(树结构数据的some方法)
259
+ ### someTree
226
260
 
227
261
  检查树结构数据中是否存在满足条件的节点。只要有一个节点满足条件就返回 true。
228
262
 
@@ -236,7 +270,7 @@ const hasLargeId = t.someTree(treeData, node => node.id > 10)
236
270
  console.log(hasLargeId) // false
237
271
  ```
238
272
 
239
- ### everyTree(树结构数据的every方法)
273
+ ### everyTree
240
274
 
241
275
  检查树结构数据中是否所有节点都满足条件。只有所有节点都满足条件才返回 true。
242
276
 
@@ -250,18 +284,11 @@ const allHaveName = t.everyTree(treeData, node => node.name)
250
284
  console.log(allHaveName) // 根据实际数据返回 true 或 false
251
285
  ```
252
286
 
253
- ### includesTree(检查树中是否包含指定节点)
254
-
255
- 检查树结构数据中是否包含指定ID的节点。
256
-
257
- ```javascript
258
- const nodeId = 2
259
- const hasNode = t.includesTree(treeData, nodeId)
287
+ ---
260
288
 
261
- console.log(hasNode) // true 表示包含该节点,false 表示不包含
262
- ```
289
+ ## 访问方法
263
290
 
264
- ### atTree(根据父节点ID和子节点索引获取节点)
291
+ ### atTree
265
292
 
266
293
  根据父节点ID和子节点索引获取节点。支持负数索引,和数组的 at 方法一样。未找到返回 null。
267
294
 
@@ -279,7 +306,7 @@ const nodeNotFound = t.atTree(treeData, 1, 10)
279
306
  console.log(nodeNotFound) // null
280
307
  ```
281
308
 
282
- ### indexOfTree(返回从根节点到目标节点的索引路径)
309
+ ### indexOfTree
283
310
 
284
311
  返回一个数组,值为从根节点开始到 targetId 所在节点的索引路径。未找到返回 null。返回值可以传入 atIndexOfTree 的第二个参数进行取值。
285
312
 
@@ -298,7 +325,7 @@ const nodeByPath = t.atIndexOfTree(treeData, indexPath)
298
325
  console.log(nodeByPath) // 获取到ID为4的节点
299
326
  ```
300
327
 
301
- ### atIndexOfTree(根据索引路径获取节点)
328
+ ### atIndexOfTree
302
329
 
303
330
  根据索引路径获取节点。路径无效或超出范围返回 null。
304
331
 
@@ -317,21 +344,61 @@ const invalidPath = t.atIndexOfTree(treeData, [999])
317
344
  console.log(invalidPath) // null
318
345
  ```
319
346
 
320
- ### dedupTree(树结构对象数组去重方法)
347
+ ---
321
348
 
322
- 树结构对象数组去重方法,根据指定的键去除重复节点。保留第一次出现的节点。
349
+ ## 修改方法
350
+
351
+ ### pushTree
352
+
353
+ 在指定节点下添加子节点到末尾。返回 true 表示添加成功,false 表示未找到目标节点。
323
354
 
324
355
  ```javascript
325
- // 根据 id 字段去重
326
- const uniqueTreeData = t.dedupTree(treeData, 'id')
327
- console.log(uniqueTreeData) // 返回去重后的树结构数据
356
+ // 在ID为1的节点下添加新子节点
357
+ const addSuccess = t.pushTree(treeData, 1, { id: 7, name: 'node7' })
358
+ console.log(addSuccess) // true
359
+ console.log(treeData) // 新节点已添加到 children 数组末尾
328
360
 
329
- // 根据 name 字段去重
330
- const uniqueByNameTree = t.dedupTree(treeData, 'name')
331
- console.log(uniqueByNameTree) // 返回根据 name 去重后的数据
361
+ // 尝试在不存在的节点下添加
362
+ const addFailed = t.pushTree(treeData, 999, { id: 8, name: 'node8' })
363
+ console.log(addFailed) // false,未找到目标节点
364
+ ```
365
+
366
+ ### unshiftTree
367
+
368
+ 在指定节点下添加子节点到开头。返回 true 表示添加成功,false 表示未找到目标节点。
369
+
370
+ ```javascript
371
+ // 在ID为1的节点下添加新子节点到开头
372
+ const unshiftSuccess = t.unshiftTree(treeData, 1, { id: 7, name: 'node7' })
373
+ console.log(unshiftSuccess) // true
374
+ console.log(treeData) // 新节点已添加到 children 数组开头
375
+ ```
376
+
377
+ ### popTree
378
+
379
+ 删除指定节点下的最后一个子节点。返回被删除的节点,如果节点不存在或没有子节点则返回 false。
380
+
381
+ ```javascript
382
+ // 删除ID为1的节点下的最后一个子节点
383
+ const removedNode = t.popTree(treeData, 1)
384
+ console.log(removedNode) // 返回被删除的节点对象,或 false
385
+
386
+ // 尝试删除不存在的节点下的子节点
387
+ const popFailed = t.popTree(treeData, 999)
388
+ console.log(popFailed) // false
389
+ ```
390
+
391
+ ### shiftTree
392
+
393
+ 删除指定节点下的第一个子节点。返回被删除的节点,如果节点不存在或没有子节点则返回 false。
394
+
395
+ ```javascript
396
+ // 删除ID为1的节点下的第一个子节点
397
+ const shiftedNode = t.shiftTree(treeData, 1)
398
+ console.log(shiftedNode) // 返回被删除的节点对象,或 false
332
399
  ```
333
400
 
334
- ### removeTree(删除指定节点)
401
+ ### removeTree
335
402
 
336
403
  删除树结构数据中指定ID的节点,包括根节点和子节点。
337
404
 
@@ -343,7 +410,25 @@ console.log(removeSuccess) // true 表示删除成功,false 表示未找到节
343
410
  console.log(treeData) // 删除后的树结构
344
411
  ```
345
412
 
346
- ### getParentTree(获取节点的父节点)
413
+ ### dedupTree
414
+
415
+ 树结构对象数组去重方法,根据指定的键去除重复节点。保留第一次出现的节点。
416
+
417
+ ```javascript
418
+ // 根据 id 字段去重
419
+ const uniqueTreeData = t.dedupTree(treeData, 'id')
420
+ console.log(uniqueTreeData) // 返回去重后的树结构数据
421
+
422
+ // 根据 name 字段去重
423
+ const uniqueByNameTree = t.dedupTree(treeData, 'name')
424
+ console.log(uniqueByNameTree) // 返回根据 name 去重后的数据
425
+ ```
426
+
427
+ ---
428
+
429
+ ## 查询方法
430
+
431
+ ### getParentTree
347
432
 
348
433
  获取指定节点的父节点。如果节点是根节点或未找到,返回 null。
349
434
 
@@ -361,7 +446,7 @@ const parentNotFound = t.getParentTree(treeData, 999)
361
446
  console.log(parentNotFound) // null
362
447
  ```
363
448
 
364
- ### getChildrenTree(获取节点的所有直接子节点)
449
+ ### getChildrenTree
365
450
 
366
451
  获取指定节点的所有直接子节点。如果未找到节点或没有子节点,返回空数组。
367
452
 
@@ -394,7 +479,7 @@ const customChildren = t.getChildrenTree(customTree, 1, fieldNames)
394
479
  console.log(customChildren) // 返回子节点数组
395
480
  ```
396
481
 
397
- ### getSiblingsTree(获取节点的所有兄弟节点)
482
+ ### getSiblingsTree
398
483
 
399
484
  获取指定节点的所有兄弟节点(包括自己)。如果未找到节点,返回空数组。根节点的兄弟节点是其他根节点。
400
485
 
@@ -432,7 +517,7 @@ const customSiblings = t.getSiblingsTree(customTree, 2, fieldNames)
432
517
  console.log(customSiblings) // 返回兄弟节点数组(包括自己)
433
518
  ```
434
519
 
435
- ### getNodeDepthMap(返回节点ID到深度的映射)
520
+ ### getNodeDepthMap
436
521
 
437
522
  返回一个字典,键代表节点的 id,值代表该节点在数据的第几层。深度从1开始,根节点深度为1。
438
523
 
@@ -450,7 +535,7 @@ const emptyDepthMap = t.getNodeDepthMap([])
450
535
  console.log(emptyDepthMap) // {}
451
536
  ```
452
537
 
453
- ### getNodeDepth(获取单个节点的深度)
538
+ ### getNodeDepth
454
539
 
455
540
  获取指定节点的深度。深度从1开始,根节点深度为1。
456
541
 
@@ -490,7 +575,11 @@ console.log(depth) // 2
490
575
  - `getNodeDepthMap` - 批量获取所有节点的深度(一次性计算所有节点)
491
576
  - `getNodeDepth` - 只获取单个节点的深度(只计算目标节点,效率更高)
492
577
 
493
- ### isLeafNode(检查节点是否是叶子节点)
578
+ ---
579
+
580
+ ## 验证方法
581
+
582
+ ### isLeafNode
494
583
 
495
584
  检查节点是否是叶子节点(没有子节点)。轻量级方法,只检查节点本身,不遍历树。
496
585
 
@@ -536,7 +625,7 @@ console.log(t.isLeafNode(customNode, fieldNames)) // true
536
625
  - `isLeafNode` - 只检查单个节点,轻量级(O(1)),适合在遍历时使用
537
626
  - `getChildrenTree` - 获取子节点数组,需要传入 tree 和 nodeId,需要查找节点(O(n))
538
627
 
539
- ### isRootNode(检查节点是否是根节点)
628
+ ### isRootNode
540
629
 
541
630
  检查节点是否是根节点(没有父节点)。根节点是树结构数据数组中的顶层节点。
542
631
 
@@ -590,7 +679,7 @@ console.log(t.isRootNode(treeData, 999)) // false
590
679
  - `getParentTree` - 返回父节点对象,需要判断是否为 null
591
680
  - `getNodeDepth` - 返回深度,需要判断是否等于 1
592
681
 
593
- ### isEmptyTreeData(检查树结构数据是否为空)
682
+ ### isEmptyTreeData
594
683
 
595
684
  检查树结构数据(数组)是否为空。空数组、null、undefined 都视为空。此函数支持 fieldNames 参数以保持 API 一致性,但该参数不生效(因为只检查数组是否为空,不访问 children 或 id 字段)。
596
685
 
@@ -613,7 +702,7 @@ const isEmptyWithFieldNames = t.isEmptyTreeData(treeData, fieldNames)
613
702
  console.log(isEmptyWithFieldNames) // false(结果与不传 fieldNames 相同)
614
703
  ```
615
704
 
616
- ### isEmptySingleTreeData(检查单个树结构数据是否为空)
705
+ ### isEmptySingleTreeData
617
706
 
618
707
  检查单个树结构数据是否为空。如果数据不是有效的单个树结构数据、没有 children 字段,或者 children 是空数组,则视为空。如果有子节点(children 数组不为空),即使子节点本身是空的,树也不为空。
619
708
 
@@ -666,7 +755,7 @@ const isEmptyCustom = t.isEmptySingleTreeData(customTree, fieldNames)
666
755
  console.log(isEmptyCustom) // true
667
756
  ```
668
757
 
669
- ### isTreeData(判断数据是否是树结构数据)
758
+ ### isTreeData
670
759
 
671
760
  判断数据是否是树结构数据(数组)。树结构数据必须是一个数组,数组中的每个元素都必须是有效的单个树结构数据。
672
761
 
@@ -715,7 +804,7 @@ const fieldNames = { children: 'subNodes', id: 'nodeId' };
715
804
  console.log(t.isTreeData(customForest, fieldNames)) // true
716
805
  ```
717
806
 
718
- ### isSingleTreeData(判断数据是否是单个树结构数据)
807
+ ### isSingleTreeData
719
808
 
720
809
  判断数据是否是单个树结构数据(单个对象)。树结构数据必须是一个对象(不能是数组、null、undefined 或基本类型),如果存在 children 字段,必须是数组类型,并且会递归检查所有子节点。
721
810
 
@@ -757,7 +846,7 @@ const fieldNames = { children: 'subNodes', id: 'nodeId' };
757
846
  console.log(t.isSingleTreeData(customTree, fieldNames)) // true
758
847
  ```
759
848
 
760
- ### isValidTreeNode(检查单个节点是否是有效的树节点结构)
849
+ ### isValidTreeNode
761
850
 
762
851
  检查单个节点是否是有效的树节点结构(轻量级,不递归检查子节点)。只检查节点本身的结构,不检查子节点。
763
852
 
@@ -794,7 +883,7 @@ console.log(t.isValidTreeNode(customNode, fieldNames)) // true
794
883
  - `isValidTreeNode` - 只检查单个节点的基本结构,不递归检查子节点(轻量级)
795
884
  - `isSingleTreeData` - 递归检查整个树结构,确保所有子节点都是有效的树结构
796
885
 
797
- ### isTreeNodeWithCircularCheck(检查节点结构并检测循环引用)
886
+ ### isTreeNodeWithCircularCheck
798
887
 
799
888
  检查节点是否是有效的树节点结构,并检测循环引用。使用 WeakSet 跟踪已访问的节点,如果发现循环引用则返回 false。
800
889
 
@@ -834,7 +923,7 @@ console.log(t.isTreeNodeWithCircularCheck(customNode, fieldNames)) // true
834
923
  - 数据验证,防止无限递归
835
924
  - 调试时检查数据结构是否正确
836
925
 
837
- ### isSafeTreeDepth(检查树深度是否安全)
926
+ ### isSafeTreeDepth
838
927
 
839
928
  检查树结构数据的深度是否安全(防止递归爆栈)。如果树的深度超过 `maxDepth`,返回 false。
840
929
 
@@ -930,13 +1019,10 @@ npm test
930
1019
  npm run build
931
1020
  ```
932
1021
 
933
- ## 技术栈
1022
+ <div align="center">
934
1023
 
935
- - **Rollup** - 模块打包工具
936
- - **Vitest** - 单元测试框架
937
- - **Terser** - JavaScript 压缩工具
938
- - **TypeScript** - 类型支持
1024
+ 如果这个项目对你有帮助,请给它一个 ⭐️
939
1025
 
940
- ## License
1026
+ Made with by [knott11]
941
1027
 
942
- MIT
1028
+ </div>
@@ -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.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}};
4932
+ const data = {"version":2,"tree":{"name":"root","children":[{"name":"tree-processor.umd.js","children":[{"name":"src/index.ts","uid":"975942c2-1"}]}],"isRoot":true},"nodeParts":{"975942c2-1":{"renderedLength":17081,"gzipLength":2155,"brotliLength":1901,"metaUid":"975942c2-0"}},"nodeMetas":{"975942c2-0":{"id":"\\src\\index.ts","moduleParts":{"tree-processor.umd.js":"975942c2-1"},"imported":[],"importedBy":[],"isEntry":true}},"env":{"rollup":"4.57.1"},"options":{"gzip":true,"brotli":true,"sourcemap":false}};
4933
4933
 
4934
4934
  const run = () => {
4935
4935
  const width = window.innerWidth;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tree-processor",
3
- "version": "0.8.0",
3
+ "version": "0.8.2",
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",
@@ -46,12 +46,6 @@
46
46
  "deduplicate",
47
47
  "menu",
48
48
  "navigation",
49
- "file-tree",
50
- "directory",
51
- "category",
52
- "comment",
53
- "permission",
54
- "tree-select",
55
49
  "tree-processor"
56
50
  ],
57
51
  "author": "",