folder-generator 1.3.9 → 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 +6 -12
- package/lib/generator.js +102 -19
- package/package.json +1 -1
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
|
|
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
|
|
55
|
-
} catch (
|
|
56
|
-
console.error(chalk.red('\n✖ Error
|
|
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,25 +2,46 @@ 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: [] };
|
|
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 whitespace
|
|
12
30
|
const depth = (line.match(/^[ │├└─]*/)[0].length) / 4;
|
|
13
|
-
const name = line.replace(/^[ │├└─]*/, '').trim();
|
|
14
31
|
|
|
32
|
+
let name = line.replace(/^[ │├└─]*/, '').split('//')[0].trim();
|
|
15
33
|
if (!name) continue;
|
|
16
34
|
|
|
17
|
-
|
|
35
|
+
const isDirectory = name.endsWith('/');
|
|
36
|
+
if (isDirectory) name = name.slice(0, -1);
|
|
37
|
+
|
|
18
38
|
while (depth <= stack[stack.length - 1].depth) {
|
|
19
39
|
stack.pop();
|
|
20
40
|
}
|
|
21
41
|
|
|
22
42
|
const parent = stack[stack.length - 1].node;
|
|
23
|
-
const newNode = { name, children: [] };
|
|
43
|
+
const newNode = { name, children: [], isDirectory };
|
|
44
|
+
|
|
24
45
|
parent.children.push(newNode);
|
|
25
46
|
stack.push({ node: newNode, depth });
|
|
26
47
|
}
|
|
@@ -28,26 +49,88 @@ function parseStructure(text) {
|
|
|
28
49
|
return root;
|
|
29
50
|
}
|
|
30
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
|
+
|
|
106
|
+
return root;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* ======================
|
|
112
|
+
* FILE CREATION (OLD)
|
|
113
|
+
* ======================
|
|
114
|
+
*/
|
|
31
115
|
function createFiles(node, currentPath = '.') {
|
|
32
116
|
if (!node) return;
|
|
33
117
|
|
|
34
|
-
const fullPath = path.join(currentPath, node.name);
|
|
35
|
-
|
|
36
|
-
if (node.name
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
118
|
+
const fullPath = node.name ? path.join(currentPath, node.name) : currentPath;
|
|
119
|
+
|
|
120
|
+
if (node.name) {
|
|
121
|
+
if (node.isDirectory) {
|
|
122
|
+
fs.mkdirSync(fullPath, { recursive: true });
|
|
123
|
+
console.log(chalk.blue(`✓ Created directory: ${fullPath}`));
|
|
124
|
+
} else {
|
|
125
|
+
fs.mkdirSync(path.dirname(fullPath), { recursive: true });
|
|
126
|
+
fs.writeFileSync(fullPath, '');
|
|
127
|
+
console.log(chalk.green(`✓ Created file: ${fullPath}`));
|
|
128
|
+
}
|
|
45
129
|
}
|
|
46
130
|
|
|
47
|
-
// Process children
|
|
48
131
|
node.children.forEach(child => {
|
|
49
|
-
createFiles(child,
|
|
132
|
+
createFiles(child, fullPath);
|
|
50
133
|
});
|
|
51
134
|
}
|
|
52
135
|
|
|
53
|
-
module.exports = { parseStructure, createFiles };
|
|
136
|
+
module.exports = { parseStructure, createFiles };
|