make-folder-txt 1.0.5 → 1.1.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/README.md CHANGED
@@ -59,6 +59,14 @@ make-folder-txt --ignore-folder examples extensions docs --ignore-file LICENSE
59
59
  make-folder-txt --ignore-file .env .env.local secrets.txt
60
60
  ```
61
61
 
62
+ Include only specific folders/files by name (everything else is ignored):
63
+
64
+ ```bash
65
+ make-folder-txt --only-folder src docs
66
+ make-folder-txt --only-file package.json README.md
67
+ make-folder-txt --only-folder src --only-file package.json
68
+ ```
69
+
62
70
  ---
63
71
 
64
72
  ## šŸŽÆ Real World Examples
@@ -19,12 +19,28 @@ const BINARY_EXTS = new Set([
19
19
 
20
20
  // ── helpers ───────────────────────────────────────────────────────────────────
21
21
 
22
- function collectFiles(dir, rootDir, ignoreDirs, ignoreFiles, indent = "", lines = [], filePaths = []) {
22
+ function collectFiles(
23
+ dir,
24
+ rootDir,
25
+ ignoreDirs,
26
+ ignoreFiles,
27
+ onlyFolders,
28
+ onlyFiles,
29
+ options = {},
30
+ ) {
31
+ const {
32
+ indent = "",
33
+ lines = [],
34
+ filePaths = [],
35
+ inSelectedFolder = false,
36
+ hasOnlyFilters = false,
37
+ } = options;
38
+
23
39
  let entries;
24
40
  try {
25
41
  entries = fs.readdirSync(dir, { withFileTypes: true });
26
42
  } catch {
27
- return { lines, filePaths };
43
+ return { lines, filePaths, hasIncluded: false };
28
44
  }
29
45
 
30
46
  entries.sort((a, b) => {
@@ -39,20 +55,53 @@ function collectFiles(dir, rootDir, ignoreDirs, ignoreFiles, indent = "", lines
39
55
 
40
56
  if (entry.isDirectory()) {
41
57
  if (ignoreDirs.has(entry.name)) {
42
- lines.push(`${indent}${connector}${entry.name}/ [skipped]`);
58
+ if (!hasOnlyFilters) {
59
+ lines.push(`${indent}${connector}${entry.name}/ [skipped]`);
60
+ }
43
61
  return;
44
62
  }
45
- lines.push(`${indent}${connector}${entry.name}/`);
46
- collectFiles(path.join(dir, entry.name), rootDir, ignoreDirs, ignoreFiles, childIndent, lines, filePaths);
63
+
64
+ const childPath = path.join(dir, entry.name);
65
+ const childInSelectedFolder = inSelectedFolder || onlyFolders.has(entry.name);
66
+ const childLines = [];
67
+ const childFiles = [];
68
+ const child = collectFiles(
69
+ childPath,
70
+ rootDir,
71
+ ignoreDirs,
72
+ ignoreFiles,
73
+ onlyFolders,
74
+ onlyFiles,
75
+ {
76
+ indent: childIndent,
77
+ lines: childLines,
78
+ filePaths: childFiles,
79
+ inSelectedFolder: childInSelectedFolder,
80
+ hasOnlyFilters,
81
+ },
82
+ );
83
+
84
+ const explicitlySelectedFolder = hasOnlyFilters && onlyFolders.has(entry.name);
85
+ const shouldIncludeDir = !hasOnlyFilters || child.hasIncluded || explicitlySelectedFolder;
86
+
87
+ if (shouldIncludeDir) {
88
+ lines.push(`${indent}${connector}${entry.name}/`);
89
+ lines.push(...child.lines);
90
+ filePaths.push(...child.filePaths);
91
+ }
47
92
  } else {
48
93
  if (ignoreFiles.has(entry.name)) return;
94
+
95
+ const shouldIncludeFile = !hasOnlyFilters || inSelectedFolder || onlyFiles.has(entry.name);
96
+ if (!shouldIncludeFile) return;
97
+
49
98
  lines.push(`${indent}${connector}${entry.name}`);
50
99
  const relPath = "/" + path.relative(rootDir, path.join(dir, entry.name)).split(path.sep).join("/");
51
100
  filePaths.push({ abs: path.join(dir, entry.name), rel: relPath });
52
101
  }
53
102
  });
54
103
 
55
- return { lines, filePaths };
104
+ return { lines, filePaths, hasIncluded: filePaths.length > 0 || lines.length > 0 };
56
105
  }
57
106
 
58
107
  function readContent(absPath) {
@@ -81,6 +130,8 @@ if (args.includes("-v") || args.includes("--version")) {
81
130
 
82
131
  const ignoreDirs = new Set(IGNORE_DIRS);
83
132
  const ignoreFiles = new Set(IGNORE_FILES);
133
+ const onlyFolders = new Set();
134
+ const onlyFiles = new Set();
84
135
  let outputArg = null;
85
136
 
86
137
  for (let i = 0; i < args.length; i += 1) {
@@ -134,6 +185,54 @@ for (let i = 0; i < args.length; i += 1) {
134
185
  continue;
135
186
  }
136
187
 
188
+ if (arg === "--only-folder") {
189
+ let consumed = 0;
190
+ while (i + 1 < args.length && !args[i + 1].startsWith("-")) {
191
+ onlyFolders.add(args[i + 1]);
192
+ i += 1;
193
+ consumed += 1;
194
+ }
195
+ if (consumed === 0) {
196
+ console.error("Error: --only-folder requires at least one folder name.");
197
+ process.exit(1);
198
+ }
199
+ continue;
200
+ }
201
+
202
+ if (arg.startsWith("--only-folder=")) {
203
+ const value = arg.slice("--only-folder=".length);
204
+ if (!value) {
205
+ console.error("Error: --only-folder requires a folder name.");
206
+ process.exit(1);
207
+ }
208
+ onlyFolders.add(value);
209
+ continue;
210
+ }
211
+
212
+ if (arg === "--only-file") {
213
+ let consumed = 0;
214
+ while (i + 1 < args.length && !args[i + 1].startsWith("-")) {
215
+ onlyFiles.add(args[i + 1]);
216
+ i += 1;
217
+ consumed += 1;
218
+ }
219
+ if (consumed === 0) {
220
+ console.error("Error: --only-file requires at least one file name.");
221
+ process.exit(1);
222
+ }
223
+ continue;
224
+ }
225
+
226
+ if (arg.startsWith("--only-file=")) {
227
+ const value = arg.slice("--only-file=".length);
228
+ if (!value) {
229
+ console.error("Error: --only-file requires a file name.");
230
+ process.exit(1);
231
+ }
232
+ onlyFiles.add(value);
233
+ continue;
234
+ }
235
+
137
236
  if (arg.startsWith("-")) {
138
237
  console.error(`Error: Unknown option "${arg}".`);
139
238
  process.exit(1);
@@ -158,7 +257,16 @@ const outputFile = outputArg
158
257
 
159
258
  console.log(`\nšŸ“‚ Scanning: ${folderPath}`);
160
259
 
161
- const { lines: treeLines, filePaths } = collectFiles(folderPath, folderPath, ignoreDirs, ignoreFiles);
260
+ const hasOnlyFilters = onlyFolders.size > 0 || onlyFiles.size > 0;
261
+ const { lines: treeLines, filePaths } = collectFiles(
262
+ folderPath,
263
+ folderPath,
264
+ ignoreDirs,
265
+ ignoreFiles,
266
+ onlyFolders,
267
+ onlyFiles,
268
+ { hasOnlyFilters },
269
+ );
162
270
 
163
271
  // ── build output ──────────────────────────────────────────────────────────────
164
272
  const out = [];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "make-folder-txt",
3
- "version": "1.0.5",
3
+ "version": "1.1.0",
4
4
  "description": "Generate a single .txt file containing the full folder structure and file contents of any project, ignoring node_modules and other junk.",
5
5
  "main": "bin/make-folder-txt.js",
6
6
  "bin": {