UNPKG

crapifyme

Version:

Ultra-fast developer productivity CLI tools - remove comments, logs, and more

205 lines 9.88 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.charsCommand = void 0; const commander_1 = require("commander"); const shared_1 = require("../../shared"); const logic_1 = require("./logic"); const types_1 = require("./types"); exports.charsCommand = new commander_1.Command('chars') .description('Detect and fix non-Latin characters that may cause encoding issues') .argument('[paths...]', 'Files or directories to process', ['.']) .option('-e, --extensions <ext>', 'File extensions to process', 'js,ts,jsx,tsx,vue,svelte,astro,html,css,scss,less,sass,py,java,c,cpp,cs,php,rb,go,rs') .option('-x, --exclude <patterns>', 'Glob patterns to exclude') .option('--fix', 'Automatically fix detected issues with ASCII replacements') .option('--strict', 'Enable strict mode (flag all non-ASCII characters)') .option('--interactive', 'Prompt for each replacement (requires --fix)') .option('--show-context <number>', 'Number of characters to show around each issue', '40') .option('--ignore-strings', 'Ignore characters inside string literals') .option('--ignore-comments', 'Ignore characters inside comments') .option('--severity <level>', 'Minimum severity level to report (low,medium,high,critical)', 'low') .action(async (paths, options, command) => { const globalOptions = command.parent?.opts() || {}; const logger = new shared_1.Logger(globalOptions.verbose, globalOptions.quiet, globalOptions.json); if (!globalOptions.force) { const vcsResult = (0, shared_1.detectVersionControl)(); if (!vcsResult.detected && options.fix) { logger.error('No version control system detected in this project or its parent directories.'); logger.error('This tool can modify your code files, which is a potentially destructive operation.'); logger.error('Use --force to proceed without version control.'); process.exit(shared_1.ExitCode.Error); } if (globalOptions.verbose && vcsResult.detected) { logger.info(`Version control detected: ${vcsResult.type} at ${vcsResult.path}`); } } try { const extensions = options.extensions.split(',').map((e) => e.trim()); const patterns = (0, shared_1.createFilePatterns)(paths, extensions); const excludePatterns = options.exclude ?.split(',') .map((p) => p.trim()) .filter(Boolean) || []; logger.info(`Search patterns: ${patterns.join(', ')}`); if (excludePatterns.length > 0) { logger.info(`Exclude patterns: ${excludePatterns.join(', ')}`); } const files = await (0, shared_1.findFiles)(patterns, excludePatterns); if (files.length === 0) { logger.warn('No files found to process'); logger.info(`Searched in: ${paths.join(', ')}`); logger.info(`Extensions: ${extensions.join(', ')}`); process.exit(shared_1.ExitCode.Success); } logger.info(`Found ${files.length} file${files.length === 1 ? '' : 's'} to process`); if (globalOptions.dryRun || !options.fix) { logger.info(options.fix ? 'DRY RUN - No files will be modified' : 'DETECTION MODE - No files will be modified'); } const detectorOptions = { strict: options.strict, interactive: options.interactive, showContext: parseInt(options.showContext) || 40, ignoreStrings: options.ignoreStrings, ignoreComments: options.ignoreComments }; const detector = new logic_1.CharacterDetector(logger, detectorOptions); const minSeverity = parseSeverity(options.severity); const stats = { filesProcessed: 0, itemsRemoved: 0, itemsPreserved: 0, charactersFound: 0, charactersFixed: 0, scriptTypes: {}, errors: [] }; for (const scriptType of Object.values(types_1.ScriptType)) { stats.scriptTypes[scriptType] = 0; } for (const file of files) { try { const content = await (0, shared_1.readFile)(file); const result = options.fix && !globalOptions.dryRun ? detector.fixCharacters(content, file) : detector.detectCharacters(content, file); const filteredIssues = result.issues.filter(issue => getSeverityLevel(issue.severity) >= getSeverityLevel(minSeverity)); if (result.modified && !globalOptions.dryRun) { await (0, shared_1.writeFile)(file, result.content); } stats.filesProcessed++; stats.charactersFound += filteredIssues.length; stats.charactersFixed += result.fixed; const scriptStats = detector.getScriptTypeStats(filteredIssues); for (const [scriptType, count] of Object.entries(scriptStats)) { stats.scriptTypes[scriptType] += count; } if (filteredIssues.length > 0) { logger.success(`${file}`); if (globalOptions.verbose || !globalOptions.json) { for (const issue of filteredIssues.slice(0, 10)) { const prefix = issue.severity === types_1.IssueSeverity.CRITICAL ? '⚠️ ' : issue.severity === types_1.IssueSeverity.HIGH ? '🔴 ' : issue.severity === types_1.IssueSeverity.MEDIUM ? '🟡 ' : '🔵 '; console.log(` ${prefix}Line ${issue.line}:${issue.column} - ${issue.character} (U+${issue.codePoint.toString(16).toUpperCase().padStart(4, '0')}) [${issue.script}]`); if (issue.replacement) { console.log(` ↳ Suggests: "${issue.replacement}"`); } console.log(` Context: ${issue.context}`); } if (filteredIssues.length > 10) { console.log(` ... and ${filteredIssues.length - 10} more issues`); } } console.log(` ┣ Characters found: ${filteredIssues.length}`); if (options.fix) { console.log(` ┣ Characters fixed: ${result.fixed}`); } console.log(` ┗ Status: ${globalOptions.dryRun ? 'DRY RUN - would be modified' : result.modified ? 'Modified' : 'Detected only'}`); } else if (globalOptions.verbose) { logger.info(`${file} - No issues found`); } } catch (error) { stats.errors.push({ file, error: error.message }); logger.error(`Failed to process ${file}`, error); } } if (globalOptions.json) { logger.json(stats); } else { if (stats.errors.length > 0) { logger.error(`Processing completed with ${stats.errors.length} error${stats.errors.length === 1 ? '' : 's'}`); } else { logger.success('Processing completed successfully'); } logger.info(`Files processed: ${stats.filesProcessed}`); logger.info(`Characters found: ${stats.charactersFound}`); if (options.fix) { logger.info(`Characters fixed: ${stats.charactersFixed}`); } if (stats.charactersFound > 0) { console.log('\nScript distribution:'); for (const [scriptType, count] of Object.entries(stats.scriptTypes)) { if (count > 0) { console.log(` ${scriptType}: ${count}`); } } } (0, shared_1.showComplete)(); if (globalOptions.dryRun && options.fix && stats.charactersFound > 0) { logger.warn('DRY RUN MODE - No files were actually modified'); logger.info('Remove --dry-run to apply changes'); } else if (!options.fix && stats.charactersFound > 0) { logger.info('Add --fix flag to automatically replace characters'); } } const exitCode = stats.errors.length > 0 ? shared_1.ExitCode.Error : stats.charactersFound > 0 ? shared_1.ExitCode.IssuesFound : shared_1.ExitCode.Success; process.exit(exitCode); } catch (error) { logger.error('Fatal error', error); process.exit(shared_1.ExitCode.Error); } }); function parseSeverity(severity) { switch (severity.toLowerCase()) { case 'low': return types_1.IssueSeverity.LOW; case 'medium': return types_1.IssueSeverity.MEDIUM; case 'high': return types_1.IssueSeverity.HIGH; case 'critical': return types_1.IssueSeverity.CRITICAL; default: return types_1.IssueSeverity.LOW; } } function getSeverityLevel(severity) { switch (severity) { case types_1.IssueSeverity.LOW: return 1; case types_1.IssueSeverity.MEDIUM: return 2; case types_1.IssueSeverity.HIGH: return 3; case types_1.IssueSeverity.CRITICAL: return 4; default: return 1; } } //# sourceMappingURL=index.js.map