From c21af0b8e37db9e5a209abf13e3b451a8d7c8f02 Mon Sep 17 00:00:00 2001 From: Victor Bo Date: Thu, 26 Oct 2023 11:36:07 +0800 Subject: [PATCH] feat: added tree package (#38) --- package.json | 3 +- packages/core/index.ts | 1 + packages/tree/index.ts | 1 + packages/tree/package.json | 56 ++++++++++++++++++ packages/tree/src/tree.ts | 106 +++++++++++++++++++++++++++++++++++ packages/tree/tsup.config.ts | 9 +++ pnpm-lock.yaml | 9 +++ 7 files changed, 184 insertions(+), 1 deletion(-) create mode 100644 packages/tree/index.ts create mode 100644 packages/tree/package.json create mode 100644 packages/tree/src/tree.ts create mode 100644 packages/tree/tsup.config.ts diff --git a/package.json b/package.json index dab279b..f8edf6d 100644 --- a/package.json +++ b/package.json @@ -73,7 +73,8 @@ "@vtrbo/utils-log": "workspace:*", "@vtrbo/utils-obj": "workspace:*", "@vtrbo/utils-str": "workspace:*", - "@vtrbo/utils-tool": "workspace:*" + "@vtrbo/utils-tool": "workspace:*", + "@vtrbo/utils-tree": "workspace:*" }, "devDependencies": { "@antfu/eslint-config": "1.0.0-beta.26", diff --git a/packages/core/index.ts b/packages/core/index.ts index f23fac1..d26445b 100644 --- a/packages/core/index.ts +++ b/packages/core/index.ts @@ -5,3 +5,4 @@ export * from '@vtrbo/utils-obj' export * from '@vtrbo/utils-arr' export * from '@vtrbo/utils-str' export * from '@vtrbo/utils-color' +export * from '@vtrbo/utils-tree' diff --git a/packages/tree/index.ts b/packages/tree/index.ts new file mode 100644 index 0000000..b5d4fa2 --- /dev/null +++ b/packages/tree/index.ts @@ -0,0 +1 @@ +export * from './src/tree' diff --git a/packages/tree/package.json b/packages/tree/package.json new file mode 100644 index 0000000..d22fee9 --- /dev/null +++ b/packages/tree/package.json @@ -0,0 +1,56 @@ +{ + "name": "@vtrbo/utils-tree", + "type": "module", + "version": "0.4.0-beta.4", + "description": "Collection of common JavaScript or TypeScript utils.", + "author": { + "name": "Victor Bo", + "email": "hi@vtrbo.cn" + }, + "license": "MIT", + "homepage": "https://github.com/vtrbo", + "bugs": "https://github.com/vtrbo/utils/issues", + "keywords": [ + "typescript", + "javascript", + "utils", + "vue", + "react", + "svelte", + "vite" + ], + "exports": { + ".": { + "types": "./index.d.ts", + "import": "./index.js", + "require": "./index.cjs" + } + }, + "main": "./index.js", + "module": "./index.js", + "types": "./index.d.ts", + "typesVersions": { + "*": { + "*": [ + "./*", + "./index.d.ts" + ] + } + }, + "files": [ + "README.md", + "index.cjs", + "index.d.cts", + "index.d.ts", + "index.js" + ], + "scripts": { + "build": "tsup", + "clean": "pnpm clean:dist && pnpm clean:deps", + "clean:dist": "rimraf dist", + "clean:deps": "rimraf node_modules" + }, + "dependencies": { + "@vtrbo/utils-tool": "workspace:*" + } +} diff --git a/packages/tree/src/tree.ts b/packages/tree/src/tree.ts new file mode 100644 index 0000000..249bc4b --- /dev/null +++ b/packages/tree/src/tree.ts @@ -0,0 +1,106 @@ +export function treeToList(tree: T[], options?: { + children?: string +}): T[] { + const tOption = Object.assign({ + children: 'children', + }, options || {}) + + const { children } = tOption + + const list: T[] = [...tree] + for (let i = 0; i < list.length; i++) { + const node: T = list[i] + if (!(node as any)[children]) + continue + list.splice(i + 1, 0, ...(treeToList((node as any)[children]) as any)) + } + + return list +} + +export function treeFilter(tree: T[], callback: (node: T) => boolean, options?: { + children?: string +}): T[] { + const tOption = Object.assign({ + children: 'children', + }, options || {}) + + const { children } = tOption + + return tree.map(node => ({ ...node })).filter((node) => { + if (callback(node)) + return node + + if ((node as any)[children] && Array.isArray((node as any)[children]) && (node as any)[children].length) + (node as any)[children] = treeFilter((node as any)[children], callback, tOption) + else + (node as any)[children] = [] + + return callback(node) || (node as any)[children].length + }) +} + +export function findPaths(tree: T[], callback: (node: T) => boolean, options?: { + children?: string + findAll?: boolean +}): Array { + const tOption = Object.assign({ + children: 'children', + findAll: false, + }, options || {}) + + const { children, findAll } = tOption + + const list: T[] = [...tree] + const path: T[] = [] + const paths: Array = [] + const records: Set = new Set() + + while (list.length) { + const node: T = list[0] + if (records.has(node)) { + path.pop() + list.shift() + } + else { + records.add(node); + (node as any)[children] && list.unshift(...(node as any)[children]) + path.push(node) + if (callback(node)) { + paths.push([...path]) + if (!findAll) + break + } + } + } + + return paths +} + +export function findNodes(tree: T[], callback: (node: T) => boolean, options?: { + children?: string + findAll?: boolean +}): T[] { + const tOption = Object.assign({ + children: 'children', + findAll: false, + }, options || {}) + + const { children, findAll } = tOption + + const list: T[] = [...tree] + const nodes: T[] = [] + + for (const node of list) { + if (callback(node)) { + nodes.push(node) + if (!findAll) + break + } + + if ((node as any)[children] && Array.isArray((node as any)[children]) && (node as any)[children].length) + list.push(...(node as any)[children]) + } + + return nodes +} diff --git a/packages/tree/tsup.config.ts b/packages/tree/tsup.config.ts new file mode 100644 index 0000000..e2bc6d0 --- /dev/null +++ b/packages/tree/tsup.config.ts @@ -0,0 +1,9 @@ +import { defineConfig } from 'tsup' + +export default defineConfig({ + entry: ['index.ts'], + format: ['cjs', 'esm'], + dts: true, + clean: true, + splitting: true, +}) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7a04589..33bc7c7 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -29,6 +29,9 @@ importers: '@vtrbo/utils-tool': specifier: workspace:* version: link:packages/tool + '@vtrbo/utils-tree': + specifier: workspace:* + version: link:packages/tree devDependencies: '@antfu/eslint-config': specifier: 1.0.0-beta.26 @@ -135,6 +138,12 @@ importers: packages/tool: {} + packages/tree: + dependencies: + '@vtrbo/utils-tool': + specifier: workspace:* + version: link:../tool + playground: devDependencies: '@vitejs/plugin-vue':