UNPKG

crapifyme

Version:

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

276 lines 11.4 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ImportsProcessor = void 0; const ast_analyzer_1 = require("./ast-analyzer"); const framework_detector_1 = require("./framework-detector"); const import_transformer_1 = require("./import-transformer"); const path_resolver_1 = require("./path-resolver"); class ImportsProcessor { constructor(options = {}) { this.options = { style: options.style || 'mixed', sort: options.sort !== false, group: options.group !== false, removeUnused: options.removeUnused !== false, mergeDuplicates: options.mergeDuplicates !== false, multilineThreshold: options.multilineThreshold || 3, aliases: options.aliases || [], preserveComments: options.preserveComments !== false, framework: options.framework || '', extensions: options.extensions || ['js', 'jsx', 'ts', 'tsx', 'vue', 'svelte'], verbose: options.verbose || false }; this.astAnalyzer = new ast_analyzer_1.ASTAnalyzer(); this.pathResolver = new path_resolver_1.PathResolver(); this.frameworkDetector = new framework_detector_1.FrameworkDetector(); this.initializeFramework(); this.initializeAliases(); this.transformer = new import_transformer_1.ImportTransformer(this.getTransformOptions()); } processFile(content, filePath) { try { const originalImportCount = this.countImports(content); if (originalImportCount === 0) { return { content, modified: false, optimized: 0, unusedRemoved: 0, duplicatesMerged: 0, pathsConverted: 0 }; } const analysisResult = this.astAnalyzer.analyzeFile(content, filePath); let processedImports = [...analysisResult.imports]; let unusedRemoved = 0; let duplicatesMerged = 0; let pathsConverted = 0; if (this.options.removeUnused) { const beforeCount = processedImports.length; processedImports = this.removeUnusedImports(processedImports, analysisResult.usedIdentifiers); unusedRemoved = beforeCount - processedImports.length; } if (this.options.mergeDuplicates) { const beforeCount = processedImports.length; processedImports = this.mergeDuplicateImports(processedImports); duplicatesMerged = beforeCount - processedImports.length; } if (this.options.style !== 'mixed') { pathsConverted = this.convertImportPaths(processedImports, filePath); } const hasContentChanges = unusedRemoved > 0 || duplicatesMerged > 0 || pathsConverted > 0; const hasStructureChanges = this.options.sort || this.options.group; if (!hasContentChanges && !hasStructureChanges) { return { content, modified: false, optimized: 0, unusedRemoved: 0, duplicatesMerged: 0, pathsConverted: 0 }; } let newContent = content; if (hasContentChanges) { const transformedImports = this.transformer.transformImports(processedImports, filePath, content); newContent = this.replaceImportsInContent(content, transformedImports, analysisResult.imports); } else if (hasStructureChanges) { newContent = this.reorderImportsInContent(content, processedImports, analysisResult.imports); } return { content: newContent, modified: content !== newContent, optimized: Math.max(unusedRemoved, duplicatesMerged, pathsConverted), unusedRemoved, duplicatesMerged, pathsConverted }; } catch (error) { return { content, modified: false, optimized: 0, unusedRemoved: 0, duplicatesMerged: 0, pathsConverted: 0, errors: [error.message] }; } } initializeFramework() { let frameworkConfig = null; if (this.options.framework) { frameworkConfig = this.frameworkDetector.getFrameworkByName(this.options.framework); } else { frameworkConfig = this.frameworkDetector.detectFramework(); } if (frameworkConfig) { if (this.options.verbose) { } this.pathResolver.addAliases(frameworkConfig.aliases); } } initializeAliases() { if (this.options.aliases && this.options.aliases.length > 0) { this.pathResolver.addAliases(this.options.aliases); } } getTransformOptions() { return { style: this.options.style, sort: this.options.sort, group: this.options.group, removeUnused: this.options.removeUnused, mergeDuplicates: this.options.mergeDuplicates, multilineThreshold: this.options.multilineThreshold, aliases: this.options.aliases, preserveComments: this.options.preserveComments }; } countImports(content) { const importRegex = /^import\s+.*?from\s+['"][^'"]+['"];?$/gm; const matches = content.match(importRegex); return matches ? matches.length : 0; } removeUnusedImports(imports, usedIdentifiers) { return imports .filter(importStmt => { return importStmt.specifiers.some((spec) => { return usedIdentifiers.has(spec.local); }); }) .map(importStmt => { const usedSpecifiers = importStmt.specifiers.filter((spec) => { return usedIdentifiers.has(spec.local); }); return { ...importStmt, specifiers: usedSpecifiers }; }); } mergeDuplicateImports(imports) { const sourceMap = new Map(); for (const importStmt of imports) { const key = `${importStmt.source}:${importStmt.importKind}`; if (!sourceMap.has(key)) { sourceMap.set(key, []); } sourceMap.get(key).push(importStmt); } const mergedImports = []; for (const [, group] of sourceMap) { if (group.length === 1) { mergedImports.push(group[0]); } else { mergedImports.push(this.astAnalyzer.mergeImports(group)); } } return mergedImports; } convertImportPaths(imports, filePath) { let converted = 0; for (const importStmt of imports) { const originalSource = importStmt.source; if (this.options.style === 'absolute') { importStmt.source = this.pathResolver.convertToAbsolute(originalSource, filePath); } else if (this.options.style === 'relative') { importStmt.source = this.pathResolver.convertToRelative(originalSource, filePath); } if (originalSource !== importStmt.source) { converted++; } } return converted; } reorderImportsInContent(content, processedImports, originalImports) { if (originalImports.length === 0) return content; const sourceToString = new Map(); originalImports.forEach(imp => { const importString = content.substring(imp.startPos, imp.endPos); sourceToString.set(imp.source, importString); }); let orderedImports = [...originalImports]; if (this.options.group && this.options.sort) { orderedImports = this.groupImportsForReorder(orderedImports, true); } else if (this.options.group) { orderedImports = this.groupImportsForReorder(orderedImports, false); } else if (this.options.sort) { orderedImports = this.sortImportsForReorder(orderedImports); } const reorderedStrings = orderedImports .map(imp => sourceToString.get(imp.source) || '') .filter(Boolean); return this.replaceImportBlock(content, originalImports, reorderedStrings.join('\n')); } replaceImportsInContent(content, transformedImports, originalImports) { if (originalImports.length === 0) { return content; } const sortedImports = [...originalImports] .filter(imp => imp.startPos !== undefined && imp.endPos !== undefined) .sort((a, b) => b.startPos - a.startPos); if (sortedImports.length === 0) { return content; } let result = content; for (const importStmt of sortedImports) { const before = result.substring(0, importStmt.startPos); const after = result.substring(importStmt.endPos); result = before + after; } const firstImportPos = Math.min(...originalImports.map(i => i.startPos)); const beforeFirst = result.substring(0, firstImportPos); const afterFirst = result.substring(firstImportPos); return beforeFirst + transformedImports + afterFirst; } groupImportsForReorder(imports, shouldSort = false) { const groups = { external: [], internal: [], relative: [] }; for (const imp of imports) { if (imp.source.startsWith('.')) { groups.relative.push(imp); } else if (imp.source.startsWith('@/') || imp.source.startsWith('~/')) { groups.internal.push(imp); } else { groups.external.push(imp); } } if (shouldSort) { groups.external.sort((a, b) => a.source.localeCompare(b.source)); groups.internal.sort((a, b) => a.source.localeCompare(b.source)); groups.relative.sort((a, b) => a.source.localeCompare(b.source)); } return [...groups.external, ...groups.internal, ...groups.relative]; } sortImportsForReorder(imports) { return [...imports].sort((a, b) => a.source.localeCompare(b.source)); } replaceImportBlock(content, originalImports, newImportsBlock) { if (originalImports.length === 0) return content; const firstImport = originalImports.reduce((min, imp) => imp.startPos < min.startPos ? imp : min); const lastImport = originalImports.reduce((max, imp) => (imp.endPos > max.endPos ? imp : max)); const before = content.substring(0, firstImport.startPos); const after = content.substring(lastImport.endPos); return before + newImportsBlock + after; } static parseAliasesFromString(aliasString) { return path_resolver_1.PathResolver.parseCliAliases(aliasString); } } exports.ImportsProcessor = ImportsProcessor; //# sourceMappingURL=logic.js.map