treeviz-cli 1.0.0

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.
Files changed (3) hide show
  1. package/README.md +47 -0
  2. package/dist/index.js +182 -0
  3. package/package.json +35 -0
package/README.md ADDED
@@ -0,0 +1,47 @@
1
+ # @treeviz/cli
2
+
3
+ Generate ASCII directory trees from the terminal. Zero dependencies, powered by Bun.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ bun add -g @treeviz/cli
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```bash
14
+ # Current directory
15
+ treeviz
16
+
17
+ # Specific path
18
+ treeviz ./src
19
+
20
+ # Add custom ignores
21
+ treeviz --ignore .env,coverage
22
+
23
+ # Disable default ignores
24
+ treeviz --no-default-ignores
25
+
26
+ # Copy output to clipboard
27
+ treeviz --copy
28
+ ```
29
+
30
+ ## Options
31
+
32
+ | Option | Alias | Description |
33
+ |--------|-------|-------------|
34
+ | `[path]` | | Directory to visualize (default: `.`) |
35
+ | `--ignore <folders>` | `-i` | Comma-separated folders to add to ignore list |
36
+ | `--no-default-ignores` | | Disable the default ignore list |
37
+ | `--copy` | `-c` | Copy output to clipboard |
38
+ | `--help` | `-h` | Show help |
39
+ | `--version` | `-v` | Show version |
40
+
41
+ ## Default Ignores
42
+
43
+ `node_modules`, `.git`, `.next`, `.husky`, `.turbo`, `dist`, `build`, `.DS_Store`
44
+
45
+ ## Web Version
46
+
47
+ Try the browser-based version at [treeviz.dev](https://treeviz.dev) — select a folder and get the same output with zero uploads.
package/dist/index.js ADDED
@@ -0,0 +1,182 @@
1
+ #!/usr/bin/env bun
2
+ // @bun
3
+
4
+ // src/index.ts
5
+ import { existsSync, statSync } from "fs";
6
+ import { resolve } from "path";
7
+
8
+ // src/tree-generator.ts
9
+ import { readdirSync } from "fs";
10
+ import { join, basename } from "path";
11
+ var DEFAULT_IGNORES = [
12
+ "node_modules",
13
+ ".git",
14
+ ".next",
15
+ ".husky",
16
+ ".turbo",
17
+ "dist",
18
+ "build",
19
+ ".DS_Store"
20
+ ];
21
+ function traverseDirectory(dirPath, ignoreList = DEFAULT_IGNORES) {
22
+ const entries = readdirSync(dirPath, { withFileTypes: true });
23
+ const children = [];
24
+ for (const entry of entries) {
25
+ if (ignoreList.includes(entry.name))
26
+ continue;
27
+ if (entry.isDirectory()) {
28
+ const childNode = traverseDirectory(join(dirPath, entry.name), ignoreList);
29
+ children.push(childNode);
30
+ } else {
31
+ children.push({ name: entry.name, type: "file" });
32
+ }
33
+ }
34
+ children.sort((a, b) => {
35
+ if (a.type !== b.type)
36
+ return a.type === "directory" ? -1 : 1;
37
+ return a.name.localeCompare(b.name);
38
+ });
39
+ return {
40
+ name: basename(dirPath),
41
+ type: "directory",
42
+ children
43
+ };
44
+ }
45
+ function generateAsciiTree(node, prefix = "", isRoot = true) {
46
+ let result = "";
47
+ if (isRoot) {
48
+ result += node.name + `/
49
+ `;
50
+ }
51
+ const children = node.children ?? [];
52
+ children.forEach((child, index) => {
53
+ const isLast = index === children.length - 1;
54
+ const connector = isLast ? "\u2514\u2500\u2500 " : "\u251C\u2500\u2500 ";
55
+ const childPrefix = isLast ? " " : "\u2502 ";
56
+ const suffix = child.type === "directory" ? "/" : "";
57
+ result += prefix + connector + child.name + suffix + `
58
+ `;
59
+ if (child.type === "directory" && child.children?.length) {
60
+ result += generateAsciiTree(child, prefix + childPrefix, false);
61
+ }
62
+ });
63
+ return result;
64
+ }
65
+
66
+ // src/index.ts
67
+ var VERSION = "1.0.0";
68
+ var HELP = `
69
+ treeviz - Generate ASCII directory trees
70
+
71
+ Usage:
72
+ treeviz [path] [options]
73
+
74
+ Arguments:
75
+ path Directory to visualize (default: current directory)
76
+
77
+ Options:
78
+ -i, --ignore <folders> Comma-separated folders to ignore (added to defaults)
79
+ --no-default-ignores Disable the default ignore list
80
+ -c, --copy Copy output to clipboard
81
+ -h, --help Show this help message
82
+ -v, --version Show version
83
+
84
+ Default ignores:
85
+ ${DEFAULT_IGNORES.join(", ")}
86
+
87
+ Examples:
88
+ treeviz
89
+ treeviz ./src
90
+ treeviz --ignore .env,coverage
91
+ treeviz --no-default-ignores
92
+ treeviz --copy
93
+ `.trim();
94
+ function parseArgs(argv) {
95
+ const args = argv.slice(2);
96
+ let targetPath = ".";
97
+ let extraIgnores = [];
98
+ let useDefaultIgnores = true;
99
+ let copyToClipboard = false;
100
+ for (let i = 0;i < args.length; i++) {
101
+ const arg = args[i];
102
+ if (arg === "-h" || arg === "--help") {
103
+ console.log(HELP);
104
+ process.exit(0);
105
+ }
106
+ if (arg === "-v" || arg === "--version") {
107
+ console.log(`treeviz v${VERSION}`);
108
+ process.exit(0);
109
+ }
110
+ if (arg === "--no-default-ignores") {
111
+ useDefaultIgnores = false;
112
+ continue;
113
+ }
114
+ if (arg === "-c" || arg === "--copy") {
115
+ copyToClipboard = true;
116
+ continue;
117
+ }
118
+ if (arg === "-i" || arg === "--ignore") {
119
+ const next = args[++i];
120
+ if (!next) {
121
+ console.error("Error: --ignore requires a value");
122
+ process.exit(1);
123
+ }
124
+ extraIgnores = next.split(",").map((s) => s.trim());
125
+ continue;
126
+ }
127
+ if (!arg.startsWith("-")) {
128
+ targetPath = arg;
129
+ continue;
130
+ }
131
+ console.error(`Unknown option: ${arg}`);
132
+ console.error('Run "treeviz --help" for usage');
133
+ process.exit(1);
134
+ }
135
+ return { targetPath, extraIgnores, useDefaultIgnores, copyToClipboard };
136
+ }
137
+ async function main() {
138
+ const { targetPath, extraIgnores, useDefaultIgnores, copyToClipboard } = parseArgs(process.argv);
139
+ const fullPath = resolve(targetPath);
140
+ if (!existsSync(fullPath)) {
141
+ console.error(`Error: Path does not exist: ${fullPath}`);
142
+ process.exit(1);
143
+ }
144
+ if (!statSync(fullPath).isDirectory()) {
145
+ console.error(`Error: Not a directory: ${fullPath}`);
146
+ process.exit(1);
147
+ }
148
+ const ignoreList = [
149
+ ...useDefaultIgnores ? DEFAULT_IGNORES : [],
150
+ ...extraIgnores
151
+ ];
152
+ const tree = traverseDirectory(fullPath, ignoreList);
153
+ const output = generateAsciiTree(tree);
154
+ console.log(output);
155
+ if (copyToClipboard) {
156
+ try {
157
+ const proc = Bun.spawn(["pbcopy"], {
158
+ stdin: "pipe"
159
+ });
160
+ proc.stdin.write(output);
161
+ proc.stdin.end();
162
+ await proc.exited;
163
+ console.log(`
164
+ \u2713 Copied to clipboard`);
165
+ } catch {
166
+ try {
167
+ const proc = Bun.spawn(["xclip", "-selection", "clipboard"], {
168
+ stdin: "pipe"
169
+ });
170
+ proc.stdin.write(output);
171
+ proc.stdin.end();
172
+ await proc.exited;
173
+ console.log(`
174
+ \u2713 Copied to clipboard`);
175
+ } catch {
176
+ console.error(`
177
+ \u2717 Could not copy to clipboard (pbcopy/xclip not found)`);
178
+ }
179
+ }
180
+ }
181
+ }
182
+ main();
package/package.json ADDED
@@ -0,0 +1,35 @@
1
+ {
2
+ "name": "treeviz-cli",
3
+ "version": "1.0.0",
4
+ "description": "Generate ASCII directory trees from the terminal",
5
+ "type": "module",
6
+ "bin": {
7
+ "treeviz": "./dist/index.js"
8
+ },
9
+ "scripts": {
10
+ "dev": "bun run src/index.ts",
11
+ "build": "bun build ./src/index.ts --outdir ./dist --target bun"
12
+ },
13
+ "files": [
14
+ "dist"
15
+ ],
16
+ "keywords": [
17
+ "tree",
18
+ "directory",
19
+ "ascii",
20
+ "cli",
21
+ "file-tree"
22
+ ],
23
+ "license": "MIT",
24
+ "repository": {
25
+ "type": "git",
26
+ "url": "https://github.com/bireycikan/treeviz-cli"
27
+ },
28
+ "homepage": "https://github.com/bireycikan/treeviz-cli#readme",
29
+ "bugs": {
30
+ "url": "https://github.com/bireycikan/treeviz-cli/issues"
31
+ },
32
+ "devDependencies": {
33
+ "bun-types": "^1.3.8"
34
+ }
35
+ }