make-folder-txt 2.2.6 → 2.2.7

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.
@@ -87,6 +87,7 @@ function collectFiles(
87
87
  rootName = "",
88
88
  txtIgnore = new Set(),
89
89
  force = false,
90
+ rootOnlyInclude = false,
90
91
  } = options;
91
92
 
92
93
  let entries;
@@ -129,27 +130,36 @@ function collectFiles(
129
130
  const childInSelectedFolder = inSelectedFolder || onlyFolders.has(entry.name);
130
131
  const childLines = [];
131
132
  const childFiles = [];
132
- const child = collectFiles(
133
- childPath,
134
- rootDir,
135
- ignoreDirs,
136
- ignoreFiles,
137
- onlyFolders,
138
- onlyFiles,
139
- {
140
- indent: childIndent,
141
- lines: childLines,
142
- filePaths: childFiles,
143
- inSelectedFolder: childInSelectedFolder,
144
- hasOnlyFilters,
145
- rootName,
146
- txtIgnore,
147
- force,
148
- },
149
- );
133
+
134
+ // If rootOnlyInclude is true, only include root-level items
135
+ let child;
136
+ if (rootOnlyInclude && dir !== rootDir) {
137
+ // Don't recurse into subdirectories when rootOnlyInclude is true
138
+ child = { lines: [], filePaths: [], hasIncluded: false };
139
+ } else {
140
+ child = collectFiles(
141
+ childPath,
142
+ rootDir,
143
+ ignoreDirs,
144
+ ignoreFiles,
145
+ onlyFolders,
146
+ onlyFiles,
147
+ {
148
+ indent: childIndent,
149
+ lines: childLines,
150
+ filePaths: childFiles,
151
+ inSelectedFolder: childInSelectedFolder,
152
+ hasOnlyFilters,
153
+ rootName,
154
+ txtIgnore,
155
+ force,
156
+ rootOnlyInclude,
157
+ },
158
+ );
159
+ }
150
160
 
151
161
  const explicitlySelectedFolder = hasOnlyFilters && onlyFolders.has(entry.name);
152
- const shouldIncludeDir = !hasOnlyFilters || child.hasIncluded || explicitlySelectedFolder;
162
+ const shouldIncludeDir = !hasOnlyFilters || (rootOnlyInclude ? false : child.hasIncluded) || explicitlySelectedFolder;
153
163
 
154
164
  if (shouldIncludeDir) {
155
165
  lines.push(`${indent}${connector}${entry.name}/`);
@@ -170,7 +180,12 @@ function collectFiles(
170
180
  // Ignore .txt files that match the folder name (e.g., foldername.txt) unless force is enabled
171
181
  if (!force && entry.name.endsWith('.txt') && entry.name === `${rootName}.txt`) return;
172
182
 
173
- const shouldIncludeFile = !hasOnlyFilters || inSelectedFolder || onlyFiles.has(entry.name);
183
+ // Check if this file matches any of the onlyFiles patterns
184
+ const shouldIncludeFile = !hasOnlyFilters || inSelectedFolder ||
185
+ onlyFiles.has(entry.name) ||
186
+ onlyFiles.has(relPathForIgnore) ||
187
+ onlyFiles.has(`/${relPathForIgnore}`);
188
+
174
189
  if (!shouldIncludeFile) return;
175
190
 
176
191
  lines.push(`${indent}${connector}${entry.name}`);
@@ -816,6 +831,7 @@ Dump an entire project folder into a single readable .txt file.
816
831
  let noSkipFlag = false;
817
832
  let splitMethod = null; // 'folder', 'file', 'size'
818
833
  let splitSize = null; // size in bytes
834
+ let rootOnlyInclude = false; // For /include flag
819
835
 
820
836
  for (let i = 0; i < args.length; i += 1) {
821
837
  const arg = args[i];
@@ -908,14 +924,21 @@ Dump an entire project folder into a single readable .txt file.
908
924
  if (arg === "--ignore-folder" || arg === "-ifo") {
909
925
  let consumed = 0;
910
926
  while (i + 1 < args.length && !args[i + 1].startsWith("-")) {
911
- // Normalize the folder name: remove backslashes, trailing slashes, and leading ./
912
927
  let folderName = args[i + 1];
913
- folderName = folderName.replace(/\\/g, '/'); // Convert backslashes to forward slashes
914
- folderName = folderName.replace(/^\.?\//, ''); // Remove leading ./ or /
915
- folderName = folderName.replace(/\/+$/, ''); // Remove trailing slashes
916
- ignoreDirs.add(folderName);
917
- i += 1;
918
- consumed += 1;
928
+
929
+ // Check for /folder syntax (root-only include)
930
+ if (folderName.startsWith("/")) {
931
+ const cleanFolderName = folderName.slice(1); // Remove leading /
932
+ onlyFolders.add(cleanFolderName);
933
+ rootOnlyInclude = true;
934
+ i += 1;
935
+ consumed += 1;
936
+ } else {
937
+ // Normal folder path (could be nested like folder/subfolder)
938
+ onlyFolders.add(folderName);
939
+ i += 1;
940
+ consumed += 1;
941
+ }
919
942
  }
920
943
  if (consumed === 0) {
921
944
  console.error("Error: --ignore-folder requires at least one folder name.");
@@ -932,12 +955,16 @@ Dump an entire project folder into a single readable .txt file.
932
955
  console.error("Error: --ignore-folder requires a folder name.");
933
956
  process.exit(1);
934
957
  }
935
- // Normalize the folder name
936
- let folderName = value;
937
- folderName = folderName.replace(/\\/g, '/'); // Convert backslashes to forward slashes
938
- folderName = folderName.replace(/^\.?\//, ''); // Remove leading ./ or /
939
- folderName = folderName.replace(/\/+$/, ''); // Remove trailing slashes
940
- ignoreDirs.add(folderName);
958
+
959
+ // Check for /folder syntax (root-only include)
960
+ if (value.startsWith("/")) {
961
+ const cleanFolderName = value.slice(1); // Remove leading /
962
+ onlyFolders.add(cleanFolderName);
963
+ rootOnlyInclude = true;
964
+ } else {
965
+ // Normal folder path (could be nested like folder/subfolder)
966
+ onlyFolders.add(value);
967
+ }
941
968
  continue;
942
969
  }
943
970
 
@@ -1006,9 +1033,21 @@ Dump an entire project folder into a single readable .txt file.
1006
1033
  if (arg === "--only-file" || arg === "-ofi") {
1007
1034
  let consumed = 0;
1008
1035
  while (i + 1 < args.length && !args[i + 1].startsWith("-")) {
1009
- onlyFiles.add(args[i + 1]);
1010
- i += 1;
1011
- consumed += 1;
1036
+ let fileName = args[i + 1];
1037
+
1038
+ // Check for /file syntax (root-only include)
1039
+ if (fileName.startsWith("/")) {
1040
+ const cleanFileName = fileName.slice(1); // Remove leading /
1041
+ onlyFiles.add(cleanFileName);
1042
+ rootOnlyInclude = true;
1043
+ i += 1;
1044
+ consumed += 1;
1045
+ } else {
1046
+ // Normal file path (could be nested like folder/file.ext)
1047
+ onlyFiles.add(fileName);
1048
+ i += 1;
1049
+ consumed += 1;
1050
+ }
1012
1051
  }
1013
1052
  if (consumed === 0) {
1014
1053
  console.error("Error: --only-file requires at least one file name.");
@@ -1025,7 +1064,16 @@ Dump an entire project folder into a single readable .txt file.
1025
1064
  console.error("Error: --only-file requires a file name.");
1026
1065
  process.exit(1);
1027
1066
  }
1028
- onlyFiles.add(value);
1067
+
1068
+ // Check for /file syntax (root-only include)
1069
+ if (value.startsWith("/")) {
1070
+ const cleanFileName = value.slice(1); // Remove leading /
1071
+ onlyFiles.add(cleanFileName);
1072
+ rootOnlyInclude = true;
1073
+ } else {
1074
+ // Normal file path (could be nested like folder/file.ext)
1075
+ onlyFiles.add(value);
1076
+ }
1029
1077
  continue;
1030
1078
  }
1031
1079
 
@@ -1065,7 +1113,8 @@ Dump an entire project folder into a single readable .txt file.
1065
1113
  rootName,
1066
1114
  txtIgnore,
1067
1115
  force: forceFlag,
1068
- hasOnlyFilters: onlyFolders.size > 0 || onlyFiles.size > 0
1116
+ hasOnlyFilters: onlyFolders.size > 0 || onlyFiles.size > 0,
1117
+ rootOnlyInclude
1069
1118
  }
1070
1119
  );
1071
1120
 
@@ -10,9 +10,8 @@ Root: C:\Programming\make-folder-txt
10
10
  make-folder-txt/
11
11
  ├── bin/
12
12
  │ └── make-folder-txt.js
13
- ├── package.json
14
13
 
15
- Total files: 2
14
+ Total files: 1
16
15
 
17
16
  ================================================================================
18
17
  FILE CONTENTS
@@ -110,6 +109,7 @@ function collectFiles(
110
109
  rootName = "",
111
110
  txtIgnore = new Set(),
112
111
  force = false,
112
+ rootOnlyInclude = false,
113
113
  } = options;
114
114
 
115
115
  let entries;
@@ -152,27 +152,36 @@ function collectFiles(
152
152
  const childInSelectedFolder = inSelectedFolder || onlyFolders.has(entry.name);
153
153
  const childLines = [];
154
154
  const childFiles = [];
155
- const child = collectFiles(
156
- childPath,
157
- rootDir,
158
- ignoreDirs,
159
- ignoreFiles,
160
- onlyFolders,
161
- onlyFiles,
162
- {
163
- indent: childIndent,
164
- lines: childLines,
165
- filePaths: childFiles,
166
- inSelectedFolder: childInSelectedFolder,
167
- hasOnlyFilters,
168
- rootName,
169
- txtIgnore,
170
- force,
171
- },
172
- );
155
+
156
+ // If rootOnlyInclude is true, only include root-level items
157
+ let child;
158
+ if (rootOnlyInclude && dir !== rootDir) {
159
+ // Don't recurse into subdirectories when rootOnlyInclude is true
160
+ child = { lines: [], filePaths: [], hasIncluded: false };
161
+ } else {
162
+ child = collectFiles(
163
+ childPath,
164
+ rootDir,
165
+ ignoreDirs,
166
+ ignoreFiles,
167
+ onlyFolders,
168
+ onlyFiles,
169
+ {
170
+ indent: childIndent,
171
+ lines: childLines,
172
+ filePaths: childFiles,
173
+ inSelectedFolder: childInSelectedFolder,
174
+ hasOnlyFilters,
175
+ rootName,
176
+ txtIgnore,
177
+ force,
178
+ rootOnlyInclude,
179
+ },
180
+ );
181
+ }
173
182
 
174
183
  const explicitlySelectedFolder = hasOnlyFilters && onlyFolders.has(entry.name);
175
- const shouldIncludeDir = !hasOnlyFilters || child.hasIncluded || explicitlySelectedFolder;
184
+ const shouldIncludeDir = !hasOnlyFilters || (rootOnlyInclude ? false : child.hasIncluded) || explicitlySelectedFolder;
176
185
 
177
186
  if (shouldIncludeDir) {
178
187
  lines.push(`${indent}${connector}${entry.name}/`);
@@ -193,7 +202,12 @@ function collectFiles(
193
202
  // Ignore .txt files that match the folder name (e.g., foldername.txt) unless force is enabled
194
203
  if (!force && entry.name.endsWith('.txt') && entry.name === `${rootName}.txt`) return;
195
204
 
196
- const shouldIncludeFile = !hasOnlyFilters || inSelectedFolder || onlyFiles.has(entry.name);
205
+ // Check if this file matches any of the onlyFiles patterns
206
+ const shouldIncludeFile = !hasOnlyFilters || inSelectedFolder ||
207
+ onlyFiles.has(entry.name) ||
208
+ onlyFiles.has(relPathForIgnore) ||
209
+ onlyFiles.has(`/${relPathForIgnore}`);
210
+
197
211
  if (!shouldIncludeFile) return;
198
212
 
199
213
  lines.push(`${indent}${connector}${entry.name}`);
@@ -839,6 +853,7 @@ Dump an entire project folder into a single readable .txt file.
839
853
  let noSkipFlag = false;
840
854
  let splitMethod = null; // 'folder', 'file', 'size'
841
855
  let splitSize = null; // size in bytes
856
+ let rootOnlyInclude = false; // For /include flag
842
857
 
843
858
  for (let i = 0; i < args.length; i += 1) {
844
859
  const arg = args[i];
@@ -931,14 +946,21 @@ Dump an entire project folder into a single readable .txt file.
931
946
  if (arg === "--ignore-folder" || arg === "-ifo") {
932
947
  let consumed = 0;
933
948
  while (i + 1 < args.length && !args[i + 1].startsWith("-")) {
934
- // Normalize the folder name: remove backslashes, trailing slashes, and leading ./
935
949
  let folderName = args[i + 1];
936
- folderName = folderName.replace(/\\/g, '/'); // Convert backslashes to forward slashes
937
- folderName = folderName.replace(/^\.?\//, ''); // Remove leading ./ or /
938
- folderName = folderName.replace(/\/+$/, ''); // Remove trailing slashes
939
- ignoreDirs.add(folderName);
940
- i += 1;
941
- consumed += 1;
950
+
951
+ // Check for /folder syntax (root-only include)
952
+ if (folderName.startsWith("/")) {
953
+ const cleanFolderName = folderName.slice(1); // Remove leading /
954
+ onlyFolders.add(cleanFolderName);
955
+ rootOnlyInclude = true;
956
+ i += 1;
957
+ consumed += 1;
958
+ } else {
959
+ // Normal folder path (could be nested like folder/subfolder)
960
+ onlyFolders.add(folderName);
961
+ i += 1;
962
+ consumed += 1;
963
+ }
942
964
  }
943
965
  if (consumed === 0) {
944
966
  console.error("Error: --ignore-folder requires at least one folder name.");
@@ -955,12 +977,16 @@ Dump an entire project folder into a single readable .txt file.
955
977
  console.error("Error: --ignore-folder requires a folder name.");
956
978
  process.exit(1);
957
979
  }
958
- // Normalize the folder name
959
- let folderName = value;
960
- folderName = folderName.replace(/\\/g, '/'); // Convert backslashes to forward slashes
961
- folderName = folderName.replace(/^\.?\//, ''); // Remove leading ./ or /
962
- folderName = folderName.replace(/\/+$/, ''); // Remove trailing slashes
963
- ignoreDirs.add(folderName);
980
+
981
+ // Check for /folder syntax (root-only include)
982
+ if (value.startsWith("/")) {
983
+ const cleanFolderName = value.slice(1); // Remove leading /
984
+ onlyFolders.add(cleanFolderName);
985
+ rootOnlyInclude = true;
986
+ } else {
987
+ // Normal folder path (could be nested like folder/subfolder)
988
+ onlyFolders.add(value);
989
+ }
964
990
  continue;
965
991
  }
966
992
 
@@ -1029,9 +1055,21 @@ Dump an entire project folder into a single readable .txt file.
1029
1055
  if (arg === "--only-file" || arg === "-ofi") {
1030
1056
  let consumed = 0;
1031
1057
  while (i + 1 < args.length && !args[i + 1].startsWith("-")) {
1032
- onlyFiles.add(args[i + 1]);
1033
- i += 1;
1034
- consumed += 1;
1058
+ let fileName = args[i + 1];
1059
+
1060
+ // Check for /file syntax (root-only include)
1061
+ if (fileName.startsWith("/")) {
1062
+ const cleanFileName = fileName.slice(1); // Remove leading /
1063
+ onlyFiles.add(cleanFileName);
1064
+ rootOnlyInclude = true;
1065
+ i += 1;
1066
+ consumed += 1;
1067
+ } else {
1068
+ // Normal file path (could be nested like folder/file.ext)
1069
+ onlyFiles.add(fileName);
1070
+ i += 1;
1071
+ consumed += 1;
1072
+ }
1035
1073
  }
1036
1074
  if (consumed === 0) {
1037
1075
  console.error("Error: --only-file requires at least one file name.");
@@ -1048,7 +1086,16 @@ Dump an entire project folder into a single readable .txt file.
1048
1086
  console.error("Error: --only-file requires a file name.");
1049
1087
  process.exit(1);
1050
1088
  }
1051
- onlyFiles.add(value);
1089
+
1090
+ // Check for /file syntax (root-only include)
1091
+ if (value.startsWith("/")) {
1092
+ const cleanFileName = value.slice(1); // Remove leading /
1093
+ onlyFiles.add(cleanFileName);
1094
+ rootOnlyInclude = true;
1095
+ } else {
1096
+ // Normal file path (could be nested like folder/file.ext)
1097
+ onlyFiles.add(value);
1098
+ }
1052
1099
  continue;
1053
1100
  }
1054
1101
 
@@ -1088,7 +1135,8 @@ Dump an entire project folder into a single readable .txt file.
1088
1135
  rootName,
1089
1136
  txtIgnore,
1090
1137
  force: forceFlag,
1091
- hasOnlyFilters: onlyFolders.size > 0 || onlyFiles.size > 0
1138
+ hasOnlyFilters: onlyFolders.size > 0 || onlyFiles.size > 0,
1139
+ rootOnlyInclude
1092
1140
  }
1093
1141
  );
1094
1142
 
@@ -1201,37 +1249,6 @@ main().catch(err => {
1201
1249
  });
1202
1250
 
1203
1251
 
1204
- --------------------------------------------------------------------------------
1205
- FILE: /package.json
1206
- --------------------------------------------------------------------------------
1207
- {
1208
- "name": "make-folder-txt",
1209
- "version": "2.2.5",
1210
- "description": "Generate a single .txt file containing the full folder structure and file contents of any project, ignoring node_modules and other junk.",
1211
- "main": "bin/make-folder-txt.js",
1212
- "bin": {
1213
- "make-folder-txt": "bin/make-folder-txt.js"
1214
- },
1215
- "scripts": {
1216
- "test": "echo \"No tests yet\" && exit 0"
1217
- },
1218
- "keywords": [
1219
- "folder",
1220
- "dump",
1221
- "project",
1222
- "structure",
1223
- "txt",
1224
- "cli",
1225
- "export"
1226
- ],
1227
- "author": "Muhammad Saad Amin",
1228
- "license": "MIT",
1229
- "engines": {
1230
- "node": ">=14.0.0"
1231
- }
1232
- }
1233
-
1234
-
1235
1252
  ================================================================================
1236
1253
  END OF FOLDER: make-folder-txt
1237
1254
  ================================================================================
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "make-folder-txt",
3
- "version": "2.2.6",
3
+ "version": "2.2.7",
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": {