@node-cli/search 3.0.0 → 3.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
@@ -1,64 +1,262 @@
1
- # Node CLI search package
1
+ # @node-cli/search
2
2
 
3
3
  ![npm](https://img.shields.io/npm/v/@node-cli/search?label=version&logo=npm)
4
4
 
5
- > Search is a command line tool that can:
6
- >
7
- > - find files or folders that match a certain pattern
8
- > - look for string within those files and display them (think shell commands "find" and "grep")
5
+ > A powerful and flexible command line tool for searching files and directories with advanced filtering capabilities. It combines the functionality of shell commands like "find" and "grep" with additional features for modern development workflows.
6
+
7
+ ## Features
8
+
9
+ - Find files or folders that match specific patterns
10
+ - Search for text within files using regular expressions
11
+ - Filter results by file type, extension, or name
12
+ - Respect `.gitignore` files (or optionally ignore them)
13
+ - Execute commands on matched files
14
+ - Output file content in different formats (simple text or XML) if needed
15
+ - Detailed statistics about search operations
9
16
 
10
17
  ## Installation
11
18
 
12
- This command line utility can be installed globally or locally within your project. It does make more sense to have it installed globally though, since it then can be use anywhere by simply starting it to search files and folders located in the current folder.
19
+ This command line utility can be installed globally or locally within your project. It makes more sense to install it globally so it can be used anywhere to search files and folders in the current directory.
20
+
21
+ ```sh
22
+ npm install --global @node-cli/search
23
+ ```
24
+
25
+ ## Command Line Usage
26
+
27
+ ### Help
28
+
29
+ To get help about available options and usage, run:
30
+
31
+ ```sh
32
+ search --help
33
+ ```
34
+
35
+ ### Basic Examples
36
+
37
+ **Find all files with the extension ".jsx" in the "src" folder:**
38
+
39
+ ```sh
40
+ search --type f --pattern "\.jsx$" src/
41
+ ```
42
+
43
+ **Find all files without the extensions "jsx" or "md" in the "src" folder:**
44
+
45
+ ```sh
46
+ search --type f --ignoreExtension jsx --ignoreExtension md src/
47
+ ```
48
+
49
+ **Change the permissions to executable for all shell scripts in the "bin" folder:**
50
+
51
+ ```sh
52
+ search --type f --pattern "\.sh$" --command "chmod +x" bin/
53
+ ```
54
+
55
+ **Search in all markdown files for the keywords "Table of Content":**
56
+
57
+ ```sh
58
+ search --type f --pattern "\.md$" --grep "Table of Content"
59
+ ```
60
+
61
+ **Find all files with the extension ".jsx" and print their content:**
13
62
 
14
63
  ```sh
15
- > npm install --global @node-cli/search
64
+ search --type f --pattern "\.jsx$" --printMode simple src/
16
65
  ```
17
66
 
18
- ## Examples
67
+ **Find all files with the extension ".jsx" and print their content in Claude XML format:**
68
+
69
+ ```sh
70
+ search --type f --pattern "\.jsx$" --printMode xml src/
71
+ ```
19
72
 
20
- Find all files with the extension ".jsx" in the "src" folder
73
+ ### Advanced Examples
74
+
75
+ **Find all files ignoring case sensitivity:**
21
76
 
22
77
  ```sh
23
- > search --type f --pattern ".jsx$" src/
78
+ search --type f --pattern "readme" --ignoreCase
24
79
  ```
25
80
 
26
- Find all files without the extension "jsx" or "md" in the "src" folder
81
+ **Find all hidden files:**
27
82
 
28
83
  ```sh
29
- > search --type f --ignore "jsx" --ignore "md" src/
84
+ search --type f --dot
30
85
  ```
31
86
 
32
- Change the permissions to executable for all the files with the extension ".sh" found under the "bin" folder
87
+ **Find all files ignoring specific folders:**
33
88
 
34
89
  ```sh
35
- > search --type f --pattern ".sh$" --command "chmod +x" bin/
90
+ search --type f --ignoreFolder node_modules --ignoreFolder dist
36
91
  ```
37
92
 
38
- Search in all the markdown files under the "src" folder for the keywords "Table of Content"
93
+ **Find all files ignoring specific file names:**
39
94
 
40
95
  ```sh
41
- > search --type f --pattern ".md$" --grep "Table of Content"
96
+ search --type f --ignoreFile README.md --ignoreFile CHANGELOG.md
42
97
  ```
43
98
 
44
- Find all files with the extension ".jsx" in the "src" folder and print their content
99
+ **Find all non-minified JavaScript files:**
45
100
 
46
101
  ```sh
47
- > search --type f --pattern ".jsx$" --printMode simple src/
102
+ search --type f --pattern "\.js$" --ignoreExtension min.js
48
103
  ```
49
104
 
50
- Find all files with the extension ".jsx" in the "src" folder and print their content in a Claude XML format
105
+ **Search for multiple patterns in TypeScript files:**
51
106
 
52
107
  ```sh
53
- > search --type f --pattern ".jsx$" --printMode xml src/
108
+ search --type f --pattern "\.ts$" --grep "export (class|function|const)"
54
109
  ```
55
110
 
56
- Get help
111
+ **Find all files ignoring .gitignore rules:**
57
112
 
58
113
  ```sh
59
- > search --help
114
+ search --type f --ignoreGitIgnore
60
115
  ```
61
116
 
117
+ ## Programmatic API Usage
118
+
119
+ The search functionality can also be used programmatically in your Node.js applications:
120
+
121
+ ```javascript
122
+ import { Search } from "@node-cli/search";
123
+
124
+ // Create a new search instance with configuration
125
+ const search = new Search({
126
+ // Path to search in
127
+ path: process.cwd(),
128
+
129
+ // Search for files only
130
+ type: "f",
131
+
132
+ // Pattern to match file names (as RegExp string)
133
+ pattern: ".js$",
134
+
135
+ // Case insensitive search
136
+ ignoreCase: true,
137
+
138
+ // Show hidden files
139
+ dot: true,
140
+
141
+ // Display statistics
142
+ stats: true,
143
+
144
+ // Extensions to ignore
145
+ ignoreExtension: ["min.js", "map"],
146
+
147
+ // Files to ignore
148
+ ignoreFile: ["package-lock.json"],
149
+
150
+ // Folders to ignore
151
+ ignoreFolder: ["node_modules", "dist"],
152
+
153
+ // Search for text within files
154
+ grep: "function",
155
+
156
+ // Command to execute on matched files
157
+ command: "wc -l",
158
+
159
+ // Output format
160
+ printMode: "simple", // or 'xml'
161
+
162
+ // Ignore .gitignore rules
163
+ ignoreGitIgnore: false,
164
+
165
+ // Short listing format
166
+ short: true,
167
+
168
+ // No color output
169
+ boring: false
170
+ });
171
+
172
+ // Start the search and print results to the console
173
+ await search.start();
174
+ ```
175
+
176
+ ### Returning Results Instead of Printing
177
+
178
+ By default, the search results are printed to the console. To get the results as a string instead, pass `true` to the `start()` method:
179
+
180
+ ```javascript
181
+ // For simple print mode
182
+ const search = new Search({
183
+ path: "./src",
184
+ type: "f",
185
+ pattern: ".ts$",
186
+ printMode: "simple"
187
+ });
188
+ const results = await search.start(true);
189
+ // results will contain the file contents in simple format
190
+ ```
191
+
192
+ ### XML Output Format
193
+
194
+ The XML output format is useful for parsing search results in other applications:
195
+
196
+ ```javascript
197
+ const search = new Search({
198
+ path: "./src",
199
+ type: "f",
200
+ pattern: ".ts$",
201
+ printMode: "xml"
202
+ });
203
+ const xmlResults = await search.start(true);
204
+ // xmlResults will contain the file contents in XML format
205
+ ```
206
+
207
+ ### Searching with Regular Expressions
208
+
209
+ You can use regular expressions for both file pattern matching and content searching:
210
+
211
+ ```javascript
212
+ const search = new Search({
213
+ path: "./src",
214
+ type: "f",
215
+ pattern: "(component|hook).tsx?$",
216
+ grep: "export\\s+const\\s+\\w+\\s*=\\s*\\(",
217
+ ignoreCase: true
218
+ });
219
+ await search.start();
220
+ ```
221
+
222
+ ### Filtering Options
223
+
224
+ The search utility provides multiple ways to filter results:
225
+
226
+ ```javascript
227
+ const search = new Search({
228
+ path: "./src",
229
+ type: "f",
230
+ // Ignore specific file extensions
231
+ ignoreExtension: ["test.ts", "spec.ts", "d.ts"],
232
+ // Ignore specific file names
233
+ ignoreFile: ["index.ts", "constants.ts"],
234
+ // Ignore specific folders
235
+ ignoreFolder: ["__tests__", "__mocks__"]
236
+ });
237
+ await search.start();
238
+ ```
239
+
240
+ ## Available Options
241
+
242
+ | Option | Type | Description |
243
+ | ----------------- | -------- | ------------------------------------------------------------------ |
244
+ | `path` | string | The path where to start the search (defaults to current directory) |
245
+ | `type` | string | Search for files ('f'), directories ('d'), or both ('both') |
246
+ | `pattern` | string | A regular expression to match file or folder names |
247
+ | `grep` | string | A regular expression to match the content of files |
248
+ | `ignoreCase` | boolean | Ignore case when searching |
249
+ | `dot` | boolean | Show hidden files and directories |
250
+ | `short` | boolean | Short listing format (equivalent to ls) |
251
+ | `stats` | boolean | Display search statistics |
252
+ | `command` | string | Command to execute over each matched node |
253
+ | `ignoreExtension` | string[] | File extensions to ignore |
254
+ | `ignoreFile` | string[] | File names to ignore |
255
+ | `ignoreFolder` | string[] | Folder names to ignore |
256
+ | `printMode` | string | Print mode ('simple' or 'xml') |
257
+ | `ignoreGitIgnore` | boolean | Ignore .gitignore files |
258
+ | `boring` | boolean | Do not use color output |
259
+
62
260
  ## License
63
261
 
64
262
  MIT © Arno Versini
package/dist/core.d.ts CHANGED
@@ -20,7 +20,8 @@ export declare class Search {
20
20
  printMode?: string;
21
21
  gitIgnoreHandler: GitIgnoreHandler;
22
22
  ignoreGitIgnore?: boolean;
23
- constructor({ boring, command, dot, grep, ignoreCase, short, path, pattern, stats, type, ignoreExtension, ignoreFile, ignoreFolder, printMode, ignoreGitIgnore, }: {
23
+ minifyForLLM?: boolean;
24
+ constructor({ boring, command, dot, grep, ignoreCase, short, path, pattern, stats, type, ignoreExtension, ignoreFile, ignoreFolder, printMode, ignoreGitIgnore, minifyForLLM, }: {
24
25
  boring?: boolean;
25
26
  command?: string;
26
27
  dot?: boolean;
@@ -36,11 +37,11 @@ export declare class Search {
36
37
  ignoreFolder?: string[];
37
38
  printMode?: string;
38
39
  ignoreGitIgnore?: boolean;
40
+ minifyForLLM?: boolean;
39
41
  });
40
42
  shouldIgnoreFolder(directory: string): boolean;
41
43
  shouldIgnoreFile(filePath: string): boolean;
42
44
  filterHidden(value: string[] | string): boolean;
43
- isBinaryFileExtension(filePath: string): boolean;
44
45
  start(returnResults?: boolean): Promise<string>;
45
46
  scanFileSystem(nodes: string[]): Promise<void>;
46
47
  readFileContent(filePath: string): Promise<string>;
package/dist/core.js CHANGED
@@ -1,12 +1,13 @@
1
- import { basename, extname, join, relative } from "node:path";
2
- import { GitIgnoreHandler } from "./gitIgnoreHandler.js";
3
- import { STR_TYPE_BOTH, STR_TYPE_DIRECTORY, STR_TYPE_FILE, checkPattern, formatLongListings, printStatistics, runCommandOnNode, runGrepOnNode } from "./utilities.js";
1
+ import { basename, join, relative } from "node:path";
4
2
  import { promisify } from "node:util";
5
3
  import { Logger } from "@node-cli/logger";
6
4
  import { Performance } from "@node-cli/perf";
7
5
  import fs from "fs-extra";
8
6
  import kleur from "kleur";
9
7
  import plur from "plur";
8
+ import { GitIgnoreHandler } from "./gitIgnoreHandler.js";
9
+ import { minifyFileContent } from "./minifiers.js";
10
+ import { STR_TYPE_BOTH, STR_TYPE_DIRECTORY, STR_TYPE_FILE, checkPattern, formatLongListings, getFileExtension, isBinaryFileExtension, printStatistics, runCommandOnNode, runGrepOnNode } from "./utilities.js";
10
11
  const lstatAsync = promisify(fs.lstat);
11
12
  const readdirAsync = promisify(fs.readdir);
12
13
  const readFileAsync = promisify(fs.readFile);
@@ -14,6 +15,9 @@ const perf = new Performance();
14
15
  const logger = new Logger({
15
16
  boring: process.env.NODE_ENV === "test"
16
17
  });
18
+ const loggerInMemory = new Logger({
19
+ inMemory: true
20
+ });
17
21
  export class Search {
18
22
  boring;
19
23
  command;
@@ -35,7 +39,8 @@ export class Search {
35
39
  printMode;
36
40
  gitIgnoreHandler;
37
41
  ignoreGitIgnore;
38
- constructor({ boring, command, dot, grep, ignoreCase, short, path, pattern, stats, type, ignoreExtension, ignoreFile, ignoreFolder, printMode, ignoreGitIgnore }){
42
+ minifyForLLM;
43
+ constructor({ boring, command, dot, grep, ignoreCase, short, path, pattern, stats, type, ignoreExtension, ignoreFile, ignoreFolder, printMode, ignoreGitIgnore, minifyForLLM }){
39
44
  this.path = path;
40
45
  this.rePattern = pattern ? new RegExp(pattern, ignoreCase ? "i" : "") : undefined;
41
46
  this.type = type || STR_TYPE_BOTH;
@@ -55,6 +60,7 @@ export class Search {
55
60
  this.ignoreFolders = ignoreFolder || [];
56
61
  this.printMode = printMode;
57
62
  this.ignoreGitIgnore = ignoreGitIgnore;
63
+ this.minifyForLLM = minifyForLLM;
58
64
  this.gitIgnoreHandler = new GitIgnoreHandler();
59
65
  try {
60
66
  this.grep = grep ? new RegExp(grep, ignoreCase ? "gi" : "g") : undefined;
@@ -81,7 +87,7 @@ export class Search {
81
87
  if (!this.ignoreExtensions || this.ignoreExtensions.length === 0) {
82
88
  return false;
83
89
  }
84
- const extension = extname(filePath).toLowerCase().replace(/^\./, "");
90
+ const extension = getFileExtension(filePath);
85
91
  // Check for exact extension match
86
92
  if (this.ignoreExtensions.includes(extension)) {
87
93
  return true;
@@ -105,70 +111,6 @@ export class Search {
105
111
  }
106
112
  return value[0] !== ".";
107
113
  }
108
- isBinaryFileExtension(filePath) {
109
- const ext = extname(filePath).toLowerCase().replace(/^\./, "");
110
- // If there's no extension, assume it's binary
111
- /* istanbul ignore if */ if (!ext) {
112
- return true;
113
- }
114
- const binaryExtensions = [
115
- // Executables and compiled code
116
- "exe",
117
- "dll",
118
- "so",
119
- "dylib",
120
- "bin",
121
- "obj",
122
- "o",
123
- // Compressed files
124
- "zip",
125
- "tar",
126
- "gz",
127
- "rar",
128
- "7z",
129
- "jar",
130
- "war",
131
- // Media files
132
- "jpg",
133
- "jpeg",
134
- "png",
135
- "gif",
136
- "bmp",
137
- "ico",
138
- "tif",
139
- "tiff",
140
- "mp3",
141
- "mp4",
142
- "avi",
143
- "mov",
144
- "wmv",
145
- "flv",
146
- "wav",
147
- "ogg",
148
- // Document formats
149
- "pdf",
150
- "doc",
151
- "docx",
152
- "xls",
153
- "xlsx",
154
- "ppt",
155
- "pptx",
156
- // Database files
157
- "db",
158
- "sqlite",
159
- "mdb",
160
- // Other binary formats
161
- "class",
162
- "pyc",
163
- "pyd",
164
- "pyo",
165
- "woff",
166
- "woff2",
167
- "ttf",
168
- "otf"
169
- ];
170
- return binaryExtensions.includes(ext);
171
- }
172
114
  async start(returnResults = false) {
173
115
  if (this.displayStats) {
174
116
  perf.start();
@@ -251,36 +193,35 @@ export class Search {
251
193
  async readFileContent(filePath) {
252
194
  try {
253
195
  // Check if it's a known binary extension
254
- /* istanbul ignore if */ if (this.isBinaryFileExtension(filePath)) {
255
- return "[Binary file]";
196
+ /* istanbul ignore if */ if (isBinaryFileExtension(filePath)) {
197
+ return null;
256
198
  }
257
199
  const content = await readFileAsync(filePath, "utf8");
258
- return content;
259
- } catch (error) {
260
- /* istanbul ignore next */ return `Error reading file: ${error.message}`;
200
+ return this.minifyForLLM ? await minifyFileContent(filePath, content) : content;
201
+ } catch (_error) {
202
+ /* istanbul ignore next */ return null;
261
203
  }
262
204
  }
263
205
  async printFilesContent(returnResults) {
264
206
  const fileNodes = this.nodesList.filter((node)=>node.type === STR_TYPE_FILE);
265
- let results = "";
266
207
  if (this.printMode === "simple") {
267
208
  for (const node of fileNodes){
268
209
  const relativePath = relative(this.path, node.name);
269
210
  if (returnResults) {
270
- results += `---\n./${relativePath}\n---\n`;
211
+ loggerInMemory.log(`---\n./${relativePath}\n---`);
271
212
  } else {
272
213
  logger.log(`---\n./${relativePath}\n---`);
273
214
  }
274
215
  const content = await this.readFileContent(node.name);
275
216
  if (returnResults) {
276
- results += `${content}\n`;
217
+ loggerInMemory.log(content);
277
218
  } else {
278
219
  logger.log(content);
279
220
  }
280
221
  // adding a new line after each file content except the last one
281
222
  if (node !== fileNodes[fileNodes.length - 1]) {
282
223
  if (returnResults) {
283
- results += "\n";
224
+ loggerInMemory.log("");
284
225
  } else {
285
226
  logger.log("");
286
227
  }
@@ -288,7 +229,7 @@ export class Search {
288
229
  }
289
230
  } else if (this.printMode === "xml") {
290
231
  if (returnResults) {
291
- results += "<documents>\n";
232
+ loggerInMemory.log("<documents>");
292
233
  } else {
293
234
  logger.log("<documents>");
294
235
  }
@@ -297,13 +238,15 @@ export class Search {
297
238
  const relativePath = relative(this.path, node.name);
298
239
  const content = await this.readFileContent(node.name);
299
240
  if (returnResults) {
300
- results += `<document index="${i + 1}">\n`;
301
- results += `<source>./${relativePath}</source>\n`;
302
- results += "<document_content>\n";
303
- results += `${content}\n`;
304
- results += "</document_content>\n";
305
- results += "</document>\n";
306
- } else {
241
+ if (content) {
242
+ loggerInMemory.log(`<document index="${i + 1}">`);
243
+ loggerInMemory.log(`<source>./${relativePath}</source>`);
244
+ loggerInMemory.log("<document_content>");
245
+ loggerInMemory.log(content);
246
+ loggerInMemory.log("</document_content>");
247
+ loggerInMemory.log("</document>");
248
+ }
249
+ } else if (content) {
307
250
  logger.log(`<document index="${i + 1}">`);
308
251
  logger.log(`<source>./${relativePath}</source>`);
309
252
  logger.log("<document_content>");
@@ -313,23 +256,22 @@ export class Search {
313
256
  }
314
257
  }
315
258
  if (returnResults) {
316
- results += "</documents>";
259
+ loggerInMemory.log("</documents>");
317
260
  } else {
318
261
  logger.log("</documents>");
319
262
  }
320
263
  }
264
+ const results = returnResults ? loggerInMemory.getMemoryLogs() : undefined;
265
+ loggerInMemory.clearMemoryLogs();
321
266
  return results;
322
267
  }
323
268
  async shouldIgnoreByGitIgnore(nodePath, isDirectory) {
324
- /* istanbul ignore if */ if (this.ignoreGitIgnore) {
269
+ if (this.ignoreGitIgnore) {
325
270
  return false;
326
271
  }
327
272
  return this.gitIgnoreHandler.isIgnored(nodePath, isDirectory);
328
273
  }
329
274
  async postProcessResults(returnResults) {
330
- /* istanbul ignore if */ if (!this.boring) {
331
- logger.log();
332
- }
333
275
  if (this.grep) {
334
276
  /**
335
277
  * Resetting the number of files found, since we want to
@@ -344,6 +286,9 @@ export class Search {
344
286
  ].includes(this.printMode)) {
345
287
  return await this.printFilesContent(returnResults);
346
288
  }
289
+ /* istanbul ignore if */ if (!this.boring) {
290
+ logger.log();
291
+ }
347
292
  for (const node of this.nodesList){
348
293
  if (this.type === STR_TYPE_FILE && node.type === STR_TYPE_FILE || this.type === STR_TYPE_DIRECTORY && node.type === STR_TYPE_DIRECTORY || this.type === STR_TYPE_BOTH) {
349
294
  let list = {
package/dist/core.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/core.ts"],"sourcesContent":["import { basename, extname, join, relative } from \"node:path\";\n\nimport { GitIgnoreHandler } from \"./gitIgnoreHandler.js\";\nimport {\n\tSTR_TYPE_BOTH,\n\tSTR_TYPE_DIRECTORY,\n\tSTR_TYPE_FILE,\n\tcheckPattern,\n\tformatLongListings,\n\tprintStatistics,\n\trunCommandOnNode,\n\trunGrepOnNode,\n} from \"./utilities.js\";\n\nimport { promisify } from \"node:util\";\nimport { Logger } from \"@node-cli/logger\";\nimport { Performance } from \"@node-cli/perf\";\nimport fs from \"fs-extra\";\nimport kleur from \"kleur\";\nimport plur from \"plur\";\n\nconst lstatAsync = promisify(fs.lstat);\nconst readdirAsync = promisify(fs.readdir);\nconst readFileAsync = promisify(fs.readFile);\nconst perf = new Performance();\nconst logger = new Logger({\n\tboring: process.env.NODE_ENV === \"test\",\n});\n\nexport class Search {\n\tboring?: boolean;\n\tcommand?: string;\n\tdisplayHiddenFilesAndFolders?: boolean;\n\tdisplayLongListing?: boolean;\n\tdisplayStats?: boolean;\n\tgrep?: RegExp;\n\tnodesList?: any[];\n\tpath?: string;\n\trePattern?: RegExp;\n\ttotalDirFound?: number;\n\ttotalDirScanned?: number;\n\ttotalFileFound?: number;\n\ttotalFileScanned?: number;\n\ttype?: string;\n\tignoreExtensions?: string[];\n\tignoreFiles?: string[];\n\tignoreFolders?: string[];\n\tprintMode?: string;\n\tgitIgnoreHandler: GitIgnoreHandler;\n\tignoreGitIgnore?: boolean;\n\n\tconstructor({\n\t\tboring,\n\t\tcommand,\n\t\tdot,\n\t\tgrep,\n\t\tignoreCase,\n\t\tshort,\n\t\tpath,\n\t\tpattern,\n\t\tstats,\n\t\ttype,\n\t\tignoreExtension,\n\t\tignoreFile,\n\t\tignoreFolder,\n\t\tprintMode,\n\t\tignoreGitIgnore,\n\t}: {\n\t\tboring?: boolean;\n\t\tcommand?: string;\n\t\tdot?: boolean;\n\t\tgrep?: string | RegExp;\n\t\tignoreCase?: boolean;\n\t\tshort?: boolean;\n\t\tpath?: string;\n\t\tpattern?: string;\n\t\tstats?: boolean;\n\t\ttype?: string;\n\t\tignoreExtension?: string[];\n\t\tignoreFile?: string[];\n\t\tignoreFolder?: string[];\n\t\tprintMode?: string;\n\t\tignoreGitIgnore?: boolean;\n\t}) {\n\t\tthis.path = path;\n\t\tthis.rePattern = pattern\n\t\t\t? new RegExp(pattern, ignoreCase ? \"i\" : \"\")\n\t\t\t: undefined;\n\t\tthis.type = type || STR_TYPE_BOTH;\n\t\tthis.boring = boring;\n\t\tkleur.enabled = !boring;\n\t\tthis.displayLongListing = !short;\n\t\tthis.displayStats = stats;\n\t\tthis.displayHiddenFilesAndFolders = dot;\n\t\tthis.nodesList = [];\n\t\tthis.totalDirScanned = 0;\n\t\tthis.totalFileScanned = 0;\n\t\tthis.totalDirFound = 0;\n\t\tthis.totalFileFound = 0;\n\t\tthis.command = command ? command.trim() : undefined;\n\t\tthis.ignoreExtensions =\n\t\t\t(ignoreExtension && ignoreExtension.map((ext) => ext.toLowerCase())) ||\n\t\t\t[];\n\t\tthis.ignoreFiles = ignoreFile || [];\n\t\tthis.ignoreFolders = ignoreFolder || [];\n\t\tthis.printMode = printMode;\n\t\tthis.ignoreGitIgnore = ignoreGitIgnore;\n\t\tthis.gitIgnoreHandler = new GitIgnoreHandler();\n\t\ttry {\n\t\t\tthis.grep = grep ? new RegExp(grep, ignoreCase ? \"gi\" : \"g\") : undefined;\n\t\t} catch (error) {\n\t\t\tlogger.error(error);\n\t\t\tprocess.exit(1);\n\t\t}\n\t}\n\n\tshouldIgnoreFolder(directory: string) {\n\t\tconst folderName = basename(directory);\n\t\t// Check for exact folder name match\n\t\tif (this.ignoreFolders && this.ignoreFolders.includes(folderName)) {\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\tshouldIgnoreFile(filePath: string) {\n\t\t// First check if the file is in the ignoreFiles list\n\t\tconst filename = basename(filePath);\n\t\tif (this.ignoreFiles && this.ignoreFiles.includes(filename)) {\n\t\t\treturn true;\n\t\t}\n\n\t\t// Then check if the extension should be ignored\n\t\tif (!this.ignoreExtensions || this.ignoreExtensions.length === 0) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst extension = extname(filePath).toLowerCase().replace(/^\\./, \"\");\n\n\t\t// Check for exact extension match\n\t\tif (this.ignoreExtensions.includes(extension)) {\n\t\t\treturn true;\n\t\t}\n\n\t\t// Check for complex patterns like \"min.js\"\n\t\tfor (const pattern of this.ignoreExtensions) {\n\t\t\t// Skip patterns that don't contain a dot\n\t\t\tif (!pattern.includes(\".\")) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Check if the filename ends with the pattern\n\t\t\tif (filename.toLowerCase().endsWith(`.${pattern}`)) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t}\n\n\tfilterHidden(value: string[] | string) {\n\t\tif (this.displayHiddenFilesAndFolders) {\n\t\t\treturn true;\n\t\t}\n\t\treturn value[0] !== \".\";\n\t}\n\n\tisBinaryFileExtension(filePath: string): boolean {\n\t\tconst ext = extname(filePath).toLowerCase().replace(/^\\./, \"\");\n\n\t\t// If there's no extension, assume it's binary\n\t\t/* istanbul ignore if */\n\t\tif (!ext) {\n\t\t\treturn true;\n\t\t}\n\n\t\tconst binaryExtensions = [\n\t\t\t// Executables and compiled code\n\t\t\t\"exe\",\n\t\t\t\"dll\",\n\t\t\t\"so\",\n\t\t\t\"dylib\",\n\t\t\t\"bin\",\n\t\t\t\"obj\",\n\t\t\t\"o\",\n\t\t\t// Compressed files\n\t\t\t\"zip\",\n\t\t\t\"tar\",\n\t\t\t\"gz\",\n\t\t\t\"rar\",\n\t\t\t\"7z\",\n\t\t\t\"jar\",\n\t\t\t\"war\",\n\t\t\t// Media files\n\t\t\t\"jpg\",\n\t\t\t\"jpeg\",\n\t\t\t\"png\",\n\t\t\t\"gif\",\n\t\t\t\"bmp\",\n\t\t\t\"ico\",\n\t\t\t\"tif\",\n\t\t\t\"tiff\",\n\t\t\t\"mp3\",\n\t\t\t\"mp4\",\n\t\t\t\"avi\",\n\t\t\t\"mov\",\n\t\t\t\"wmv\",\n\t\t\t\"flv\",\n\t\t\t\"wav\",\n\t\t\t\"ogg\",\n\t\t\t// Document formats\n\t\t\t\"pdf\",\n\t\t\t\"doc\",\n\t\t\t\"docx\",\n\t\t\t\"xls\",\n\t\t\t\"xlsx\",\n\t\t\t\"ppt\",\n\t\t\t\"pptx\",\n\t\t\t// Database files\n\t\t\t\"db\",\n\t\t\t\"sqlite\",\n\t\t\t\"mdb\",\n\t\t\t// Other binary formats\n\t\t\t\"class\",\n\t\t\t\"pyc\",\n\t\t\t\"pyd\",\n\t\t\t\"pyo\",\n\t\t\t\"woff\",\n\t\t\t\"woff2\",\n\t\t\t\"ttf\",\n\t\t\t\"otf\",\n\t\t];\n\n\t\treturn binaryExtensions.includes(ext);\n\t}\n\n\tasync start(returnResults = false) {\n\t\tif (this.displayStats) {\n\t\t\tperf.start();\n\t\t}\n\t\tawait this.scanFileSystem([this.path]);\n\t\tconst results = await this.postProcessResults(returnResults);\n\n\t\tif (this.displayStats) {\n\t\t\tperf.stop();\n\t\t\tprintStatistics({\n\t\t\t\tduration: perf.results.duration,\n\t\t\t\tgrep: this.grep,\n\t\t\t\tpattern: this.rePattern,\n\t\t\t\ttotalDirScanned: this.totalDirScanned,\n\t\t\t\ttotalDirsFound: this.totalDirFound,\n\t\t\t\ttotalFileScanned: this.totalFileScanned,\n\t\t\t\ttotalFilesFound: this.totalFileFound,\n\t\t\t\ttype: this.type,\n\t\t\t});\n\t\t}\n\t\treturn returnResults ? results : undefined;\n\t}\n\n\tasync scanFileSystem(nodes: string[]) {\n\t\tfor (const node of nodes) {\n\t\t\tlet result: boolean | RegExpExecArray,\n\t\t\t\tfiles: string[],\n\t\t\t\tshortname: string,\n\t\t\t\tstat: fs.Stats;\n\t\t\ttry {\n\t\t\t\tstat = await lstatAsync(node);\n\t\t\t} catch {\n\t\t\t\t// ignore read permission denied errors silently...\n\t\t\t}\n\n\t\t\tconst isDirectory = stat && stat.isDirectory();\n\t\t\tconst isFile = stat && stat.isFile();\n\n\t\t\t// Add this check to respect .gitignore patterns\n\t\t\tif (await this.shouldIgnoreByGitIgnore(node, isDirectory)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (isDirectory && !this.shouldIgnoreFolder(node)) {\n\t\t\t\tthis.totalDirScanned++;\n\n\t\t\t\tresult = checkPattern(this.rePattern, node);\n\t\t\t\tif (result) {\n\t\t\t\t\tthis.totalDirFound++;\n\t\t\t\t\tthis.nodesList.push({\n\t\t\t\t\t\tcommand: this.command,\n\t\t\t\t\t\tmatch: result,\n\t\t\t\t\t\tname: node,\n\t\t\t\t\t\tstat,\n\t\t\t\t\t\ttype: STR_TYPE_DIRECTORY,\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\ttry {\n\t\t\t\t\tfiles = await readdirAsync(node);\n\t\t\t\t\tawait this.scanFileSystem(\n\t\t\t\t\t\tfiles\n\t\t\t\t\t\t\t.filter((element) => this.filterHidden(element))\n\t\t\t\t\t\t\t.map(function (file) {\n\t\t\t\t\t\t\t\treturn join(node, file);\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t);\n\t\t\t\t} catch {\n\t\t\t\t\t// nothing to declare\n\t\t\t\t}\n\t\t\t} else if (isFile) {\n\t\t\t\t// Skip files with ignored extensions\n\t\t\t\tif (this.shouldIgnoreFile(node)) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tthis.totalFileScanned++;\n\t\t\t\tshortname = basename(node);\n\t\t\t\tconst patternResult = checkPattern(this.rePattern, shortname);\n\t\t\t\tif (patternResult) {\n\t\t\t\t\tthis.totalFileFound++;\n\t\t\t\t\tthis.nodesList.push({\n\t\t\t\t\t\tcommand: this.command,\n\t\t\t\t\t\tmatch: patternResult[0],\n\t\t\t\t\t\tname: node,\n\t\t\t\t\t\tstat,\n\t\t\t\t\t\ttype: STR_TYPE_FILE,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tasync readFileContent(filePath: string): Promise<string> {\n\t\ttry {\n\t\t\t// Check if it's a known binary extension\n\t\t\t/* istanbul ignore if */\n\t\t\tif (this.isBinaryFileExtension(filePath)) {\n\t\t\t\treturn \"[Binary file]\";\n\t\t\t}\n\t\t\tconst content = await readFileAsync(filePath, \"utf8\");\n\t\t\treturn content;\n\t\t} catch (error) {\n\t\t\t/* istanbul ignore next */\n\t\t\treturn `Error reading file: ${error.message}`;\n\t\t}\n\t}\n\n\tasync printFilesContent(returnResults: boolean) {\n\t\tconst fileNodes = this.nodesList.filter(\n\t\t\t(node) => node.type === STR_TYPE_FILE,\n\t\t);\n\n\t\tlet results = \"\";\n\t\tif (this.printMode === \"simple\") {\n\t\t\tfor (const node of fileNodes) {\n\t\t\t\tconst relativePath = relative(this.path, node.name);\n\t\t\t\tif (returnResults) {\n\t\t\t\t\tresults += `---\\n./${relativePath}\\n---\\n`;\n\t\t\t\t} else {\n\t\t\t\t\tlogger.log(`---\\n./${relativePath}\\n---`);\n\t\t\t\t}\n\t\t\t\tconst content = await this.readFileContent(node.name);\n\t\t\t\tif (returnResults) {\n\t\t\t\t\tresults += `${content}\\n`;\n\t\t\t\t} else {\n\t\t\t\t\tlogger.log(content);\n\t\t\t\t}\n\t\t\t\t// adding a new line after each file content except the last one\n\t\t\t\tif (node !== fileNodes[fileNodes.length - 1]) {\n\t\t\t\t\tif (returnResults) {\n\t\t\t\t\t\tresults += \"\\n\";\n\t\t\t\t\t} else {\n\t\t\t\t\t\tlogger.log(\"\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (this.printMode === \"xml\") {\n\t\t\tif (returnResults) {\n\t\t\t\tresults += \"<documents>\\n\";\n\t\t\t} else {\n\t\t\t\tlogger.log(\"<documents>\");\n\t\t\t}\n\n\t\t\tfor (let i = 0; i < fileNodes.length; i++) {\n\t\t\t\tconst node = fileNodes[i];\n\t\t\t\tconst relativePath = relative(this.path, node.name);\n\t\t\t\tconst content = await this.readFileContent(node.name);\n\n\t\t\t\tif (returnResults) {\n\t\t\t\t\tresults += `<document index=\"${i + 1}\">\\n`;\n\t\t\t\t\tresults += `<source>./${relativePath}</source>\\n`;\n\t\t\t\t\tresults += \"<document_content>\\n\";\n\t\t\t\t\tresults += `${content}\\n`;\n\t\t\t\t\tresults += \"</document_content>\\n\";\n\t\t\t\t\tresults += \"</document>\\n\";\n\t\t\t\t} else {\n\t\t\t\t\tlogger.log(`<document index=\"${i + 1}\">`);\n\t\t\t\t\tlogger.log(`<source>./${relativePath}</source>`);\n\t\t\t\t\tlogger.log(\"<document_content>\");\n\t\t\t\t\tlogger.log(content);\n\t\t\t\t\tlogger.log(\"</document_content>\");\n\t\t\t\t\tlogger.log(\"</document>\");\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (returnResults) {\n\t\t\t\tresults += \"</documents>\";\n\t\t\t} else {\n\t\t\t\tlogger.log(\"</documents>\");\n\t\t\t}\n\t\t}\n\t\treturn results;\n\t}\n\n\tasync shouldIgnoreByGitIgnore(\n\t\tnodePath: string,\n\t\tisDirectory: boolean,\n\t): Promise<boolean> {\n\t\t/* istanbul ignore if */\n\t\tif (this.ignoreGitIgnore) {\n\t\t\treturn false;\n\t\t}\n\t\treturn this.gitIgnoreHandler.isIgnored(nodePath, isDirectory);\n\t}\n\n\tasync postProcessResults(returnResults: boolean) {\n\t\t/* istanbul ignore if */\n\t\tif (!this.boring) {\n\t\t\tlogger.log();\n\t\t}\n\n\t\tif (this.grep) {\n\t\t\t/**\n\t\t\t * Resetting the number of files found, since we want to\n\t\t\t * show how many matched the grep, not how many matched the\n\t\t\t * pattern (in the file name).\n\t\t\t */\n\t\t\tthis.totalFileFound = 0;\n\t\t}\n\n\t\t// If printMode is enabled, handle file content printing and return\n\t\tif (this.printMode && [\"simple\", \"xml\"].includes(this.printMode)) {\n\t\t\treturn await this.printFilesContent(returnResults);\n\t\t}\n\n\t\tfor (const node of this.nodesList) {\n\t\t\tif (\n\t\t\t\t(this.type === STR_TYPE_FILE && node.type === STR_TYPE_FILE) ||\n\t\t\t\t(this.type === STR_TYPE_DIRECTORY &&\n\t\t\t\t\tnode.type === STR_TYPE_DIRECTORY) ||\n\t\t\t\tthis.type === STR_TYPE_BOTH\n\t\t\t) {\n\t\t\t\tlet list: {\n\t\t\t\t\t\tgroup?: string;\n\t\t\t\t\t\tmdate?: string;\n\t\t\t\t\t\tmode?: string;\n\t\t\t\t\t\towner?: string;\n\t\t\t\t\t\tsize?: string;\n\t\t\t\t\t} = {\n\t\t\t\t\t\tgroup: \"\",\n\t\t\t\t\t\tmdate: \"\",\n\t\t\t\t\t\tmode: \"\",\n\t\t\t\t\t\towner: \"\",\n\t\t\t\t\t\tsize: \"\",\n\t\t\t\t\t},\n\t\t\t\t\tname: string,\n\t\t\t\t\tseparator: string = \"\";\n\n\t\t\t\t/* istanbul ignore if */\n\t\t\t\tif (this.displayLongListing) {\n\t\t\t\t\tlist = await formatLongListings(node.stat, node.type);\n\t\t\t\t\tseparator = \"\\t\";\n\t\t\t\t}\n\n\t\t\t\tconst color = node.type === STR_TYPE_FILE ? kleur.gray : kleur.blue;\n\t\t\t\tname = relative(this.path, node.name);\n\n\t\t\t\tif (node.match) {\n\t\t\t\t\tconst matchStr = String(node.match); // Ensure match is a string\n\t\t\t\t\tconst match = new RegExp(matchStr, \"g\");\n\t\t\t\t\tconst highlightedMatch = kleur.black().bgYellow(matchStr);\n\t\t\t\t\tname = color(name.replace(match, highlightedMatch));\n\t\t\t\t} else {\n\t\t\t\t\tname = color(name);\n\t\t\t\t}\n\n\t\t\t\tif (this.grep && node.type === STR_TYPE_FILE) {\n\t\t\t\t\tconst { totalMatchingLines, results } = await runGrepOnNode(\n\t\t\t\t\t\tnode.name,\n\t\t\t\t\t\tthis.grep,\n\t\t\t\t\t);\n\t\t\t\t\t/* istanbul ignore else */\n\t\t\t\t\tif (totalMatchingLines) {\n\t\t\t\t\t\tthis.totalFileFound++;\n\t\t\t\t\t\tconst occurrences = plur(\"occurrence\", totalMatchingLines);\n\n\t\t\t\t\t\tlogger.log(\n\t\t\t\t\t\t\t` %s${separator}%s${separator}%s${separator}%s${separator}%s`,\n\t\t\t\t\t\t\tlist.mode.trim(),\n\t\t\t\t\t\t\tlist.owner.trim(),\n\t\t\t\t\t\t\tlist.size.trim(),\n\t\t\t\t\t\t\tlist.mdate,\n\t\t\t\t\t\t\tname,\n\t\t\t\t\t\t\t`(${kleur.white(totalMatchingLines)} ${occurrences})`,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tlogger.log(`${results.join(\"\\n\")}\\n`);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t/* istanbul ignore next */\n\t\t\t\t\tif (!this.grep) {\n\t\t\t\t\t\tlogger.log(\n\t\t\t\t\t\t\t` %s${separator}%s${separator}%s${separator}%s${separator}%s`,\n\t\t\t\t\t\t\tlist.mode.trim(),\n\t\t\t\t\t\t\tlist.owner.trim(),\n\t\t\t\t\t\t\tlist.size.trim(),\n\t\t\t\t\t\t\tlist.mdate,\n\t\t\t\t\t\t\tname,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tif (node.command) {\n\t\t\t\t\t\t\tawait runCommandOnNode(node.name, node.command);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n"],"names":["basename","extname","join","relative","GitIgnoreHandler","STR_TYPE_BOTH","STR_TYPE_DIRECTORY","STR_TYPE_FILE","checkPattern","formatLongListings","printStatistics","runCommandOnNode","runGrepOnNode","promisify","Logger","Performance","fs","kleur","plur","lstatAsync","lstat","readdirAsync","readdir","readFileAsync","readFile","perf","logger","boring","process","env","NODE_ENV","Search","command","displayHiddenFilesAndFolders","displayLongListing","displayStats","grep","nodesList","path","rePattern","totalDirFound","totalDirScanned","totalFileFound","totalFileScanned","type","ignoreExtensions","ignoreFiles","ignoreFolders","printMode","gitIgnoreHandler","ignoreGitIgnore","constructor","dot","ignoreCase","short","pattern","stats","ignoreExtension","ignoreFile","ignoreFolder","RegExp","undefined","enabled","trim","map","ext","toLowerCase","error","exit","shouldIgnoreFolder","directory","folderName","includes","shouldIgnoreFile","filePath","filename","length","extension","replace","endsWith","filterHidden","value","isBinaryFileExtension","binaryExtensions","start","returnResults","scanFileSystem","results","postProcessResults","stop","duration","totalDirsFound","totalFilesFound","nodes","node","result","files","shortname","stat","isDirectory","isFile","shouldIgnoreByGitIgnore","push","match","name","filter","element","file","patternResult","readFileContent","content","message","printFilesContent","fileNodes","relativePath","log","i","nodePath","isIgnored","list","group","mdate","mode","owner","size","separator","color","gray","blue","matchStr","String","highlightedMatch","black","bgYellow","totalMatchingLines","occurrences","white"],"mappings":"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"}
1
+ {"version":3,"sources":["../src/core.ts"],"sourcesContent":["import { basename, extname, join, relative } from \"node:path\";\nimport { promisify } from \"node:util\";\nimport { Logger } from \"@node-cli/logger\";\nimport { Performance } from \"@node-cli/perf\";\nimport fs from \"fs-extra\";\nimport kleur from \"kleur\";\nimport plur from \"plur\";\n\nimport { GitIgnoreHandler } from \"./gitIgnoreHandler.js\";\nimport { minifyCss, minifyFileContent, minifyJs } from \"./minifiers.js\";\nimport {\n\tSTR_TYPE_BOTH,\n\tSTR_TYPE_DIRECTORY,\n\tSTR_TYPE_FILE,\n\tcheckPattern,\n\tformatLongListings,\n\tgetFileExtension,\n\tisBinaryFileExtension,\n\tprintStatistics,\n\trunCommandOnNode,\n\trunGrepOnNode,\n} from \"./utilities.js\";\n\nconst lstatAsync = promisify(fs.lstat);\nconst readdirAsync = promisify(fs.readdir);\nconst readFileAsync = promisify(fs.readFile);\nconst perf = new Performance();\nconst logger = new Logger({\n\tboring: process.env.NODE_ENV === \"test\",\n});\nconst loggerInMemory = new Logger({\n\tinMemory: true,\n});\n\nexport class Search {\n\tboring?: boolean;\n\tcommand?: string;\n\tdisplayHiddenFilesAndFolders?: boolean;\n\tdisplayLongListing?: boolean;\n\tdisplayStats?: boolean;\n\tgrep?: RegExp;\n\tnodesList?: any[];\n\tpath?: string;\n\trePattern?: RegExp;\n\ttotalDirFound?: number;\n\ttotalDirScanned?: number;\n\ttotalFileFound?: number;\n\ttotalFileScanned?: number;\n\ttype?: string;\n\tignoreExtensions?: string[];\n\tignoreFiles?: string[];\n\tignoreFolders?: string[];\n\tprintMode?: string;\n\tgitIgnoreHandler: GitIgnoreHandler;\n\tignoreGitIgnore?: boolean;\n\tminifyForLLM?: boolean;\n\n\tconstructor({\n\t\tboring,\n\t\tcommand,\n\t\tdot,\n\t\tgrep,\n\t\tignoreCase,\n\t\tshort,\n\t\tpath,\n\t\tpattern,\n\t\tstats,\n\t\ttype,\n\t\tignoreExtension,\n\t\tignoreFile,\n\t\tignoreFolder,\n\t\tprintMode,\n\t\tignoreGitIgnore,\n\t\tminifyForLLM,\n\t}: {\n\t\tboring?: boolean;\n\t\tcommand?: string;\n\t\tdot?: boolean;\n\t\tgrep?: string | RegExp;\n\t\tignoreCase?: boolean;\n\t\tshort?: boolean;\n\t\tpath?: string;\n\t\tpattern?: string;\n\t\tstats?: boolean;\n\t\ttype?: string;\n\t\tignoreExtension?: string[];\n\t\tignoreFile?: string[];\n\t\tignoreFolder?: string[];\n\t\tprintMode?: string;\n\t\tignoreGitIgnore?: boolean;\n\t\tminifyForLLM?: boolean;\n\t}) {\n\t\tthis.path = path;\n\t\tthis.rePattern = pattern\n\t\t\t? new RegExp(pattern, ignoreCase ? \"i\" : \"\")\n\t\t\t: undefined;\n\t\tthis.type = type || STR_TYPE_BOTH;\n\t\tthis.boring = boring;\n\t\tkleur.enabled = !boring;\n\t\tthis.displayLongListing = !short;\n\t\tthis.displayStats = stats;\n\t\tthis.displayHiddenFilesAndFolders = dot;\n\t\tthis.nodesList = [];\n\t\tthis.totalDirScanned = 0;\n\t\tthis.totalFileScanned = 0;\n\t\tthis.totalDirFound = 0;\n\t\tthis.totalFileFound = 0;\n\t\tthis.command = command ? command.trim() : undefined;\n\t\tthis.ignoreExtensions =\n\t\t\t(ignoreExtension && ignoreExtension.map((ext) => ext.toLowerCase())) ||\n\t\t\t[];\n\t\tthis.ignoreFiles = ignoreFile || [];\n\t\tthis.ignoreFolders = ignoreFolder || [];\n\t\tthis.printMode = printMode;\n\t\tthis.ignoreGitIgnore = ignoreGitIgnore;\n\t\tthis.minifyForLLM = minifyForLLM;\n\t\tthis.gitIgnoreHandler = new GitIgnoreHandler();\n\t\ttry {\n\t\t\tthis.grep = grep ? new RegExp(grep, ignoreCase ? \"gi\" : \"g\") : undefined;\n\t\t} catch (error) {\n\t\t\tlogger.error(error);\n\t\t\tprocess.exit(1);\n\t\t}\n\t}\n\n\tshouldIgnoreFolder(directory: string) {\n\t\tconst folderName = basename(directory);\n\t\t// Check for exact folder name match\n\t\tif (this.ignoreFolders && this.ignoreFolders.includes(folderName)) {\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\tshouldIgnoreFile(filePath: string) {\n\t\t// First check if the file is in the ignoreFiles list\n\t\tconst filename = basename(filePath);\n\t\tif (this.ignoreFiles && this.ignoreFiles.includes(filename)) {\n\t\t\treturn true;\n\t\t}\n\n\t\t// Then check if the extension should be ignored\n\t\tif (!this.ignoreExtensions || this.ignoreExtensions.length === 0) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst extension = getFileExtension(filePath);\n\n\t\t// Check for exact extension match\n\t\tif (this.ignoreExtensions.includes(extension)) {\n\t\t\treturn true;\n\t\t}\n\n\t\t// Check for complex patterns like \"min.js\"\n\t\tfor (const pattern of this.ignoreExtensions) {\n\t\t\t// Skip patterns that don't contain a dot\n\t\t\tif (!pattern.includes(\".\")) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Check if the filename ends with the pattern\n\t\t\tif (filename.toLowerCase().endsWith(`.${pattern}`)) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t}\n\n\tfilterHidden(value: string[] | string) {\n\t\tif (this.displayHiddenFilesAndFolders) {\n\t\t\treturn true;\n\t\t}\n\t\treturn value[0] !== \".\";\n\t}\n\n\tasync start(returnResults = false) {\n\t\tif (this.displayStats) {\n\t\t\tperf.start();\n\t\t}\n\t\tawait this.scanFileSystem([this.path]);\n\t\tconst results = await this.postProcessResults(returnResults);\n\n\t\tif (this.displayStats) {\n\t\t\tperf.stop();\n\t\t\tprintStatistics({\n\t\t\t\tduration: perf.results.duration,\n\t\t\t\tgrep: this.grep,\n\t\t\t\tpattern: this.rePattern,\n\t\t\t\ttotalDirScanned: this.totalDirScanned,\n\t\t\t\ttotalDirsFound: this.totalDirFound,\n\t\t\t\ttotalFileScanned: this.totalFileScanned,\n\t\t\t\ttotalFilesFound: this.totalFileFound,\n\t\t\t\ttype: this.type,\n\t\t\t});\n\t\t}\n\t\treturn returnResults ? results : undefined;\n\t}\n\n\tasync scanFileSystem(nodes: string[]) {\n\t\tfor (const node of nodes) {\n\t\t\tlet result: boolean | RegExpExecArray,\n\t\t\t\tfiles: string[],\n\t\t\t\tshortname: string,\n\t\t\t\tstat: fs.Stats;\n\t\t\ttry {\n\t\t\t\tstat = await lstatAsync(node);\n\t\t\t} catch {\n\t\t\t\t// ignore read permission denied errors silently...\n\t\t\t}\n\n\t\t\tconst isDirectory = stat && stat.isDirectory();\n\t\t\tconst isFile = stat && stat.isFile();\n\n\t\t\t// Add this check to respect .gitignore patterns\n\t\t\tif (await this.shouldIgnoreByGitIgnore(node, isDirectory)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (isDirectory && !this.shouldIgnoreFolder(node)) {\n\t\t\t\tthis.totalDirScanned++;\n\n\t\t\t\tresult = checkPattern(this.rePattern, node);\n\t\t\t\tif (result) {\n\t\t\t\t\tthis.totalDirFound++;\n\t\t\t\t\tthis.nodesList.push({\n\t\t\t\t\t\tcommand: this.command,\n\t\t\t\t\t\tmatch: result,\n\t\t\t\t\t\tname: node,\n\t\t\t\t\t\tstat,\n\t\t\t\t\t\ttype: STR_TYPE_DIRECTORY,\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\ttry {\n\t\t\t\t\tfiles = await readdirAsync(node);\n\t\t\t\t\tawait this.scanFileSystem(\n\t\t\t\t\t\tfiles\n\t\t\t\t\t\t\t.filter((element) => this.filterHidden(element))\n\t\t\t\t\t\t\t.map(function (file) {\n\t\t\t\t\t\t\t\treturn join(node, file);\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t);\n\t\t\t\t} catch {\n\t\t\t\t\t// nothing to declare\n\t\t\t\t}\n\t\t\t} else if (isFile) {\n\t\t\t\t// Skip files with ignored extensions\n\t\t\t\tif (this.shouldIgnoreFile(node)) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tthis.totalFileScanned++;\n\t\t\t\tshortname = basename(node);\n\t\t\t\tconst patternResult = checkPattern(this.rePattern, shortname);\n\t\t\t\tif (patternResult) {\n\t\t\t\t\tthis.totalFileFound++;\n\t\t\t\t\tthis.nodesList.push({\n\t\t\t\t\t\tcommand: this.command,\n\t\t\t\t\t\tmatch: patternResult[0],\n\t\t\t\t\t\tname: node,\n\t\t\t\t\t\tstat,\n\t\t\t\t\t\ttype: STR_TYPE_FILE,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tasync readFileContent(filePath: string): Promise<string> {\n\t\ttry {\n\t\t\t// Check if it's a known binary extension\n\t\t\t/* istanbul ignore if */\n\t\t\tif (isBinaryFileExtension(filePath)) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tconst content = await readFileAsync(filePath, \"utf8\");\n\t\t\treturn this.minifyForLLM\n\t\t\t\t? await minifyFileContent(filePath, content)\n\t\t\t\t: content;\n\t\t} catch (_error) {\n\t\t\t/* istanbul ignore next */\n\t\t\treturn null;\n\t\t}\n\t}\n\n\tasync printFilesContent(returnResults: boolean) {\n\t\tconst fileNodes = this.nodesList.filter(\n\t\t\t(node) => node.type === STR_TYPE_FILE,\n\t\t);\n\n\t\tif (this.printMode === \"simple\") {\n\t\t\tfor (const node of fileNodes) {\n\t\t\t\tconst relativePath = relative(this.path, node.name);\n\t\t\t\tif (returnResults) {\n\t\t\t\t\tloggerInMemory.log(`---\\n./${relativePath}\\n---`);\n\t\t\t\t} else {\n\t\t\t\t\tlogger.log(`---\\n./${relativePath}\\n---`);\n\t\t\t\t}\n\t\t\t\tconst content = await this.readFileContent(node.name);\n\t\t\t\tif (returnResults) {\n\t\t\t\t\tloggerInMemory.log(content);\n\t\t\t\t} else {\n\t\t\t\t\tlogger.log(content);\n\t\t\t\t}\n\t\t\t\t// adding a new line after each file content except the last one\n\t\t\t\tif (node !== fileNodes[fileNodes.length - 1]) {\n\t\t\t\t\tif (returnResults) {\n\t\t\t\t\t\tloggerInMemory.log(\"\");\n\t\t\t\t\t} else {\n\t\t\t\t\t\tlogger.log(\"\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (this.printMode === \"xml\") {\n\t\t\tif (returnResults) {\n\t\t\t\tloggerInMemory.log(\"<documents>\");\n\t\t\t} else {\n\t\t\t\tlogger.log(\"<documents>\");\n\t\t\t}\n\n\t\t\tfor (let i = 0; i < fileNodes.length; i++) {\n\t\t\t\tconst node = fileNodes[i];\n\t\t\t\tconst relativePath = relative(this.path, node.name);\n\t\t\t\tconst content = await this.readFileContent(node.name);\n\n\t\t\t\tif (returnResults) {\n\t\t\t\t\tif (content) {\n\t\t\t\t\t\tloggerInMemory.log(`<document index=\"${i + 1}\">`);\n\t\t\t\t\t\tloggerInMemory.log(`<source>./${relativePath}</source>`);\n\t\t\t\t\t\tloggerInMemory.log(\"<document_content>\");\n\t\t\t\t\t\tloggerInMemory.log(content);\n\t\t\t\t\t\tloggerInMemory.log(\"</document_content>\");\n\t\t\t\t\t\tloggerInMemory.log(\"</document>\");\n\t\t\t\t\t}\n\t\t\t\t} else if (content) {\n\t\t\t\t\tlogger.log(`<document index=\"${i + 1}\">`);\n\t\t\t\t\tlogger.log(`<source>./${relativePath}</source>`);\n\t\t\t\t\tlogger.log(\"<document_content>\");\n\t\t\t\t\tlogger.log(content);\n\t\t\t\t\tlogger.log(\"</document_content>\");\n\t\t\t\t\tlogger.log(\"</document>\");\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (returnResults) {\n\t\t\t\tloggerInMemory.log(\"</documents>\");\n\t\t\t} else {\n\t\t\t\tlogger.log(\"</documents>\");\n\t\t\t}\n\t\t}\n\t\tconst results = returnResults ? loggerInMemory.getMemoryLogs() : undefined;\n\t\tloggerInMemory.clearMemoryLogs();\n\t\treturn results;\n\t}\n\n\tasync shouldIgnoreByGitIgnore(\n\t\tnodePath: string,\n\t\tisDirectory: boolean,\n\t): Promise<boolean> {\n\t\tif (this.ignoreGitIgnore) {\n\t\t\treturn false;\n\t\t}\n\t\treturn this.gitIgnoreHandler.isIgnored(nodePath, isDirectory);\n\t}\n\n\tasync postProcessResults(returnResults: boolean) {\n\t\tif (this.grep) {\n\t\t\t/**\n\t\t\t * Resetting the number of files found, since we want to\n\t\t\t * show how many matched the grep, not how many matched the\n\t\t\t * pattern (in the file name).\n\t\t\t */\n\t\t\tthis.totalFileFound = 0;\n\t\t}\n\n\t\t// If printMode is enabled, handle file content printing and return\n\t\tif (this.printMode && [\"simple\", \"xml\"].includes(this.printMode)) {\n\t\t\treturn await this.printFilesContent(returnResults);\n\t\t}\n\n\t\t/* istanbul ignore if */\n\t\tif (!this.boring) {\n\t\t\tlogger.log();\n\t\t}\n\n\t\tfor (const node of this.nodesList) {\n\t\t\tif (\n\t\t\t\t(this.type === STR_TYPE_FILE && node.type === STR_TYPE_FILE) ||\n\t\t\t\t(this.type === STR_TYPE_DIRECTORY &&\n\t\t\t\t\tnode.type === STR_TYPE_DIRECTORY) ||\n\t\t\t\tthis.type === STR_TYPE_BOTH\n\t\t\t) {\n\t\t\t\tlet list: {\n\t\t\t\t\t\tgroup?: string;\n\t\t\t\t\t\tmdate?: string;\n\t\t\t\t\t\tmode?: string;\n\t\t\t\t\t\towner?: string;\n\t\t\t\t\t\tsize?: string;\n\t\t\t\t\t} = {\n\t\t\t\t\t\tgroup: \"\",\n\t\t\t\t\t\tmdate: \"\",\n\t\t\t\t\t\tmode: \"\",\n\t\t\t\t\t\towner: \"\",\n\t\t\t\t\t\tsize: \"\",\n\t\t\t\t\t},\n\t\t\t\t\tname: string,\n\t\t\t\t\tseparator: string = \"\";\n\n\t\t\t\t/* istanbul ignore if */\n\t\t\t\tif (this.displayLongListing) {\n\t\t\t\t\tlist = await formatLongListings(node.stat, node.type);\n\t\t\t\t\tseparator = \"\\t\";\n\t\t\t\t}\n\n\t\t\t\tconst color = node.type === STR_TYPE_FILE ? kleur.gray : kleur.blue;\n\t\t\t\tname = relative(this.path, node.name);\n\n\t\t\t\tif (node.match) {\n\t\t\t\t\tconst matchStr = String(node.match); // Ensure match is a string\n\t\t\t\t\tconst match = new RegExp(matchStr, \"g\");\n\t\t\t\t\tconst highlightedMatch = kleur.black().bgYellow(matchStr);\n\t\t\t\t\tname = color(name.replace(match, highlightedMatch));\n\t\t\t\t} else {\n\t\t\t\t\tname = color(name);\n\t\t\t\t}\n\n\t\t\t\tif (this.grep && node.type === STR_TYPE_FILE) {\n\t\t\t\t\tconst { totalMatchingLines, results } = await runGrepOnNode(\n\t\t\t\t\t\tnode.name,\n\t\t\t\t\t\tthis.grep,\n\t\t\t\t\t);\n\t\t\t\t\t/* istanbul ignore else */\n\t\t\t\t\tif (totalMatchingLines) {\n\t\t\t\t\t\tthis.totalFileFound++;\n\t\t\t\t\t\tconst occurrences = plur(\"occurrence\", totalMatchingLines);\n\n\t\t\t\t\t\tlogger.log(\n\t\t\t\t\t\t\t` %s${separator}%s${separator}%s${separator}%s${separator}%s`,\n\t\t\t\t\t\t\tlist.mode.trim(),\n\t\t\t\t\t\t\tlist.owner.trim(),\n\t\t\t\t\t\t\tlist.size.trim(),\n\t\t\t\t\t\t\tlist.mdate,\n\t\t\t\t\t\t\tname,\n\t\t\t\t\t\t\t`(${kleur.white(totalMatchingLines)} ${occurrences})`,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tlogger.log(`${results.join(\"\\n\")}\\n`);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t/* istanbul ignore next */\n\t\t\t\t\tif (!this.grep) {\n\t\t\t\t\t\tlogger.log(\n\t\t\t\t\t\t\t` %s${separator}%s${separator}%s${separator}%s${separator}%s`,\n\t\t\t\t\t\t\tlist.mode.trim(),\n\t\t\t\t\t\t\tlist.owner.trim(),\n\t\t\t\t\t\t\tlist.size.trim(),\n\t\t\t\t\t\t\tlist.mdate,\n\t\t\t\t\t\t\tname,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tif (node.command) {\n\t\t\t\t\t\t\tawait runCommandOnNode(node.name, node.command);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n"],"names":["basename","join","relative","promisify","Logger","Performance","fs","kleur","plur","GitIgnoreHandler","minifyFileContent","STR_TYPE_BOTH","STR_TYPE_DIRECTORY","STR_TYPE_FILE","checkPattern","formatLongListings","getFileExtension","isBinaryFileExtension","printStatistics","runCommandOnNode","runGrepOnNode","lstatAsync","lstat","readdirAsync","readdir","readFileAsync","readFile","perf","logger","boring","process","env","NODE_ENV","loggerInMemory","inMemory","Search","command","displayHiddenFilesAndFolders","displayLongListing","displayStats","grep","nodesList","path","rePattern","totalDirFound","totalDirScanned","totalFileFound","totalFileScanned","type","ignoreExtensions","ignoreFiles","ignoreFolders","printMode","gitIgnoreHandler","ignoreGitIgnore","minifyForLLM","constructor","dot","ignoreCase","short","pattern","stats","ignoreExtension","ignoreFile","ignoreFolder","RegExp","undefined","enabled","trim","map","ext","toLowerCase","error","exit","shouldIgnoreFolder","directory","folderName","includes","shouldIgnoreFile","filePath","filename","length","extension","endsWith","filterHidden","value","start","returnResults","scanFileSystem","results","postProcessResults","stop","duration","totalDirsFound","totalFilesFound","nodes","node","result","files","shortname","stat","isDirectory","isFile","shouldIgnoreByGitIgnore","push","match","name","filter","element","file","patternResult","readFileContent","content","_error","printFilesContent","fileNodes","relativePath","log","i","getMemoryLogs","clearMemoryLogs","nodePath","isIgnored","list","group","mdate","mode","owner","size","separator","color","gray","blue","matchStr","String","highlightedMatch","black","bgYellow","replace","totalMatchingLines","occurrences","white"],"mappings":"AAAA,SAASA,QAAQ,EAAWC,IAAI,EAAEC,QAAQ,QAAQ,YAAY;AAC9D,SAASC,SAAS,QAAQ,YAAY;AACtC,SAASC,MAAM,QAAQ,mBAAmB;AAC1C,SAASC,WAAW,QAAQ,iBAAiB;AAC7C,OAAOC,QAAQ,WAAW;AAC1B,OAAOC,WAAW,QAAQ;AAC1B,OAAOC,UAAU,OAAO;AAExB,SAASC,gBAAgB,QAAQ,wBAAwB;AACzD,SAAoBC,iBAAiB,QAAkB,iBAAiB;AACxE,SACCC,aAAa,EACbC,kBAAkB,EAClBC,aAAa,EACbC,YAAY,EACZC,kBAAkB,EAClBC,gBAAgB,EAChBC,qBAAqB,EACrBC,eAAe,EACfC,gBAAgB,EAChBC,aAAa,QACP,iBAAiB;AAExB,MAAMC,aAAalB,UAAUG,GAAGgB,KAAK;AACrC,MAAMC,eAAepB,UAAUG,GAAGkB,OAAO;AACzC,MAAMC,gBAAgBtB,UAAUG,GAAGoB,QAAQ;AAC3C,MAAMC,OAAO,IAAItB;AACjB,MAAMuB,SAAS,IAAIxB,OAAO;IACzByB,QAAQC,QAAQC,GAAG,CAACC,QAAQ,KAAK;AAClC;AACA,MAAMC,iBAAiB,IAAI7B,OAAO;IACjC8B,UAAU;AACX;AAEA,OAAO,MAAMC;IACZN,OAAiB;IACjBO,QAAiB;IACjBC,6BAAuC;IACvCC,mBAA6B;IAC7BC,aAAuB;IACvBC,KAAc;IACdC,UAAkB;IAClBC,KAAc;IACdC,UAAmB;IACnBC,cAAuB;IACvBC,gBAAyB;IACzBC,eAAwB;IACxBC,iBAA0B;IAC1BC,KAAc;IACdC,iBAA4B;IAC5BC,YAAuB;IACvBC,cAAyB;IACzBC,UAAmB;IACnBC,iBAAmC;IACnCC,gBAA0B;IAC1BC,aAAuB;IAEvBC,YAAY,EACX3B,MAAM,EACNO,OAAO,EACPqB,GAAG,EACHjB,IAAI,EACJkB,UAAU,EACVC,KAAK,EACLjB,IAAI,EACJkB,OAAO,EACPC,KAAK,EACLb,IAAI,EACJc,eAAe,EACfC,UAAU,EACVC,YAAY,EACZZ,SAAS,EACTE,eAAe,EACfC,YAAY,EAkBZ,CAAE;QACF,IAAI,CAACb,IAAI,GAAGA;QACZ,IAAI,CAACC,SAAS,GAAGiB,UACd,IAAIK,OAAOL,SAASF,aAAa,MAAM,MACvCQ;QACH,IAAI,CAAClB,IAAI,GAAGA,QAAQrC;QACpB,IAAI,CAACkB,MAAM,GAAGA;QACdtB,MAAM4D,OAAO,GAAG,CAACtC;QACjB,IAAI,CAACS,kBAAkB,GAAG,CAACqB;QAC3B,IAAI,CAACpB,YAAY,GAAGsB;QACpB,IAAI,CAACxB,4BAA4B,GAAGoB;QACpC,IAAI,CAAChB,SAAS,GAAG,EAAE;QACnB,IAAI,CAACI,eAAe,GAAG;QACvB,IAAI,CAACE,gBAAgB,GAAG;QACxB,IAAI,CAACH,aAAa,GAAG;QACrB,IAAI,CAACE,cAAc,GAAG;QACtB,IAAI,CAACV,OAAO,GAAGA,UAAUA,QAAQgC,IAAI,KAAKF;QAC1C,IAAI,CAACjB,gBAAgB,GACpB,AAACa,mBAAmBA,gBAAgBO,GAAG,CAAC,CAACC,MAAQA,IAAIC,WAAW,OAChE,EAAE;QACH,IAAI,CAACrB,WAAW,GAAGa,cAAc,EAAE;QACnC,IAAI,CAACZ,aAAa,GAAGa,gBAAgB,EAAE;QACvC,IAAI,CAACZ,SAAS,GAAGA;QACjB,IAAI,CAACE,eAAe,GAAGA;QACvB,IAAI,CAACC,YAAY,GAAGA;QACpB,IAAI,CAACF,gBAAgB,GAAG,IAAI5C;QAC5B,IAAI;YACH,IAAI,CAAC+B,IAAI,GAAGA,OAAO,IAAIyB,OAAOzB,MAAMkB,aAAa,OAAO,OAAOQ;QAChE,EAAE,OAAOM,OAAO;YACf5C,OAAO4C,KAAK,CAACA;YACb1C,QAAQ2C,IAAI,CAAC;QACd;IACD;IAEAC,mBAAmBC,SAAiB,EAAE;QACrC,MAAMC,aAAa5E,SAAS2E;QAC5B,oCAAoC;QACpC,IAAI,IAAI,CAACxB,aAAa,IAAI,IAAI,CAACA,aAAa,CAAC0B,QAAQ,CAACD,aAAa;YAClE,OAAO;QACR;QACA,OAAO;IACR;IAEAE,iBAAiBC,QAAgB,EAAE;QAClC,qDAAqD;QACrD,MAAMC,WAAWhF,SAAS+E;QAC1B,IAAI,IAAI,CAAC7B,WAAW,IAAI,IAAI,CAACA,WAAW,CAAC2B,QAAQ,CAACG,WAAW;YAC5D,OAAO;QACR;QAEA,gDAAgD;QAChD,IAAI,CAAC,IAAI,CAAC/B,gBAAgB,IAAI,IAAI,CAACA,gBAAgB,CAACgC,MAAM,KAAK,GAAG;YACjE,OAAO;QACR;QAEA,MAAMC,YAAYlE,iBAAiB+D;QAEnC,kCAAkC;QAClC,IAAI,IAAI,CAAC9B,gBAAgB,CAAC4B,QAAQ,CAACK,YAAY;YAC9C,OAAO;QACR;QAEA,2CAA2C;QAC3C,KAAK,MAAMtB,WAAW,IAAI,CAACX,gBAAgB,CAAE;YAC5C,yCAAyC;YACzC,IAAI,CAACW,QAAQiB,QAAQ,CAAC,MAAM;gBAC3B;YACD;YAEA,8CAA8C;YAC9C,IAAIG,SAAST,WAAW,GAAGY,QAAQ,CAAC,CAAC,CAAC,EAAEvB,SAAS,GAAG;gBACnD,OAAO;YACR;QACD;QAEA,OAAO;IACR;IAEAwB,aAAaC,KAAwB,EAAE;QACtC,IAAI,IAAI,CAAChD,4BAA4B,EAAE;YACtC,OAAO;QACR;QACA,OAAOgD,KAAK,CAAC,EAAE,KAAK;IACrB;IAEA,MAAMC,MAAMC,gBAAgB,KAAK,EAAE;QAClC,IAAI,IAAI,CAAChD,YAAY,EAAE;YACtBZ,KAAK2D,KAAK;QACX;QACA,MAAM,IAAI,CAACE,cAAc,CAAC;YAAC,IAAI,CAAC9C,IAAI;SAAC;QACrC,MAAM+C,UAAU,MAAM,IAAI,CAACC,kBAAkB,CAACH;QAE9C,IAAI,IAAI,CAAChD,YAAY,EAAE;YACtBZ,KAAKgE,IAAI;YACTzE,gBAAgB;gBACf0E,UAAUjE,KAAK8D,OAAO,CAACG,QAAQ;gBAC/BpD,MAAM,IAAI,CAACA,IAAI;gBACfoB,SAAS,IAAI,CAACjB,SAAS;gBACvBE,iBAAiB,IAAI,CAACA,eAAe;gBACrCgD,gBAAgB,IAAI,CAACjD,aAAa;gBAClCG,kBAAkB,IAAI,CAACA,gBAAgB;gBACvC+C,iBAAiB,IAAI,CAAChD,cAAc;gBACpCE,MAAM,IAAI,CAACA,IAAI;YAChB;QACD;QACA,OAAOuC,gBAAgBE,UAAUvB;IAClC;IAEA,MAAMsB,eAAeO,KAAe,EAAE;QACrC,KAAK,MAAMC,QAAQD,MAAO;YACzB,IAAIE,QACHC,OACAC,WACAC;YACD,IAAI;gBACHA,OAAO,MAAM/E,WAAW2E;YACzB,EAAE,OAAM;YACP,mDAAmD;YACpD;YAEA,MAAMK,cAAcD,QAAQA,KAAKC,WAAW;YAC5C,MAAMC,SAASF,QAAQA,KAAKE,MAAM;YAElC,gDAAgD;YAChD,IAAI,MAAM,IAAI,CAACC,uBAAuB,CAACP,MAAMK,cAAc;gBAC1D;YACD;YAEA,IAAIA,eAAe,CAAC,IAAI,CAAC3B,kBAAkB,CAACsB,OAAO;gBAClD,IAAI,CAACnD,eAAe;gBAEpBoD,SAASnF,aAAa,IAAI,CAAC6B,SAAS,EAAEqD;gBACtC,IAAIC,QAAQ;oBACX,IAAI,CAACrD,aAAa;oBAClB,IAAI,CAACH,SAAS,CAAC+D,IAAI,CAAC;wBACnBpE,SAAS,IAAI,CAACA,OAAO;wBACrBqE,OAAOR;wBACPS,MAAMV;wBACNI;wBACApD,MAAMpC;oBACP;gBACD;gBAEA,IAAI;oBACHsF,QAAQ,MAAM3E,aAAayE;oBAC3B,MAAM,IAAI,CAACR,cAAc,CACxBU,MACES,MAAM,CAAC,CAACC,UAAY,IAAI,CAACxB,YAAY,CAACwB,UACtCvC,GAAG,CAAC,SAAUwC,IAAI;wBAClB,OAAO5G,KAAK+F,MAAMa;oBACnB;gBAEH,EAAE,OAAM;gBACP,qBAAqB;gBACtB;YACD,OAAO,IAAIP,QAAQ;gBAClB,qCAAqC;gBACrC,IAAI,IAAI,CAACxB,gBAAgB,CAACkB,OAAO;oBAChC;gBACD;gBAEA,IAAI,CAACjD,gBAAgB;gBACrBoD,YAAYnG,SAASgG;gBACrB,MAAMc,gBAAgBhG,aAAa,IAAI,CAAC6B,SAAS,EAAEwD;gBACnD,IAAIW,eAAe;oBAClB,IAAI,CAAChE,cAAc;oBACnB,IAAI,CAACL,SAAS,CAAC+D,IAAI,CAAC;wBACnBpE,SAAS,IAAI,CAACA,OAAO;wBACrBqE,OAAOK,aAAa,CAAC,EAAE;wBACvBJ,MAAMV;wBACNI;wBACApD,MAAMnC;oBACP;gBACD;YACD;QACD;IACD;IAEA,MAAMkG,gBAAgBhC,QAAgB,EAAmB;QACxD,IAAI;YACH,yCAAyC;YACzC,sBAAsB,GACtB,IAAI9D,sBAAsB8D,WAAW;gBACpC,OAAO;YACR;YACA,MAAMiC,UAAU,MAAMvF,cAAcsD,UAAU;YAC9C,OAAO,IAAI,CAACxB,YAAY,GACrB,MAAM7C,kBAAkBqE,UAAUiC,WAClCA;QACJ,EAAE,OAAOC,QAAQ;YAChB,wBAAwB,GACxB,OAAO;QACR;IACD;IAEA,MAAMC,kBAAkB3B,aAAsB,EAAE;QAC/C,MAAM4B,YAAY,IAAI,CAAC1E,SAAS,CAACkE,MAAM,CACtC,CAACX,OAASA,KAAKhD,IAAI,KAAKnC;QAGzB,IAAI,IAAI,CAACuC,SAAS,KAAK,UAAU;YAChC,KAAK,MAAM4C,QAAQmB,UAAW;gBAC7B,MAAMC,eAAelH,SAAS,IAAI,CAACwC,IAAI,EAAEsD,KAAKU,IAAI;gBAClD,IAAInB,eAAe;oBAClBtD,eAAeoF,GAAG,CAAC,CAAC,OAAO,EAAED,aAAa,KAAK,CAAC;gBACjD,OAAO;oBACNxF,OAAOyF,GAAG,CAAC,CAAC,OAAO,EAAED,aAAa,KAAK,CAAC;gBACzC;gBACA,MAAMJ,UAAU,MAAM,IAAI,CAACD,eAAe,CAACf,KAAKU,IAAI;gBACpD,IAAInB,eAAe;oBAClBtD,eAAeoF,GAAG,CAACL;gBACpB,OAAO;oBACNpF,OAAOyF,GAAG,CAACL;gBACZ;gBACA,gEAAgE;gBAChE,IAAIhB,SAASmB,SAAS,CAACA,UAAUlC,MAAM,GAAG,EAAE,EAAE;oBAC7C,IAAIM,eAAe;wBAClBtD,eAAeoF,GAAG,CAAC;oBACpB,OAAO;wBACNzF,OAAOyF,GAAG,CAAC;oBACZ;gBACD;YACD;QACD,OAAO,IAAI,IAAI,CAACjE,SAAS,KAAK,OAAO;YACpC,IAAImC,eAAe;gBAClBtD,eAAeoF,GAAG,CAAC;YACpB,OAAO;gBACNzF,OAAOyF,GAAG,CAAC;YACZ;YAEA,IAAK,IAAIC,IAAI,GAAGA,IAAIH,UAAUlC,MAAM,EAAEqC,IAAK;gBAC1C,MAAMtB,OAAOmB,SAAS,CAACG,EAAE;gBACzB,MAAMF,eAAelH,SAAS,IAAI,CAACwC,IAAI,EAAEsD,KAAKU,IAAI;gBAClD,MAAMM,UAAU,MAAM,IAAI,CAACD,eAAe,CAACf,KAAKU,IAAI;gBAEpD,IAAInB,eAAe;oBAClB,IAAIyB,SAAS;wBACZ/E,eAAeoF,GAAG,CAAC,CAAC,iBAAiB,EAAEC,IAAI,EAAE,EAAE,CAAC;wBAChDrF,eAAeoF,GAAG,CAAC,CAAC,UAAU,EAAED,aAAa,SAAS,CAAC;wBACvDnF,eAAeoF,GAAG,CAAC;wBACnBpF,eAAeoF,GAAG,CAACL;wBACnB/E,eAAeoF,GAAG,CAAC;wBACnBpF,eAAeoF,GAAG,CAAC;oBACpB;gBACD,OAAO,IAAIL,SAAS;oBACnBpF,OAAOyF,GAAG,CAAC,CAAC,iBAAiB,EAAEC,IAAI,EAAE,EAAE,CAAC;oBACxC1F,OAAOyF,GAAG,CAAC,CAAC,UAAU,EAAED,aAAa,SAAS,CAAC;oBAC/CxF,OAAOyF,GAAG,CAAC;oBACXzF,OAAOyF,GAAG,CAACL;oBACXpF,OAAOyF,GAAG,CAAC;oBACXzF,OAAOyF,GAAG,CAAC;gBACZ;YACD;YAEA,IAAI9B,eAAe;gBAClBtD,eAAeoF,GAAG,CAAC;YACpB,OAAO;gBACNzF,OAAOyF,GAAG,CAAC;YACZ;QACD;QACA,MAAM5B,UAAUF,gBAAgBtD,eAAesF,aAAa,KAAKrD;QACjEjC,eAAeuF,eAAe;QAC9B,OAAO/B;IACR;IAEA,MAAMc,wBACLkB,QAAgB,EAChBpB,WAAoB,EACD;QACnB,IAAI,IAAI,CAAC/C,eAAe,EAAE;YACzB,OAAO;QACR;QACA,OAAO,IAAI,CAACD,gBAAgB,CAACqE,SAAS,CAACD,UAAUpB;IAClD;IAEA,MAAMX,mBAAmBH,aAAsB,EAAE;QAChD,IAAI,IAAI,CAAC/C,IAAI,EAAE;YACd;;;;IAIC,GACD,IAAI,CAACM,cAAc,GAAG;QACvB;QAEA,mEAAmE;QACnE,IAAI,IAAI,CAACM,SAAS,IAAI;YAAC;YAAU;SAAM,CAACyB,QAAQ,CAAC,IAAI,CAACzB,SAAS,GAAG;YACjE,OAAO,MAAM,IAAI,CAAC8D,iBAAiB,CAAC3B;QACrC;QAEA,sBAAsB,GACtB,IAAI,CAAC,IAAI,CAAC1D,MAAM,EAAE;YACjBD,OAAOyF,GAAG;QACX;QAEA,KAAK,MAAMrB,QAAQ,IAAI,CAACvD,SAAS,CAAE;YAClC,IACC,AAAC,IAAI,CAACO,IAAI,KAAKnC,iBAAiBmF,KAAKhD,IAAI,KAAKnC,iBAC7C,IAAI,CAACmC,IAAI,KAAKpC,sBACdoF,KAAKhD,IAAI,KAAKpC,sBACf,IAAI,CAACoC,IAAI,KAAKrC,eACb;gBACD,IAAIgH,OAMC;oBACHC,OAAO;oBACPC,OAAO;oBACPC,MAAM;oBACNC,OAAO;oBACPC,MAAM;gBACP,GACAtB,MACAuB,YAAoB;gBAErB,sBAAsB,GACtB,IAAI,IAAI,CAAC3F,kBAAkB,EAAE;oBAC5BqF,OAAO,MAAM5G,mBAAmBiF,KAAKI,IAAI,EAAEJ,KAAKhD,IAAI;oBACpDiF,YAAY;gBACb;gBAEA,MAAMC,QAAQlC,KAAKhD,IAAI,KAAKnC,gBAAgBN,MAAM4H,IAAI,GAAG5H,MAAM6H,IAAI;gBACnE1B,OAAOxG,SAAS,IAAI,CAACwC,IAAI,EAAEsD,KAAKU,IAAI;gBAEpC,IAAIV,KAAKS,KAAK,EAAE;oBACf,MAAM4B,WAAWC,OAAOtC,KAAKS,KAAK,GAAG,2BAA2B;oBAChE,MAAMA,QAAQ,IAAIxC,OAAOoE,UAAU;oBACnC,MAAME,mBAAmBhI,MAAMiI,KAAK,GAAGC,QAAQ,CAACJ;oBAChD3B,OAAOwB,MAAMxB,KAAKgC,OAAO,CAACjC,OAAO8B;gBAClC,OAAO;oBACN7B,OAAOwB,MAAMxB;gBACd;gBAEA,IAAI,IAAI,CAAClE,IAAI,IAAIwD,KAAKhD,IAAI,KAAKnC,eAAe;oBAC7C,MAAM,EAAE8H,kBAAkB,EAAElD,OAAO,EAAE,GAAG,MAAMrE,cAC7C4E,KAAKU,IAAI,EACT,IAAI,CAAClE,IAAI;oBAEV,wBAAwB,GACxB,IAAImG,oBAAoB;wBACvB,IAAI,CAAC7F,cAAc;wBACnB,MAAM8F,cAAcpI,KAAK,cAAcmI;wBAEvC/G,OAAOyF,GAAG,CACT,CAAC,GAAG,EAAEY,UAAU,EAAE,EAAEA,UAAU,EAAE,EAAEA,UAAU,EAAE,EAAEA,UAAU,EAAE,CAAC,EAC7DN,KAAKG,IAAI,CAAC1D,IAAI,IACduD,KAAKI,KAAK,CAAC3D,IAAI,IACfuD,KAAKK,IAAI,CAAC5D,IAAI,IACduD,KAAKE,KAAK,EACVnB,MACA,CAAC,CAAC,EAAEnG,MAAMsI,KAAK,CAACF,oBAAoB,CAAC,EAAEC,YAAY,CAAC,CAAC;wBAEtDhH,OAAOyF,GAAG,CAAC,GAAG5B,QAAQxF,IAAI,CAAC,MAAM,EAAE,CAAC;oBACrC;gBACD,OAAO;oBACN,wBAAwB,GACxB,IAAI,CAAC,IAAI,CAACuC,IAAI,EAAE;wBACfZ,OAAOyF,GAAG,CACT,CAAC,GAAG,EAAEY,UAAU,EAAE,EAAEA,UAAU,EAAE,EAAEA,UAAU,EAAE,EAAEA,UAAU,EAAE,CAAC,EAC7DN,KAAKG,IAAI,CAAC1D,IAAI,IACduD,KAAKI,KAAK,CAAC3D,IAAI,IACfuD,KAAKK,IAAI,CAAC5D,IAAI,IACduD,KAAKE,KAAK,EACVnB;wBAED,IAAIV,KAAK5D,OAAO,EAAE;4BACjB,MAAMjB,iBAAiB6E,KAAKU,IAAI,EAAEV,KAAK5D,OAAO;wBAC/C;oBACD;gBACD;YACD;QACD;IACD;AACD"}
package/dist/index.d.ts CHANGED
@@ -5,6 +5,7 @@
5
5
  export * from "./core";
6
6
  export * from "./defaults";
7
7
  export * from "./gitIgnoreHandler";
8
+ export * from "./minifiers";
8
9
  export * from "./parse";
9
10
  export * from "./search";
10
11
  export * from "./utilities";
@@ -0,0 +1,4 @@
1
+ export declare function minifyImports(content: string): string;
2
+ export declare function minifyJs(content: string): string;
3
+ export declare function minifyCss(content: string): string;
4
+ export declare function minifyFileContent(filePath: string, content: string): Promise<string>;
@@ -0,0 +1,110 @@
1
+ import { v4 as uuidv4 } from "uuid";
2
+ import { getFileExtension } from "./utilities.js";
3
+ export function minifyImports(content) {
4
+ return content.replace(/(import\s*\{)([^}]*?)(\}\s*from)/g, (_match, _importStart, importItems, _importEnd)=>{
5
+ // Process the items being imported
6
+ const cleanedItems = importItems.split(",").map((item)=>{
7
+ // Handle 'type' keyword specifically
8
+ return item.trim().replace(/(\btype\b)\s+/, "$1");
9
+ }).join(",");
10
+ return `import {${cleanedItems}} from`;
11
+ });
12
+ }
13
+ export function minifyJs(content) {
14
+ // Store template literals and regular expressions to protect them from minification
15
+ const tokenPrefix = `__PROTECTED_${uuidv4()}_`;
16
+ const protectedSegments = [];
17
+ // Function to create a unique token for each protected segment
18
+ const createToken = (index)=>`${tokenPrefix}${index}__`;
19
+ // Function to protect a segment of code with a custom handler
20
+ const protect = (pattern, handler)=>{
21
+ content = content.replace(pattern, (match)=>{
22
+ // If a handler is provided, use it to determine if we should protect this match
23
+ if (handler && !handler(match)) {
24
+ return ""; // Return empty string for JSDoc comments we don't want to keep
25
+ }
26
+ const index = protectedSegments.length;
27
+ protectedSegments.push(match);
28
+ return createToken(index);
29
+ });
30
+ };
31
+ // Protect template literals
32
+ protect(/`[\s\S]*?`/g);
33
+ // Protect regular expressions
34
+ // This regex pattern matches JavaScript regular expressions while avoiding division operators
35
+ protect(/(?<![a-zA-Z0-9_$])\/(?![*+?\/])(?:[^\r\n\[/\\]|\\.|\[(?:[^\r\n\]\\]|\\.)*\])+\/[gimyus]*/g);
36
+ // Protect important JSDoc comments
37
+ protect(/\/\*\*[\s\S]*?\*\//g, (match)=>{
38
+ return match.includes("@param") || match.includes("@returns") || match.includes("@description");
39
+ });
40
+ // Remove comments (both single-line and multi-line)
41
+ content = content.replace(/\/\/.*$/gm, ""); // Remove single-line comments
42
+ content = content.replace(/\/\*[\s\S]*?\*\//g, ""); // Remove multi-line comments
43
+ // Compact import statements
44
+ content = minifyImports(content);
45
+ // Remove extra whitespace
46
+ content = content.replace(/^\s+/gm, ""); // Remove leading whitespace
47
+ content = content.replace(/\s+$/gm, ""); // Remove trailing whitespace
48
+ content = content.replace(/\s{2,}/g, " "); // Replace multiple spaces with a single space
49
+ // Compact newlines ( we protected template literals before)
50
+ content = content.replace(/\n+/g, " ");
51
+ // Replace semicolon + space with just semicolon
52
+ content = content.replace(/;\s+/g, ";");
53
+ // Replace colon + space with just colon
54
+ content = content.replace(/,\s+/g, ",");
55
+ // Remove spaces around operators (we protected regex operators before)
56
+ content = content.replace(/\s+([+\-*/%=&|<>!?:;,])\s+/g, "$1");
57
+ // Handle spaces around parentheses and brackets
58
+ content = content.replace(/\(\s+/g, "(");
59
+ content = content.replace(/\s+\)/g, ")");
60
+ content = content.replace(/\[\s+/g, "[");
61
+ content = content.replace(/\s+\]/g, "]");
62
+ // Handle spaces in all curly braces (for object literals, destructuring, etc.)
63
+ content = content.replace(/\{\s+/g, "{");
64
+ content = content.replace(/\s+\}/g, "}");
65
+ // Restore protected segments
66
+ // We need to handle nested tokens, so we'll iterate until all tokens are replaced
67
+ let previousContent = "";
68
+ while(previousContent !== content){
69
+ previousContent = content;
70
+ // Sort indices in descending order to handle nested tokens correctly
71
+ const indices = Array.from({
72
+ length: protectedSegments.length
73
+ }, (_, i)=>i).sort((a, b)=>b - a);
74
+ for (const index of indices){
75
+ const token = createToken(index);
76
+ const segment = protectedSegments[index];
77
+ // Use global replacement to catch all instances
78
+ const tokenRegex = new RegExp(token.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "g");
79
+ content = content.replace(tokenRegex, ()=>segment);
80
+ }
81
+ }
82
+ return content;
83
+ }
84
+ export function minifyCss(content) {
85
+ // Remove CSS comments
86
+ content = content.replace(/\/\*[\s\S]*?\*\//g, "");
87
+ // Remove extra whitespace
88
+ content = content.replace(/\s+/g, " ");
89
+ content = content.replace(/\s*{\s*/g, "{");
90
+ content = content.replace(/\s*}\s*/g, "}");
91
+ content = content.replace(/\s*:\s*/g, ":");
92
+ content = content.replace(/\s*;\s*/g, ";");
93
+ content = content.replace(/\s*,\s*/g, ",");
94
+ return content;
95
+ }
96
+ export async function minifyFileContent(filePath, content) {
97
+ if (!content || content.length < 100) {
98
+ return content;
99
+ }
100
+ const fileExtension = getFileExtension(filePath);
101
+ if (content && content.length > 0 && (fileExtension.endsWith("js") || fileExtension.endsWith("ts") || /* istanbul ignore next */ fileExtension.endsWith("jsx") || /* istanbul ignore next */ fileExtension.endsWith("tsx"))) {
102
+ return minifyJs(content);
103
+ }
104
+ /* istanbul ignore next */ if (content && content.length > 0 && fileExtension.endsWith("css")) {
105
+ return minifyCss(content);
106
+ }
107
+ return content;
108
+ }
109
+
110
+ //# sourceMappingURL=minifiers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/minifiers.ts"],"sourcesContent":["import { v4 as uuidv4 } from \"uuid\";\nimport { getFileExtension } from \"./utilities.js\";\n\nexport function minifyImports(content: string): string {\n\treturn content.replace(\n\t\t/(import\\s*\\{)([^}]*?)(\\}\\s*from)/g,\n\t\t(_match, _importStart, importItems, _importEnd) => {\n\t\t\t// Process the items being imported\n\t\t\tconst cleanedItems = importItems\n\t\t\t\t.split(\",\")\n\t\t\t\t.map((item) => {\n\t\t\t\t\t// Handle 'type' keyword specifically\n\t\t\t\t\treturn item.trim().replace(/(\\btype\\b)\\s+/, \"$1\");\n\t\t\t\t})\n\t\t\t\t.join(\",\");\n\n\t\t\treturn `import {${cleanedItems}} from`;\n\t\t},\n\t);\n}\n\nexport function minifyJs(content: string): string {\n\t// Store template literals and regular expressions to protect them from minification\n\tconst tokenPrefix = `__PROTECTED_${uuidv4()}_`;\n\tconst protectedSegments: string[] = [];\n\n\t// Function to create a unique token for each protected segment\n\tconst createToken = (index: number) => `${tokenPrefix}${index}__`;\n\n\t// Function to protect a segment of code with a custom handler\n\tconst protect = (pattern: RegExp, handler?: (match: string) => boolean) => {\n\t\tcontent = content.replace(pattern, (match) => {\n\t\t\t// If a handler is provided, use it to determine if we should protect this match\n\t\t\tif (handler && !handler(match)) {\n\t\t\t\treturn \"\"; // Return empty string for JSDoc comments we don't want to keep\n\t\t\t}\n\t\t\tconst index = protectedSegments.length;\n\t\t\tprotectedSegments.push(match);\n\t\t\treturn createToken(index);\n\t\t});\n\t};\n\n\t// Protect template literals\n\tprotect(/`[\\s\\S]*?`/g);\n\n\t// Protect regular expressions\n\t// This regex pattern matches JavaScript regular expressions while avoiding division operators\n\tprotect(\n\t\t/(?<![a-zA-Z0-9_$])\\/(?![*+?\\/])(?:[^\\r\\n\\[/\\\\]|\\\\.|\\[(?:[^\\r\\n\\]\\\\]|\\\\.)*\\])+\\/[gimyus]*/g,\n\t);\n\n\t// Protect important JSDoc comments\n\tprotect(/\\/\\*\\*[\\s\\S]*?\\*\\//g, (match) => {\n\t\treturn (\n\t\t\tmatch.includes(\"@param\") ||\n\t\t\tmatch.includes(\"@returns\") ||\n\t\t\tmatch.includes(\"@description\")\n\t\t);\n\t});\n\n\t// Remove comments (both single-line and multi-line)\n\tcontent = content.replace(/\\/\\/.*$/gm, \"\"); // Remove single-line comments\n\tcontent = content.replace(/\\/\\*[\\s\\S]*?\\*\\//g, \"\"); // Remove multi-line comments\n\n\t// Compact import statements\n\tcontent = minifyImports(content);\n\n\t// Remove extra whitespace\n\tcontent = content.replace(/^\\s+/gm, \"\"); // Remove leading whitespace\n\tcontent = content.replace(/\\s+$/gm, \"\"); // Remove trailing whitespace\n\tcontent = content.replace(/\\s{2,}/g, \" \"); // Replace multiple spaces with a single space\n\n\t// Compact newlines ( we protected template literals before)\n\tcontent = content.replace(/\\n+/g, \" \");\n\n\t// Replace semicolon + space with just semicolon\n\tcontent = content.replace(/;\\s+/g, \";\");\n\n\t// Replace colon + space with just colon\n\tcontent = content.replace(/,\\s+/g, \",\");\n\n\t// Remove spaces around operators (we protected regex operators before)\n\tcontent = content.replace(/\\s+([+\\-*/%=&|<>!?:;,])\\s+/g, \"$1\");\n\n\t// Handle spaces around parentheses and brackets\n\tcontent = content.replace(/\\(\\s+/g, \"(\");\n\tcontent = content.replace(/\\s+\\)/g, \")\");\n\tcontent = content.replace(/\\[\\s+/g, \"[\");\n\tcontent = content.replace(/\\s+\\]/g, \"]\");\n\n\t// Handle spaces in all curly braces (for object literals, destructuring, etc.)\n\tcontent = content.replace(/\\{\\s+/g, \"{\");\n\tcontent = content.replace(/\\s+\\}/g, \"}\");\n\n\t// Restore protected segments\n\t// We need to handle nested tokens, so we'll iterate until all tokens are replaced\n\tlet previousContent = \"\";\n\twhile (previousContent !== content) {\n\t\tpreviousContent = content;\n\t\t// Sort indices in descending order to handle nested tokens correctly\n\t\tconst indices = Array.from(\n\t\t\t{ length: protectedSegments.length },\n\t\t\t(_, i) => i,\n\t\t).sort((a, b) => b - a);\n\t\tfor (const index of indices) {\n\t\t\tconst token = createToken(index);\n\t\t\tconst segment = protectedSegments[index];\n\t\t\t// Use global replacement to catch all instances\n\t\t\tconst tokenRegex = new RegExp(\n\t\t\t\ttoken.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\"),\n\t\t\t\t\"g\",\n\t\t\t);\n\t\t\tcontent = content.replace(tokenRegex, () => segment);\n\t\t}\n\t}\n\treturn content;\n}\n\nexport function minifyCss(content: string): string {\n\t// Remove CSS comments\n\tcontent = content.replace(/\\/\\*[\\s\\S]*?\\*\\//g, \"\");\n\n\t// Remove extra whitespace\n\tcontent = content.replace(/\\s+/g, \" \");\n\tcontent = content.replace(/\\s*{\\s*/g, \"{\");\n\tcontent = content.replace(/\\s*}\\s*/g, \"}\");\n\tcontent = content.replace(/\\s*:\\s*/g, \":\");\n\tcontent = content.replace(/\\s*;\\s*/g, \";\");\n\tcontent = content.replace(/\\s*,\\s*/g, \",\");\n\n\treturn content;\n}\n\nexport async function minifyFileContent(\n\tfilePath: string,\n\tcontent: string,\n): Promise<string> {\n\tif (!content || content.length < 100) {\n\t\treturn content;\n\t}\n\n\tconst fileExtension = getFileExtension(filePath);\n\n\tif (\n\t\tcontent &&\n\t\tcontent.length > 0 &&\n\t\t(fileExtension.endsWith(\"js\") ||\n\t\t\tfileExtension.endsWith(\"ts\") ||\n\t\t\t/* istanbul ignore next */\n\t\t\tfileExtension.endsWith(\"jsx\") ||\n\t\t\t/* istanbul ignore next */\n\t\t\tfileExtension.endsWith(\"tsx\"))\n\t) {\n\t\treturn minifyJs(content);\n\t}\n\n\t/* istanbul ignore next */\n\tif (content && content.length > 0 && fileExtension.endsWith(\"css\")) {\n\t\treturn minifyCss(content);\n\t}\n\n\treturn content;\n}\n"],"names":["v4","uuidv4","getFileExtension","minifyImports","content","replace","_match","_importStart","importItems","_importEnd","cleanedItems","split","map","item","trim","join","minifyJs","tokenPrefix","protectedSegments","createToken","index","protect","pattern","handler","match","length","push","includes","previousContent","indices","Array","from","_","i","sort","a","b","token","segment","tokenRegex","RegExp","minifyCss","minifyFileContent","filePath","fileExtension","endsWith"],"mappings":"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"}
@@ -1,6 +1,7 @@
1
1
  export declare const STR_TYPE_DIRECTORY = "d";
2
2
  export declare const STR_TYPE_FILE = "f";
3
3
  export declare const STR_TYPE_BOTH = "both";
4
+ export declare const getFileExtension: (filename: string) => string;
4
5
  export declare const extractMode: (mode: number) => string;
5
6
  export declare const convertSize: (bytes: number) => string;
6
7
  export declare const convertDate: (mtime: Date) => string;
@@ -34,3 +35,4 @@ export type RunGrepOnNode = {
34
35
  totalMatchingLines: number;
35
36
  };
36
37
  export declare const runGrepOnNode: (node?: string, rePattern?: RegExp) => Promise<RunGrepOnNode>;
38
+ export declare function isBinaryFileExtension(filePath: string): boolean;
package/dist/utilities.js CHANGED
@@ -1,6 +1,7 @@
1
- import { run } from "@node-cli/run";
2
1
  import fs from "node:fs";
2
+ import { extname } from "node:path";
3
3
  import { Logger } from "@node-cli/logger";
4
+ import { run } from "@node-cli/run";
4
5
  import kleur from "kleur";
5
6
  import prettyMilliseconds from "pretty-ms";
6
7
  const BYTE_CHUNKS = 1000;
@@ -17,6 +18,62 @@ const PERMISSIONS_PREFIX = {
17
18
  [STR_TYPE_DIRECTORY]: "d",
18
19
  [STR_TYPE_FILE]: "-"
19
20
  };
21
+ const BINARY_EXTENSIONS = [
22
+ // Executables and compiled code
23
+ "exe",
24
+ "dll",
25
+ "so",
26
+ "dylib",
27
+ "bin",
28
+ "obj",
29
+ "o",
30
+ // Compressed files
31
+ "zip",
32
+ "tar",
33
+ "gz",
34
+ "rar",
35
+ "7z",
36
+ "jar",
37
+ "war",
38
+ // Media files
39
+ "jpg",
40
+ "jpeg",
41
+ "png",
42
+ "gif",
43
+ "bmp",
44
+ "ico",
45
+ "tif",
46
+ "tiff",
47
+ "mp3",
48
+ "mp4",
49
+ "avi",
50
+ "mov",
51
+ "wmv",
52
+ "flv",
53
+ "wav",
54
+ "ogg",
55
+ // Document formats
56
+ "pdf",
57
+ "doc",
58
+ "docx",
59
+ "xls",
60
+ "xlsx",
61
+ "ppt",
62
+ "pptx",
63
+ // Database files
64
+ "db",
65
+ "sqlite",
66
+ "mdb",
67
+ // Other binary formats
68
+ "class",
69
+ "pyc",
70
+ "pyd",
71
+ "pyo",
72
+ "woff",
73
+ "woff2",
74
+ "ttf",
75
+ "otf"
76
+ ];
20
77
  const ownerNames = {
21
78
  0: "root"
22
79
  };
@@ -37,6 +94,9 @@ const MONTHS = {
37
94
  const logger = new Logger({
38
95
  boring: process.env.NODE_ENV === "test"
39
96
  });
97
+ export const getFileExtension = (filename)=>{
98
+ return extname(filename).toLowerCase().replace(/^\./, "");
99
+ };
40
100
  export const extractMode = (mode)=>{
41
101
  const modeDec = Number.parseInt(mode.toString(OCTAL), DECIMAL).toString().slice(LAST_THREE_ENTRIES);
42
102
  const modeOwner = modeDec.charAt(MODE_OWNER_POS);
@@ -172,5 +232,13 @@ export const runGrepOnNode = async (node, rePattern)=>{
172
232
  /* istanbul ignore next */ logger.error(error);
173
233
  }
174
234
  };
235
+ export function isBinaryFileExtension(filePath) {
236
+ const ext = getFileExtension(filePath);
237
+ // If there's no extension, assume it's binary
238
+ if (!ext) {
239
+ return true;
240
+ }
241
+ return BINARY_EXTENSIONS.includes(ext);
242
+ }
175
243
 
176
244
  //# sourceMappingURL=utilities.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/utilities.ts"],"sourcesContent":["import { RunResult, run } from \"@node-cli/run\";\n\nimport fs from \"node:fs\";\nimport { Logger } from \"@node-cli/logger\";\nimport kleur from \"kleur\";\nimport prettyMilliseconds from \"pretty-ms\";\n\nconst BYTE_CHUNKS = 1000;\nconst DECIMAL = 10;\nconst LAST_THREE_ENTRIES = -3;\nconst MODE_GROUP_POS = 1;\nconst MODE_OWNER_POS = 0;\nconst MODE_WORD_POS = 2;\nconst OCTAL = 8;\nexport const STR_TYPE_DIRECTORY = \"d\";\nexport const STR_TYPE_FILE = \"f\";\nexport const STR_TYPE_BOTH = \"both\";\nconst PERMISSIONS_PREFIX = {\n\t[STR_TYPE_DIRECTORY]: \"d\",\n\t[STR_TYPE_FILE]: \"-\",\n};\n\nconst ownerNames = {\n\t0: \"root\",\n};\n\nconst MONTHS = {\n\t0: \"Jan\",\n\t1: \"Feb\",\n\t2: \"Mar\",\n\t3: \"Apr\",\n\t4: \"May\",\n\t5: \"Jun\",\n\t6: \"Jul\",\n\t7: \"Aug\",\n\t8: \"Sep\",\n\t9: \"Oct\",\n\t10: \"Nov\",\n\t11: \"Dec\",\n};\n\nconst logger = new Logger({\n\tboring: process.env.NODE_ENV === \"test\",\n});\n\nexport const extractMode = (mode: number): string => {\n\tconst modeDec = Number.parseInt(mode.toString(OCTAL), DECIMAL)\n\t\t.toString()\n\t\t.slice(LAST_THREE_ENTRIES);\n\tconst modeOwner = modeDec.charAt(MODE_OWNER_POS);\n\tconst modeGroup = modeDec.charAt(MODE_GROUP_POS);\n\tconst modeWorld = modeDec.charAt(MODE_WORD_POS);\n\tconst modes = {\n\t\t0: \"---\",\n\t\t1: \"--x\",\n\t\t2: \"-w-\",\n\t\t3: \"-wx\",\n\t\t4: \"r--\",\n\t\t5: \"r-x\",\n\t\t6: \"rw-\",\n\t\t7: \"rwx\",\n\t};\n\treturn modes[modeOwner] + modes[modeGroup] + modes[modeWorld];\n};\n\nexport const convertSize = (bytes: number): string => {\n\tconst sizes = [\"B\", \"K\", \"M\", \"G\", \"T\"];\n\tconst length = 5;\n\tlet posttxt = 0;\n\n\twhile (bytes >= BYTE_CHUNKS) {\n\t\tposttxt = posttxt + 1;\n\t\tbytes = bytes / BYTE_CHUNKS;\n\t}\n\tconst string_ =\n\t\tNumber.parseInt(bytes.toString(), DECIMAL).toFixed(0) + sizes[posttxt];\n\treturn (\n\t\tArray.from({ length: length + 1 - string_.length }).join(\" \") + string_\n\t);\n};\n\nexport const convertDate = (mtime: Date): string => {\n\tconst month = MONTHS[mtime.getMonth()];\n\tconst date = `${mtime.getDate()}`.padStart(2, \"0\");\n\tconst hours = `${mtime.getHours()}`.padStart(2, \"0\");\n\tconst minutes = `${mtime.getMinutes()}`.padStart(2, \"0\");\n\treturn `${month} ${date} ${hours}:${minutes}`;\n};\n\nexport const getOwnerNameFromId = async (\n\tuid: string | number,\n): Promise<string | number> => {\n\tlet result: RunResult;\n\n\t/* istanbul ignore else */\n\tif (ownerNames[uid]) {\n\t\treturn ownerNames[uid];\n\t} else {\n\t\ttry {\n\t\t\tresult = await run(`id -nu ${uid}`);\n\t\t\townerNames[uid] = result.stdout;\n\t\t\treturn result.stdout;\n\t\t} catch {\n\t\t\t// nothing to declare officer\n\t\t\treturn `${uid}`;\n\t\t}\n\t}\n};\n\nexport const formatLongListings = async (\n\tstat: { mtime: Date; mode: number; uid: string | number; size: number },\n\ttype: string,\n): Promise<{\n\tmdate: string;\n\tmode: string;\n\towner: string;\n\tsize: string;\n}> => ({\n\tmdate: `${convertDate(stat.mtime)}`,\n\tmode: PERMISSIONS_PREFIX[type] + extractMode(stat.mode),\n\towner: `${await getOwnerNameFromId(stat.uid)}`,\n\tsize: `${convertSize(stat.size)}`,\n});\n\nexport type Statistics = {\n\tduration?: number;\n\ttotalDirScanned?: number;\n\ttotalDirsFound?: number;\n\ttotalFileScanned?: number;\n\ttotalFilesFound?: number;\n\ttype?: string;\n\tpattern?: boolean | RegExp;\n\tgrep?: boolean | RegExp | string;\n};\nexport const printStatistics = ({\n\tduration,\n\ttotalDirScanned,\n\ttotalDirsFound,\n\ttotalFileScanned,\n\ttotalFilesFound,\n\ttype,\n\tpattern,\n\tgrep,\n}: Statistics) => {\n\tlet message = `Total folders scanned: ${kleur.yellow(totalDirScanned)}\\n`;\n\tmessage += `Total files scanned: ${kleur.yellow(totalFileScanned)}\\n`;\n\tswitch (type) {\n\t\tcase STR_TYPE_DIRECTORY: {\n\t\t\tmessage += `Total folders matching: ${kleur.green(totalDirsFound)}\\n`;\n\t\t\tbreak;\n\t\t}\n\n\t\tcase STR_TYPE_FILE: {\n\t\t\tmessage += `Total files matching: ${kleur.green(totalFilesFound)}\\n`;\n\t\t\tbreak;\n\t\t}\n\n\t\tdefault: {\n\t\t\tif (pattern) {\n\t\t\t\tmessage += `Total folders matching: ${kleur.green(totalDirsFound)}\\n`;\n\t\t\t\tmessage += `Total files matching: ${kleur.green(totalFilesFound)}\\n`;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tmessage += `Duration: ${kleur.yellow(`${prettyMilliseconds(duration)}`)}`;\n\tif (!grep) {\n\t\tlogger.log();\n\t}\n\tlogger.printBox(message);\n};\n\nexport const checkPattern = (\n\trePattern: RegExp | undefined,\n\tstring_: string,\n): boolean | RegExpExecArray => {\n\tif (rePattern) {\n\t\trePattern.lastIndex = 0;\n\t\treturn rePattern.exec(string_);\n\t}\n\treturn true;\n};\n\nexport const runCommandOnNode = async (node: string, command: string) => {\n\ttry {\n\t\tconst { stdout } = await run(`${command} ${node}`);\n\t\tif (stdout) {\n\t\t\tlogger.log(stdout);\n\t\t}\n\t} catch {\n\t\t// nothing to declare officer\n\t}\n};\n\nexport type RunGrepOnNode = {\n\tresults: (string | number)[];\n\ttotalMatchingLines: number;\n};\nexport const runGrepOnNode = async (\n\tnode?: string,\n\trePattern?: RegExp,\n): Promise<RunGrepOnNode> => {\n\ttry {\n\t\tconst lines = [];\n\t\tlet totalMatchingLines = 0;\n\t\tconst buffer = fs.readFileSync(node, \"utf8\").split(\"\\n\");\n\n\t\tfor (const [lineNumber, line] of buffer.entries()) {\n\t\t\trePattern.lastIndex = 0;\n\t\t\tconst result: (string | number)[] = rePattern.exec(line);\n\t\t\tif (!result) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\ttotalMatchingLines++;\n\t\t\tif (lineNumber > 0) {\n\t\t\t\tlines.push(`${lineNumber}: ${kleur.grey(buffer[lineNumber - 1])}`);\n\t\t\t}\n\t\t\tlines.push(\n\t\t\t\t`${lineNumber + 1}: ${kleur.grey(\n\t\t\t\t\tline.replace(rePattern, kleur.black().bgYellow(result[0])),\n\t\t\t\t)}`,\n\t\t\t\t`${lineNumber + 2}: ${kleur.grey(buffer[lineNumber + 1])}`,\n\t\t\t\t\"\",\n\t\t\t);\n\t\t}\n\t\treturn {\n\t\t\tresults: lines.length > 0 ? lines : [],\n\t\t\ttotalMatchingLines,\n\t\t};\n\t} catch (error) {\n\t\t/* istanbul ignore next */\n\t\tlogger.error(error);\n\t}\n};\n"],"names":["run","fs","Logger","kleur","prettyMilliseconds","BYTE_CHUNKS","DECIMAL","LAST_THREE_ENTRIES","MODE_GROUP_POS","MODE_OWNER_POS","MODE_WORD_POS","OCTAL","STR_TYPE_DIRECTORY","STR_TYPE_FILE","STR_TYPE_BOTH","PERMISSIONS_PREFIX","ownerNames","MONTHS","logger","boring","process","env","NODE_ENV","extractMode","mode","modeDec","Number","parseInt","toString","slice","modeOwner","charAt","modeGroup","modeWorld","modes","convertSize","bytes","sizes","length","posttxt","string_","toFixed","Array","from","join","convertDate","mtime","month","getMonth","date","getDate","padStart","hours","getHours","minutes","getMinutes","getOwnerNameFromId","uid","result","stdout","formatLongListings","stat","type","mdate","owner","size","printStatistics","duration","totalDirScanned","totalDirsFound","totalFileScanned","totalFilesFound","pattern","grep","message","yellow","green","log","printBox","checkPattern","rePattern","lastIndex","exec","runCommandOnNode","node","command","runGrepOnNode","lines","totalMatchingLines","buffer","readFileSync","split","lineNumber","line","entries","push","grey","replace","black","bgYellow","results","error"],"mappings":"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"}
1
+ {"version":3,"sources":["../src/utilities.ts"],"sourcesContent":["import fs from \"node:fs\";\nimport { extname } from \"node:path\";\nimport { Logger } from \"@node-cli/logger\";\nimport { RunResult, run } from \"@node-cli/run\";\nimport kleur from \"kleur\";\nimport prettyMilliseconds from \"pretty-ms\";\n\nconst BYTE_CHUNKS = 1000;\nconst DECIMAL = 10;\nconst LAST_THREE_ENTRIES = -3;\nconst MODE_GROUP_POS = 1;\nconst MODE_OWNER_POS = 0;\nconst MODE_WORD_POS = 2;\nconst OCTAL = 8;\nexport const STR_TYPE_DIRECTORY = \"d\";\nexport const STR_TYPE_FILE = \"f\";\nexport const STR_TYPE_BOTH = \"both\";\nconst PERMISSIONS_PREFIX = {\n\t[STR_TYPE_DIRECTORY]: \"d\",\n\t[STR_TYPE_FILE]: \"-\",\n};\nconst BINARY_EXTENSIONS = [\n\t// Executables and compiled code\n\t\"exe\",\n\t\"dll\",\n\t\"so\",\n\t\"dylib\",\n\t\"bin\",\n\t\"obj\",\n\t\"o\",\n\t// Compressed files\n\t\"zip\",\n\t\"tar\",\n\t\"gz\",\n\t\"rar\",\n\t\"7z\",\n\t\"jar\",\n\t\"war\",\n\t// Media files\n\t\"jpg\",\n\t\"jpeg\",\n\t\"png\",\n\t\"gif\",\n\t\"bmp\",\n\t\"ico\",\n\t\"tif\",\n\t\"tiff\",\n\t\"mp3\",\n\t\"mp4\",\n\t\"avi\",\n\t\"mov\",\n\t\"wmv\",\n\t\"flv\",\n\t\"wav\",\n\t\"ogg\",\n\t// Document formats\n\t\"pdf\",\n\t\"doc\",\n\t\"docx\",\n\t\"xls\",\n\t\"xlsx\",\n\t\"ppt\",\n\t\"pptx\",\n\t// Database files\n\t\"db\",\n\t\"sqlite\",\n\t\"mdb\",\n\t// Other binary formats\n\t\"class\",\n\t\"pyc\",\n\t\"pyd\",\n\t\"pyo\",\n\t\"woff\",\n\t\"woff2\",\n\t\"ttf\",\n\t\"otf\",\n];\n\nconst ownerNames = {\n\t0: \"root\",\n};\n\nconst MONTHS = {\n\t0: \"Jan\",\n\t1: \"Feb\",\n\t2: \"Mar\",\n\t3: \"Apr\",\n\t4: \"May\",\n\t5: \"Jun\",\n\t6: \"Jul\",\n\t7: \"Aug\",\n\t8: \"Sep\",\n\t9: \"Oct\",\n\t10: \"Nov\",\n\t11: \"Dec\",\n};\n\nconst logger = new Logger({\n\tboring: process.env.NODE_ENV === \"test\",\n});\n\nexport const getFileExtension = (filename: string): string => {\n\treturn extname(filename).toLowerCase().replace(/^\\./, \"\");\n};\n\nexport const extractMode = (mode: number): string => {\n\tconst modeDec = Number.parseInt(mode.toString(OCTAL), DECIMAL)\n\t\t.toString()\n\t\t.slice(LAST_THREE_ENTRIES);\n\tconst modeOwner = modeDec.charAt(MODE_OWNER_POS);\n\tconst modeGroup = modeDec.charAt(MODE_GROUP_POS);\n\tconst modeWorld = modeDec.charAt(MODE_WORD_POS);\n\tconst modes = {\n\t\t0: \"---\",\n\t\t1: \"--x\",\n\t\t2: \"-w-\",\n\t\t3: \"-wx\",\n\t\t4: \"r--\",\n\t\t5: \"r-x\",\n\t\t6: \"rw-\",\n\t\t7: \"rwx\",\n\t};\n\treturn modes[modeOwner] + modes[modeGroup] + modes[modeWorld];\n};\n\nexport const convertSize = (bytes: number): string => {\n\tconst sizes = [\"B\", \"K\", \"M\", \"G\", \"T\"];\n\tconst length = 5;\n\tlet posttxt = 0;\n\n\twhile (bytes >= BYTE_CHUNKS) {\n\t\tposttxt = posttxt + 1;\n\t\tbytes = bytes / BYTE_CHUNKS;\n\t}\n\tconst string_ =\n\t\tNumber.parseInt(bytes.toString(), DECIMAL).toFixed(0) + sizes[posttxt];\n\treturn (\n\t\tArray.from({ length: length + 1 - string_.length }).join(\" \") + string_\n\t);\n};\n\nexport const convertDate = (mtime: Date): string => {\n\tconst month = MONTHS[mtime.getMonth()];\n\tconst date = `${mtime.getDate()}`.padStart(2, \"0\");\n\tconst hours = `${mtime.getHours()}`.padStart(2, \"0\");\n\tconst minutes = `${mtime.getMinutes()}`.padStart(2, \"0\");\n\treturn `${month} ${date} ${hours}:${minutes}`;\n};\n\nexport const getOwnerNameFromId = async (\n\tuid: string | number,\n): Promise<string | number> => {\n\tlet result: RunResult;\n\n\t/* istanbul ignore else */\n\tif (ownerNames[uid]) {\n\t\treturn ownerNames[uid];\n\t} else {\n\t\ttry {\n\t\t\tresult = await run(`id -nu ${uid}`);\n\t\t\townerNames[uid] = result.stdout;\n\t\t\treturn result.stdout;\n\t\t} catch {\n\t\t\t// nothing to declare officer\n\t\t\treturn `${uid}`;\n\t\t}\n\t}\n};\n\nexport const formatLongListings = async (\n\tstat: { mtime: Date; mode: number; uid: string | number; size: number },\n\ttype: string,\n): Promise<{\n\tmdate: string;\n\tmode: string;\n\towner: string;\n\tsize: string;\n}> => ({\n\tmdate: `${convertDate(stat.mtime)}`,\n\tmode: PERMISSIONS_PREFIX[type] + extractMode(stat.mode),\n\towner: `${await getOwnerNameFromId(stat.uid)}`,\n\tsize: `${convertSize(stat.size)}`,\n});\n\nexport type Statistics = {\n\tduration?: number;\n\ttotalDirScanned?: number;\n\ttotalDirsFound?: number;\n\ttotalFileScanned?: number;\n\ttotalFilesFound?: number;\n\ttype?: string;\n\tpattern?: boolean | RegExp;\n\tgrep?: boolean | RegExp | string;\n};\nexport const printStatistics = ({\n\tduration,\n\ttotalDirScanned,\n\ttotalDirsFound,\n\ttotalFileScanned,\n\ttotalFilesFound,\n\ttype,\n\tpattern,\n\tgrep,\n}: Statistics) => {\n\tlet message = `Total folders scanned: ${kleur.yellow(totalDirScanned)}\\n`;\n\tmessage += `Total files scanned: ${kleur.yellow(totalFileScanned)}\\n`;\n\tswitch (type) {\n\t\tcase STR_TYPE_DIRECTORY: {\n\t\t\tmessage += `Total folders matching: ${kleur.green(totalDirsFound)}\\n`;\n\t\t\tbreak;\n\t\t}\n\n\t\tcase STR_TYPE_FILE: {\n\t\t\tmessage += `Total files matching: ${kleur.green(totalFilesFound)}\\n`;\n\t\t\tbreak;\n\t\t}\n\n\t\tdefault: {\n\t\t\tif (pattern) {\n\t\t\t\tmessage += `Total folders matching: ${kleur.green(totalDirsFound)}\\n`;\n\t\t\t\tmessage += `Total files matching: ${kleur.green(totalFilesFound)}\\n`;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tmessage += `Duration: ${kleur.yellow(`${prettyMilliseconds(duration)}`)}`;\n\tif (!grep) {\n\t\tlogger.log();\n\t}\n\tlogger.printBox(message);\n};\n\nexport const checkPattern = (\n\trePattern: RegExp | undefined,\n\tstring_: string,\n): boolean | RegExpExecArray => {\n\tif (rePattern) {\n\t\trePattern.lastIndex = 0;\n\t\treturn rePattern.exec(string_);\n\t}\n\treturn true;\n};\n\nexport const runCommandOnNode = async (node: string, command: string) => {\n\ttry {\n\t\tconst { stdout } = await run(`${command} ${node}`);\n\t\tif (stdout) {\n\t\t\tlogger.log(stdout);\n\t\t}\n\t} catch {\n\t\t// nothing to declare officer\n\t}\n};\n\nexport type RunGrepOnNode = {\n\tresults: (string | number)[];\n\ttotalMatchingLines: number;\n};\nexport const runGrepOnNode = async (\n\tnode?: string,\n\trePattern?: RegExp,\n): Promise<RunGrepOnNode> => {\n\ttry {\n\t\tconst lines = [];\n\t\tlet totalMatchingLines = 0;\n\t\tconst buffer = fs.readFileSync(node, \"utf8\").split(\"\\n\");\n\n\t\tfor (const [lineNumber, line] of buffer.entries()) {\n\t\t\trePattern.lastIndex = 0;\n\t\t\tconst result: (string | number)[] = rePattern.exec(line);\n\t\t\tif (!result) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\ttotalMatchingLines++;\n\t\t\tif (lineNumber > 0) {\n\t\t\t\tlines.push(`${lineNumber}: ${kleur.grey(buffer[lineNumber - 1])}`);\n\t\t\t}\n\t\t\tlines.push(\n\t\t\t\t`${lineNumber + 1}: ${kleur.grey(\n\t\t\t\t\tline.replace(rePattern, kleur.black().bgYellow(result[0])),\n\t\t\t\t)}`,\n\t\t\t\t`${lineNumber + 2}: ${kleur.grey(buffer[lineNumber + 1])}`,\n\t\t\t\t\"\",\n\t\t\t);\n\t\t}\n\t\treturn {\n\t\t\tresults: lines.length > 0 ? lines : [],\n\t\t\ttotalMatchingLines,\n\t\t};\n\t} catch (error) {\n\t\t/* istanbul ignore next */\n\t\tlogger.error(error);\n\t}\n};\n\nexport function isBinaryFileExtension(filePath: string): boolean {\n\tconst ext = getFileExtension(filePath);\n\t// If there's no extension, assume it's binary\n\tif (!ext) {\n\t\treturn true;\n\t}\n\treturn BINARY_EXTENSIONS.includes(ext);\n}\n"],"names":["fs","extname","Logger","run","kleur","prettyMilliseconds","BYTE_CHUNKS","DECIMAL","LAST_THREE_ENTRIES","MODE_GROUP_POS","MODE_OWNER_POS","MODE_WORD_POS","OCTAL","STR_TYPE_DIRECTORY","STR_TYPE_FILE","STR_TYPE_BOTH","PERMISSIONS_PREFIX","BINARY_EXTENSIONS","ownerNames","MONTHS","logger","boring","process","env","NODE_ENV","getFileExtension","filename","toLowerCase","replace","extractMode","mode","modeDec","Number","parseInt","toString","slice","modeOwner","charAt","modeGroup","modeWorld","modes","convertSize","bytes","sizes","length","posttxt","string_","toFixed","Array","from","join","convertDate","mtime","month","getMonth","date","getDate","padStart","hours","getHours","minutes","getMinutes","getOwnerNameFromId","uid","result","stdout","formatLongListings","stat","type","mdate","owner","size","printStatistics","duration","totalDirScanned","totalDirsFound","totalFileScanned","totalFilesFound","pattern","grep","message","yellow","green","log","printBox","checkPattern","rePattern","lastIndex","exec","runCommandOnNode","node","command","runGrepOnNode","lines","totalMatchingLines","buffer","readFileSync","split","lineNumber","line","entries","push","grey","black","bgYellow","results","error","isBinaryFileExtension","filePath","ext","includes"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@node-cli/search",
3
- "version": "3.0.0",
3
+ "version": "3.1.0",
4
4
  "license": "MIT",
5
5
  "author": "Arno Versini",
6
6
  "description": "Search for files in a directory",
@@ -25,7 +25,7 @@
25
25
  "watch": "swc --strip-leading-paths --watch --out-dir dist src"
26
26
  },
27
27
  "dependencies": {
28
- "@node-cli/logger": "1.2.6",
28
+ "@node-cli/logger": "1.3.0",
29
29
  "@node-cli/parser": "2.4.0",
30
30
  "@node-cli/perf": "1.0.6",
31
31
  "@node-cli/run": "1.1.2",
@@ -33,10 +33,11 @@
33
33
  "kleur": "4.1.5",
34
34
  "micromatch": "4.0.8",
35
35
  "plur": "5.1.0",
36
- "pretty-ms": "9.2.0"
36
+ "pretty-ms": "9.2.0",
37
+ "uuid": "11.1.0"
37
38
  },
38
39
  "publishConfig": {
39
40
  "access": "public"
40
41
  },
41
- "gitHead": "0ca585eac6d0052eb2a2b41f6910572cc68c233f"
42
+ "gitHead": "decdedb3863d685996d0abd91f4c23746e9e3172"
42
43
  }