folder-generator 2.0.0 → 3.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.
package/bin/cli.js CHANGED
@@ -1,6 +1,5 @@
1
- #!/usr/bin/env node
1
+ #!/usr/bin/env node
2
2
  const fs = require('fs');
3
- const path = require('path');
4
3
  const chalk = require('chalk');
5
4
  const { parseStructure, createFiles } = require('../lib/generator');
6
5
  const yargs = require('yargs/yargs');
@@ -27,23 +26,18 @@ async function main() {
27
26
  if (argv.file) {
28
27
  try {
29
28
  input = fs.readFileSync(argv.file, 'utf8');
30
- } catch (err) {
29
+ } catch {
31
30
  console.error(chalk.red(`Error reading file: ${argv.file}`));
32
31
  process.exit(1);
33
32
  }
34
33
  } else if (argv.input) {
35
34
  input = argv.input;
36
35
  } else if (!process.stdin.isTTY) {
37
- // Read from stdin if piped
38
36
  const chunks = [];
39
37
  for await (const chunk of process.stdin) chunks.push(chunk);
40
38
  input = Buffer.concat(chunks).toString('utf8');
41
39
  } else {
42
40
  console.error(chalk.red('Error: No input provided'));
43
- console.log(chalk.yellow('Usage:'));
44
- console.log(chalk.yellow(' foldgen --input "your/structure"'));
45
- console.log(chalk.yellow(' foldgen --file structure.txt'));
46
- console.log(chalk.yellow(' echo "structure" | foldgen'));
47
41
  process.exit(1);
48
42
  }
49
43
 
@@ -51,11 +45,11 @@ async function main() {
51
45
  console.log(chalk.yellow('\nParsing structure...'));
52
46
  const structure = parseStructure(input);
53
47
  createFiles(structure);
54
- console.log(chalk.bold.green('\n✔ Folder structure created successfully!'));
55
- } catch (error) {
56
- console.error(chalk.red('\n✖ Error creating structure:'), error.message);
48
+ console.log(chalk.green.bold('\n✔ Folder structure created successfully!\n'));
49
+ } catch (err) {
50
+ console.error(chalk.red('\n✖ Error:'), err.message);
57
51
  process.exit(1);
58
52
  }
59
53
  }
60
54
 
61
- main();
55
+ main();
package/lib/generator.js CHANGED
@@ -2,64 +2,135 @@ const fs = require('fs');
2
2
  const path = require('path');
3
3
  const chalk = require('chalk');
4
4
 
5
+ /**
6
+ * Entry point parser
7
+ * Automatically detects tree-format vs indented-path format
8
+ */
5
9
  function parseStructure(text) {
10
+ if (text.includes('├──') || text.includes('└──')) {
11
+ return parseTreeFormat(text);
12
+ }
13
+ return parseIndentedPathFormat(text);
14
+ }
15
+
16
+ /**
17
+ * =========================
18
+ * TREE FORMAT PARSER (OLD)
19
+ * =========================
20
+ * Supports:
21
+ * ├── backend/
22
+ * │ └── main.go
23
+ */
24
+ function parseTreeFormat(text) {
6
25
  const lines = text.split('\n').filter(line => line.trim());
7
- const root = { name: '', children: [], isDirectory: true }; // Root is always a directory
26
+ const root = { name: '', children: [], isDirectory: true };
8
27
  let stack = [{ node: root, depth: -1 }];
9
28
 
10
29
  for (const line of lines) {
11
- // Calculate depth based on leading tree characters
12
30
  const depth = (line.match(/^[ │├└─]*/)[0].length) / 4;
13
31
 
14
- // Extract the name, remove comments (using //), and trim whitespace
15
32
  let name = line.replace(/^[ │├└─]*/, '').split('//')[0].trim();
16
33
  if (!name) continue;
17
34
 
18
- // A name ending with '/' is a directory
19
35
  const isDirectory = name.endsWith('/');
20
- if (isDirectory) {
21
- name = name.slice(0, -1); // Remove the trailing '/' from the name
22
- }
36
+ if (isDirectory) name = name.slice(0, -1);
23
37
 
24
- // Find the correct parent in the stack based on depth
25
38
  while (depth <= stack[stack.length - 1].depth) {
26
39
  stack.pop();
27
40
  }
28
41
 
29
42
  const parent = stack[stack.length - 1].node;
30
43
  const newNode = { name, children: [], isDirectory };
44
+
31
45
  parent.children.push(newNode);
32
46
  stack.push({ node: newNode, depth });
33
47
  }
48
+
49
+ return root;
50
+ }
51
+
52
+ /**
53
+ * =====================================
54
+ * INDENTED + PATH FORMAT PARSER (NEW)
55
+ * =====================================
56
+ * Supports:
57
+ *
58
+ * backend/
59
+ * cmd/server/main.go
60
+ * internal/config/config.go
61
+ */
62
+ function parseIndentedPathFormat(text) {
63
+ const lines = text.split('\n').filter(line => line.trim());
64
+ const root = { name: '', children: [], isDirectory: true };
65
+ const stack = [{ node: root, indent: -1 }];
66
+
67
+ for (const line of lines) {
68
+ const indent = line.match(/^\s*/)[0].length;
69
+ const raw = line.trim();
70
+ const isExplicitDir = raw.endsWith('/');
71
+
72
+ const trimmed = raw.replace(/\/$/, '');
73
+
74
+ while (stack.length && indent <= stack[stack.length - 1].indent) {
75
+ stack.pop();
76
+ }
77
+
78
+ let parent = stack[stack.length - 1].node;
79
+ const parts = trimmed.split('/');
80
+
81
+ parts.forEach((part, index) => {
82
+ const isLast = index === parts.length - 1;
83
+
84
+ // ✅ FIX: directory only if NOT last OR explicitly marked
85
+ const isDirectory = !isLast || isExplicitDir;
86
+
87
+ let existing = parent.children.find(c => c.name === part);
88
+ if (!existing) {
89
+ existing = {
90
+ name: part,
91
+ children: [],
92
+ isDirectory
93
+ };
94
+ parent.children.push(existing);
95
+ }
96
+
97
+ parent = existing;
98
+ });
99
+
100
+ // Push only real directories
101
+ if (isExplicitDir) {
102
+ stack.push({ node: parent, indent });
103
+ }
104
+ }
105
+
34
106
  return root;
35
107
  }
36
108
 
37
109
 
110
+ /**
111
+ * ======================
112
+ * FILE CREATION (OLD)
113
+ * ======================
114
+ */
38
115
  function createFiles(node, currentPath = '.') {
39
116
  if (!node) return;
40
117
 
41
- // The root node has an empty name and represents the starting path.
42
118
  const fullPath = node.name ? path.join(currentPath, node.name) : currentPath;
43
119
 
44
- // Process only nodes with names (skips the initial root container)
45
120
  if (node.name) {
46
121
  if (node.isDirectory) {
47
- // It's a directory
48
122
  fs.mkdirSync(fullPath, { recursive: true });
49
123
  console.log(chalk.blue(`✓ Created directory: ${fullPath}`));
50
124
  } else {
51
- // It's a file
52
- // Ensure parent directory exists before creating the file.
53
125
  fs.mkdirSync(path.dirname(fullPath), { recursive: true });
54
126
  fs.writeFileSync(fullPath, '');
55
127
  console.log(chalk.green(`✓ Created file: ${fullPath}`));
56
128
  }
57
129
  }
58
130
 
59
- // Process children recursively, passing the new parent path
60
131
  node.children.forEach(child => {
61
132
  createFiles(child, fullPath);
62
133
  });
63
134
  }
64
135
 
65
- module.exports = { parseStructure, createFiles };
136
+ module.exports = { parseStructure, createFiles };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "folder-generator",
3
- "version": "2.0.0",
3
+ "version": "3.0.0",
4
4
  "description": "CLI tool to generate folder structures from text input",
5
5
  "bin": {
6
6
  "foldgen": "./bin/cli.js"