/** * Read Compressor - Compress file content while preserving essential information * * Strategies: * - Remove blank lines (configurable) * - Remove comment-only lines (language-aware) * - Collapse import blocks * - Preserve line numbers for reference */ // Language-specific comment patterns const COMMENT_PATTERNS = { // Single-line comments javascript: [/^\s*\/\/.*$/, /^\s*\/\*.*\*\/\s*$/], typescript: [/^\s*\/\/.*$/, /^\s*\/\*.*\*\/\s*$/], python: [/^\s*#.*$/], ruby: [/^\s*#.*$/], bash: [/^\s*#.*$/], swift: [/^\s*\/\/.*$/], go: [/^\s*\/\/.*$/], rust: [/^\s*\/\/.*$/], php: [/^\s*\/\/.*$/, /^\s*#.*$/, /^\s*\/\*.*\*\/\s*$/], }; // Import patterns by language const IMPORT_PATTERNS = { javascript: /^(import|export)\s+/, typescript: /^(import|export)\s+/, python: /^(import|from)\s+/, swift: /^import\s+/, go: /^import\s+/, rust: /^use\s+/, php: /^(use|require|include)/, }; function detectLanguage(filename) { const ext = filename.split('.').pop()?.toLowerCase() || ''; const langMap = { js: 'javascript', jsx: 'javascript', ts: 'typescript', tsx: 'typescript', py: 'python', rb: 'ruby', sh: 'bash', bash: 'bash', swift: 'swift', go: 'go', rs: 'rust', php: 'php', }; return langMap[ext] || 'unknown'; } function isCommentLine(line, language) { const patterns = COMMENT_PATTERNS[language]; if (!patterns) return false; return patterns.some(pattern => pattern.test(line)); } function isImportLine(line, language) { const pattern = IMPORT_PATTERNS[language]; if (!pattern) return false; return pattern.test(line.trim()); } export function compressRead(content, filename, options = {}) { const { removeBlankLines = true, removeComments = true, collapseImports = true, maxLines = 500, } = options; const language = detectLanguage(filename); const lines = content.split('\n'); const originalLines = lines.length; const result = []; let importBlock = []; let inImportBlock = false; let lineNumber = 0; for (const line of lines) { lineNumber++; // Skip blank lines if configured if (removeBlankLines && line.trim() === '') { continue; } // Skip comment lines if configured if (removeComments && isCommentLine(line, language)) { continue; } // Handle import collapsing if (collapseImports && isImportLine(line, language)) { if (!inImportBlock) { inImportBlock = true; importBlock = []; } importBlock.push(line.trim()); continue; } else if (inImportBlock) { // End of import block - collapse it if (importBlock.length > 3) { result.push(`// [${importBlock.length} imports collapsed]`); } else { result.push(...importBlock); } importBlock = []; inImportBlock = false; } // Add line with number prefix for reference result.push(`${lineNumber}: ${line}`); } // Handle remaining imports at end of file if (importBlock.length > 0) { if (importBlock.length > 3) { result.push(`// [${importBlock.length} imports collapsed]`); } else { result.push(...importBlock); } } // Truncate if too long let compressed = result; let truncated = false; if (compressed.length > maxLines) { compressed = compressed.slice(0, maxLines); compressed.push(`\n... [${result.length - maxLines} more lines truncated]`); truncated = true; } const compressedLines = compressed.length; const savings = ((1 - compressedLines / originalLines) * 100).toFixed(1); return { content: compressed.join('\n'), originalLines, compressedLines, savings: `${savings}%`, }; }