tz-clean 2.2.0 → 2.3.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/eslint.config.mjs CHANGED
@@ -26,6 +26,9 @@ export default [
26
26
  jsdoc.configs['flat/recommended'],
27
27
  perfectionist.configs['recommended-natural'],
28
28
  {
29
+ linterOptions: {
30
+ reportUnusedDisableDirectives: 'error',
31
+ },
29
32
  languageOptions: {
30
33
  ecmaVersion: 2022,
31
34
  globals: {
@@ -57,6 +60,7 @@ export default [
57
60
  'jsdoc/require-param': 'warn',
58
61
  'jsdoc/require-returns': 'warn',
59
62
  'no-comments/disallowComments': 'warn',
63
+ 'no-multiple-empty-lines': ['error', { max: 1, maxBOF: 0, maxEOF: 0 }],
60
64
  'no-redeclare': 'off',
61
65
  'no-undef': 'off',
62
66
  'no-unused-vars': ['error', { args: 'none', vars: 'local' }],
package/index.js CHANGED
@@ -140,6 +140,8 @@ async function run() {
140
140
 
141
141
  try {
142
142
  const fixedFiles = runPrettier ? runPrettierTools(includePaths, excludePaths) : [];
143
+ const strippedFiles = stripCommentsAndEmptyLines(includePaths, excludePaths);
144
+ const allFixedFiles = [...new Set([...fixedFiles, ...strippedFiles])];
143
145
  const typecheckResult = runTypecheck ? runTypecheckTools() : { error: null, ran: false };
144
146
  const reportData = runEslint ? runEslintTools(includePaths, excludePaths) : [];
145
147
  const { totalErrors, totalWarnings } = calculateTotals(reportData);
@@ -163,10 +165,10 @@ async function run() {
163
165
  }
164
166
 
165
167
  if (response.reportType === 'terminal') {
166
- printTerminalSummary(reportData, fixedFiles, totalErrors, totalWarnings, typecheckResult);
168
+ printTerminalSummary(reportData, allFixedFiles, totalErrors, totalWarnings, typecheckResult);
167
169
  } else if (response.reportType === 'ui') {
168
170
  console.log('⏳ Generating UI Dashboard...');
169
- const outputPath = generateHtmlReport(reportData, fixedFiles);
171
+ const outputPath = generateHtmlReport(reportData, allFixedFiles);
170
172
  console.log(`🚀 Opening report in browser: ${outputPath}`);
171
173
  await open(outputPath);
172
174
  } else if (response.reportType === 'hosted') {
@@ -174,7 +176,7 @@ async function run() {
174
176
  const templatePath = path.join(configDir, 'report-template.html');
175
177
  let html = fs.readFileSync(templatePath, 'utf-8');
176
178
  html = html.replace('/* REPORT_DATA_PLACEHOLDER */ null', JSON.stringify(reportData));
177
- html = html.replace('/* FIXED_FILES_PLACEHOLDER */ []', JSON.stringify(fixedFiles));
179
+ html = html.replace('/* FIXED_FILES_PLACEHOLDER */ []', JSON.stringify(allFixedFiles));
178
180
  serveHostedReport(html);
179
181
  }
180
182
  } catch (globalError) {
@@ -183,6 +185,73 @@ async function run() {
183
185
  }
184
186
  }
185
187
 
188
+ /**
189
+ * Strips all comments and excess blank lines from JS/TS files in the target paths.
190
+ * Removes single-line comments (//), block comments (/* *\/), eslint-disable directives,
191
+ * and collapses multiple consecutive blank lines into one.
192
+ * @param {string[]} includePaths - Paths to process (defaults to targetDir).
193
+ * @param {string[]} excludePaths - Paths to skip.
194
+ * @returns {string[]} List of files that were modified.
195
+ */
196
+ function stripCommentsAndEmptyLines(includePaths = [], excludePaths = []) {
197
+ const extensions = ['.js', '.ts', '.jsx', '.tsx', '.mjs', '.cjs'];
198
+ const modifiedFiles = [];
199
+
200
+ const defaultIgnorePatterns = [
201
+ /node_modules/,
202
+ /\.min\.(js|cjs|mjs)$/,
203
+ /\.bundle\.js$/,
204
+ /[/\\](dist|build|vendor|libs)[/\\]/,
205
+ ];
206
+
207
+ const userIgnorePatterns = excludePaths.map((p) => new RegExp(p.replace(/\//g, '[/\\\\]')));
208
+ const allIgnorePatterns = [...defaultIgnorePatterns, ...userIgnorePatterns];
209
+
210
+ const scanDir = (dir) => {
211
+ let entries;
212
+ try {
213
+ entries = fs.readdirSync(dir, { withFileTypes: true });
214
+ } catch {
215
+ return;
216
+ }
217
+ for (const entry of entries) {
218
+ const fullPath = path.join(dir, entry.name);
219
+ if (allIgnorePatterns.some((re) => re.test(fullPath))) continue;
220
+ if (entry.isDirectory()) {
221
+ scanDir(fullPath);
222
+ } else if (entry.isFile() && extensions.includes(path.extname(entry.name))) {
223
+ const original = fs.readFileSync(fullPath, 'utf-8');
224
+ let cleaned = original;
225
+
226
+ // Remove block comments /** */ and /* */ (but not shebang)
227
+ cleaned = cleaned.replace(/\/\*[\s\S]*?\*\//g, '');
228
+
229
+ // Remove single-line comments // (including eslint-disable)
230
+ cleaned = cleaned.replace(/[ \t]*\/\/.*$/gm, '');
231
+
232
+ // Collapse multiple blank lines into one
233
+ cleaned = cleaned.replace(/\n{3,}/g, '\n\n');
234
+
235
+ // Remove blank lines at start of file
236
+ cleaned = cleaned.replace(/^\n+/, '');
237
+
238
+ // Ensure single newline at end of file
239
+ cleaned = cleaned.trimEnd() + '\n';
240
+
241
+ if (cleaned !== original) {
242
+ fs.writeFileSync(fullPath, cleaned, 'utf-8');
243
+ modifiedFiles.push(path.relative(targetDir, fullPath));
244
+ }
245
+ }
246
+ }
247
+ };
248
+
249
+ const targets = includePaths.length > 0 ? includePaths.map((p) => path.resolve(targetDir, p)) : [targetDir];
250
+ targets.forEach((t) => scanDir(t));
251
+
252
+ return modifiedFiles;
253
+ }
254
+
186
255
  /**
187
256
  * Executes ESLint to analyze code.
188
257
  * @param {string[]} includePaths - Paths to include in analysis.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tz-clean",
3
- "version": "2.2.0",
3
+ "version": "2.3.0",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "bin": {