tz-clean 2.3.3 → 2.5.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/.husky/pre-commit CHANGED
@@ -1 +1,12 @@
1
1
  npx lint-staged
2
+
3
+ node -e "
4
+ const fs = require('fs');
5
+ const file = 'index.js';
6
+ const content = fs.readFileSync(file, 'utf-8');
7
+ if (!content.startsWith('#!/usr/bin/env node')) {
8
+ fs.writeFileSync(file, '#!/usr/bin/env node\n' + content);
9
+ require('child_process').execSync('git add ' + file);
10
+ console.log('Restored shebang in index.js');
11
+ }
12
+ "
package/index.js CHANGED
@@ -70,6 +70,13 @@ function parseArgs() {
70
70
  return { excludePaths, includePaths, runEslint, runPrettier, runTypecheck, tools };
71
71
  }
72
72
 
73
+ function printFileProgress(label, filePath) {
74
+ const maxLen = 60;
75
+ const relative = path.relative(targetDir, filePath) || filePath;
76
+ const display = relative.length > maxLen ? '...' + relative.slice(-(maxLen - 3)) : relative;
77
+ process.stdout.write(`\r ${label} ${display.padEnd(maxLen + 5)}`);
78
+ }
79
+
73
80
  function printTerminalSummary(reportData, fixedFiles, totalErrors, totalWarnings, typecheckResult) {
74
81
  console.log('\n--- 📊 tz-clean Summary ---');
75
82
  console.log(`Files Analyzed: ${reportData.length}`);
@@ -120,12 +127,28 @@ async function run() {
120
127
  if (excludePaths.length > 0) console.log(`🚫 Exclude: ${excludePaths.join(', ')}`);
121
128
 
122
129
  try {
130
+ process.stdout.write('⏳ [1/4] Running Prettier...\n');
123
131
  const fixedFiles = runPrettier ? runPrettierTools(includePaths, excludePaths) : [];
132
+ process.stdout.write(`✅ [1/4] Prettier done (${fixedFiles.length} file(s) formatted) \n`);
133
+
134
+ process.stdout.write('⏳ [2/4] Stripping comments...\n');
124
135
  const strippedFiles = stripCommentsAndEmptyLines(includePaths, excludePaths);
136
+ process.stdout.write(`\r✅ [2/4] Comments stripped (${strippedFiles.length} file(s) modified)${' '.repeat(30)}\n`);
137
+
125
138
  const allFixedFiles = [...new Set([...fixedFiles, ...strippedFiles])];
139
+
140
+ process.stdout.write('⏳ [3/4] Running Typecheck...');
126
141
  const typecheckResult = runTypecheck ? runTypecheckTools() : { error: null, ran: false };
142
+ let typecheckStatus = 'skipped';
143
+ if (typecheckResult.ran) {
144
+ typecheckStatus = typecheckResult.error ? 'failed' : 'passed';
145
+ }
146
+ process.stdout.write(`\r✅ [3/4] Typecheck ${typecheckStatus} \n`);
147
+
148
+ process.stdout.write('⏳ [4/4] Running ESLint...');
127
149
  const reportData = runEslint ? runEslintTools(includePaths, excludePaths) : [];
128
150
  const { totalErrors, totalWarnings } = calculateTotals(reportData);
151
+ process.stdout.write(`\r✅ [4/4] ESLint done (${totalErrors} error(s), ${totalWarnings} warning(s)) \n`);
129
152
 
130
153
  console.log('\n✅ Analysis complete!');
131
154
  const response = await prompts({
@@ -216,13 +239,21 @@ function runPrettierTools(includePaths = [], excludePaths = []) {
216
239
  fixedFiles = prettierOutput
217
240
  .split('\n')
218
241
  .filter((line) => line.trim() && !line.includes('(unchanged)'))
219
- .map((line) => line.split(' ')[0]);
242
+ .map((line) => {
243
+ const filePath = line.split(' ')[0];
244
+ printFileProgress('✏️ ', path.resolve(targetDir, filePath));
245
+ return filePath;
246
+ });
220
247
  } catch (err) {
221
248
  if (err.stdout) {
222
249
  fixedFiles = err.stdout
223
250
  .split('\n')
224
251
  .filter((line) => line.trim() && !line.includes('(unchanged)'))
225
- .map((line) => line.split(' ')[0]);
252
+ .map((line) => {
253
+ const filePath = line.split(' ')[0];
254
+ printFileProgress('✏️ ', path.resolve(targetDir, filePath));
255
+ return filePath;
256
+ });
226
257
  }
227
258
  } finally {
228
259
  if (fs.existsSync(tempIgnorePath)) fs.unlinkSync(tempIgnorePath);
@@ -259,6 +290,13 @@ function serveHostedReport(html) {
259
290
  });
260
291
  }
261
292
 
293
+ function skipLineComment(source, startIndex) {
294
+ let i = startIndex + 2;
295
+ const len = source.length;
296
+ while (i < len && source[i] !== '\n') i++;
297
+ return i;
298
+ }
299
+
262
300
  function skipStringLiteral(source, startIndex) {
263
301
  const quote = source[startIndex];
264
302
  let i = startIndex + 1;
@@ -303,6 +341,7 @@ function stripCommentsAndEmptyLines(includePaths = [], excludePaths = []) {
303
341
  if (entry.isDirectory()) {
304
342
  scanDir(fullPath);
305
343
  } else if (entry.isFile() && extensions.includes(path.extname(entry.name))) {
344
+ printFileProgress('✂️ ', fullPath);
306
345
  const original = fs.readFileSync(fullPath, 'utf-8');
307
346
  let cleaned = stripCommentsFromSource(original);
308
347
  cleaned = cleaned.replace(new RegExp('\\n{3,}', 'g'), '\n\n');
@@ -326,6 +365,13 @@ function stripCommentsFromSource(source) {
326
365
  let i = 0;
327
366
  const len = source.length;
328
367
 
368
+ if (source.startsWith('#!')) {
369
+ const end = source.indexOf('\n');
370
+ const shebangEnd = end === -1 ? len : end + 1;
371
+ result += source.slice(0, shebangEnd);
372
+ i = shebangEnd;
373
+ }
374
+
329
375
  while (i < len) {
330
376
  const ch = source[i];
331
377
 
@@ -342,8 +388,7 @@ function stripCommentsFromSource(source) {
342
388
  }
343
389
 
344
390
  if (ch === '/' && source[i + 1] === '/') {
345
- i += 2;
346
- while (i < len && source[i] !== '\n') i++;
391
+ i = skipLineComment(source, i);
347
392
  continue;
348
393
  }
349
394
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tz-clean",
3
- "version": "2.3.3",
3
+ "version": "2.5.0",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "bin": {