@regele/devtools
Version:
A collection of developer utilities for code processing and text analysis
150 lines (125 loc) • 5.56 kB
JavaScript
try {
// Direct implementation of comment removal
const fs = require('fs');
const path = require('path');
const { Command } = require('commander');
const chalk = require('chalk');
const ora = require('ora');
const fg = require('fast-glob');
// Ensure ora is properly imported
const createSpinner = ora.default || ora;
// Function to remove comments from JavaScript code
function removeJavaScriptComments(code) {
let result = code;
try {
// First, preserve strings and regexes to avoid modifying comments inside them
const preservedItems = [];
let preservedCount = 0;
// Temporarily replace strings and regexes with placeholders
result = result.replace(
/(["'`])(?:\\[\s\S]|(?!\1)[^\\])*\1|\/(?![*+?])(?:[^\r\n\[/\\]|\\.|\[(?:[^\r\n\]\\]|\\.)*\])+\/(?:[gimuy]+\b)?/g,
(match) => {
const placeholder = `__PRESERVED_ITEM_${preservedCount}__`;
preservedItems[preservedCount] = match;
preservedCount++;
return placeholder;
}
);
// Remove JSX comments
result = result.replace(/\{\/\*[\s\S]*?\*\/\}/g, '');
// Remove multi-line comments
result = result.replace(/\/\*[\s\S]*?\*\//g, '');
// Remove single-line comments
// Handle comments at start of line
result = result.replace(/^[ \t]*\/\/.*$/gm, '');
// Handle comments after code (but not in URLs)
result = result.replace(/([^:/])\/\/.*$/gm, '$1');
// Restore preserved strings and regexes
for (let i = 0; i < preservedCount; i++) {
const placeholder = `__PRESERVED_ITEM_${i}__`;
const regex = new RegExp(placeholder, 'g');
result = result.replace(regex, () => preservedItems[i]);
}
// Remove empty lines
// Remove lines that contain only whitespace
result = result.replace(/^\s*[\r\n]/gm, '');
// Remove consecutive empty lines (preserving indentation)
result = result.replace(/\n(\s*)\n(\s*)\n/g, '\n$2\n');
// Remove empty lines at the beginning and end of the file
result = result.replace(/^(\s*\n)+/, '');
result = result.replace(/(\n\s*)+$/, '');
return result.trim();
} catch (error) {
console.error(`JavaScript comment removal failed: ${error.message}`);
return code;
}
}
// Test function
async function testGlob(pattern) {
try {
console.log(`Testing pattern: ${pattern}`);
// Normalize pattern for Windows paths
const normalizedPattern = pattern.replace(/\\/g, '/');
// Find files
const files = await fg(normalizedPattern, {
onlyFiles: true,
absolute: true
});
console.log(`Found ${files.length} files`);
// Print first 10 files
if (files.length > 0) {
console.log('First 10 files:');
files.slice(0, 10).forEach(file => {
console.log(`- ${file}`);
});
// Process the first file as a test
if (files.length > 0) {
const testFile = files[0];
console.log(`\nProcessing test file: ${testFile}`);
// Read the file
const content = fs.readFileSync(testFile, 'utf8');
console.log(`Original size: ${content.length} bytes`);
// Process based on extension
const ext = path.extname(testFile).toLowerCase();
let newContent;
if (['.js', '.jsx', '.ts', '.tsx', '.json'].includes(ext)) {
newContent = removeJavaScriptComments(content);
} else if (['.html', '.htm', '.xml'].includes(ext)) {
// For HTML files, remove HTML comments
newContent = content.replace(/<!--[\s\S]*?-->/g, '');
// Also process script and style tags for JS and CSS comments
newContent = newContent.replace(/(<script\b[^>]*>)([\s\S]*?)(<\/script>)/gi, (match, openTag, content, closeTag) => {
return openTag + removeJavaScriptComments(content) + closeTag;
});
newContent = newContent.replace(/(<style\b[^>]*>)([\s\S]*?)(<\/style>)/gi, (match, openTag, content, closeTag) => {
return openTag + removeJavaScriptComments(content) + closeTag;
});
} else if (['.css', '.scss', '.less'].includes(ext)) {
// For CSS files, remove CSS comments
newContent = content.replace(/\/\*[\s\S]*?\*\//g, '');
// Remove empty lines
newContent = newContent.replace(/^\s*[\r\n]/gm, '');
newContent = newContent.replace(/\n\s*\n/g, '\n');
} else {
newContent = removeJavaScriptComments(content);
}
console.log(`New size: ${newContent.length} bytes`);
console.log(`Removed: ${content.length - newContent.length} bytes (${((content.length - newContent.length) / content.length * 100).toFixed(2)}%)`);
// Write to a test file
const testOutputFile = testFile + '.cleaned';
fs.writeFileSync(testOutputFile, newContent, 'utf8');
console.log(`Cleaned file written to: ${testOutputFile}`);
}
}
} catch (error) {
console.error('Error:', error.message);
}
}
// Get pattern from command line
const pattern = process.argv[2] || 'C:/Users/darw1/Downloads/testing/**/*.{js,ts,jsx,tsx,css,html,json}';
testGlob(pattern);
} catch (error) {
console.error('Error:', error.message);
process.exit(1);
}