crapifyme
Version:
Ultra-fast developer productivity CLI tools - remove comments, logs, and more
278 lines • 10.8 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ImportTransformer = void 0;
const types_1 = require("./types");
class ImportTransformer {
constructor(options = {}) {
this.indentation = ' ';
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
};
}
transformImports(imports, filePath, originalContent) {
if (originalContent) {
this.detectIndentation(originalContent);
}
let processedImports = [...imports];
if (this.options.mergeDuplicates) {
processedImports = this.mergeDuplicateImports(processedImports);
}
if (this.options.removeUnused) {
processedImports = this.removeUnusedImports(processedImports);
}
if (this.options.style !== 'mixed') {
processedImports = this.convertImportPaths(processedImports, filePath);
}
if (this.options.group) {
const groups = this.groupImports(processedImports);
return this.renderImportGroups(groups);
}
if (this.options.sort) {
processedImports = this.sortImports(processedImports);
}
return this.renderImports(processedImports);
}
detectIndentation(content) {
const multilineMatch = content.match(/import\s*{[^}]*\n(\s+)[^}]/);
if (multilineMatch && multilineMatch[1]) {
this.indentation = multilineMatch[1];
return;
}
const lines = content.split('\n');
for (const line of lines) {
const match = line.match(/^(\s+)\S/);
if (match && match[1]) {
this.indentation = match[1];
return;
}
}
}
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.mergeImportGroup(group));
}
}
return mergedImports;
}
mergeImportGroup(imports) {
const mergedSpecifiers = [];
const seenLocals = new Set();
for (const importStmt of imports) {
for (const spec of importStmt.specifiers) {
const key = `${spec.type}:${spec.local}:${spec.imported || ''}`;
if (!seenLocals.has(key)) {
mergedSpecifiers.push(spec);
seenLocals.add(key);
}
}
}
return {
source: imports[0].source,
specifiers: mergedSpecifiers,
importKind: imports[0].importKind,
startPos: Math.min(...imports.map(i => i.startPos)),
endPos: Math.max(...imports.map(i => i.endPos)),
leadingComments: imports[0].leadingComments,
trailingComments: imports[imports.length - 1].trailingComments
};
}
removeUnusedImports(imports) {
return imports.filter(importStmt => {
return importStmt.specifiers.length > 0;
});
}
convertImportPaths(imports, filePath) {
return imports.map(importStmt => {
const convertedSource = this.convertPath(importStmt.source, filePath);
return { ...importStmt, source: convertedSource };
});
}
convertPath(importPath, filePath) {
if (this.isExternalModule(importPath)) {
return importPath;
}
for (const alias of this.options.aliases) {
if (alias.regex.test(importPath)) {
return importPath.replace(alias.regex, alias.replacement);
}
}
if (this.options.style === types_1.ImportStyle.ABSOLUTE) {
return this.toAbsolutePath(importPath, filePath);
}
else if (this.options.style === types_1.ImportStyle.RELATIVE) {
return this.toRelativePath(importPath, filePath);
}
return importPath;
}
isExternalModule(path) {
return (!path.startsWith('.') &&
!path.startsWith('/') &&
!path.startsWith('@/') &&
!path.startsWith('~/'));
}
toAbsolutePath(importPath, filePath) {
if (importPath.startsWith('./')) {
const dir = filePath.split('/').slice(0, -1).join('/');
return `@/${dir}/${importPath.slice(2)}`.replace(/\/+/g, '/');
}
if (importPath.startsWith('../')) {
const dir = filePath.split('/').slice(0, -1);
const parts = importPath.split('/');
let upCount = 0;
for (const part of parts) {
if (part === '..') {
upCount++;
dir.pop();
}
else if (part !== '.') {
dir.push(part);
}
}
return `@/${dir.join('/')}`.replace(/\/+/g, '/');
}
return importPath;
}
toRelativePath(importPath, filePath) {
if (importPath.startsWith('@/')) {
const currentDir = filePath.split('/').slice(0, -1);
const targetPath = importPath.slice(2).split('/');
let relativePath = '';
let commonIndex = 0;
while (commonIndex < Math.min(currentDir.length, targetPath.length) &&
currentDir[commonIndex] === targetPath[commonIndex]) {
commonIndex++;
}
const upLevels = currentDir.length - commonIndex;
relativePath = '../'.repeat(upLevels);
relativePath += targetPath.slice(commonIndex).join('/');
return relativePath || './';
}
return importPath;
}
groupImports(imports) {
const groups = new Map([
[types_1.ImportGroupType.EXTERNAL, []],
[types_1.ImportGroupType.INTERNAL, []],
[types_1.ImportGroupType.RELATIVE, []]
]);
for (const importStmt of imports) {
const groupType = this.getImportGroupType(importStmt.source);
groups.get(groupType).push(importStmt);
}
const result = [];
if (groups.get(types_1.ImportGroupType.EXTERNAL).length > 0) {
result.push({
type: types_1.ImportGroupType.EXTERNAL,
imports: this.sortImports(groups.get(types_1.ImportGroupType.EXTERNAL)),
priority: 1
});
}
if (groups.get(types_1.ImportGroupType.INTERNAL).length > 0) {
result.push({
type: types_1.ImportGroupType.INTERNAL,
imports: this.sortImports(groups.get(types_1.ImportGroupType.INTERNAL)),
priority: 2
});
}
if (groups.get(types_1.ImportGroupType.RELATIVE).length > 0) {
result.push({
type: types_1.ImportGroupType.RELATIVE,
imports: this.sortImports(groups.get(types_1.ImportGroupType.RELATIVE)),
priority: 3
});
}
return result;
}
getImportGroupType(source) {
if (source.startsWith('.')) {
return types_1.ImportGroupType.RELATIVE;
}
if (source.startsWith('@/') || source.startsWith('~/')) {
return types_1.ImportGroupType.INTERNAL;
}
return types_1.ImportGroupType.EXTERNAL;
}
sortImports(imports) {
return imports.slice().sort((a, b) => {
return a.source.localeCompare(b.source);
});
}
renderImportGroups(groups) {
return groups
.sort((a, b) => a.priority - b.priority)
.map(group => this.renderImports(group.imports))
.filter(group => group.trim().length > 0)
.join('\n\n');
}
renderImports(imports) {
return imports.map(importStmt => this.renderImport(importStmt)).join('\n');
}
renderImport(importStmt) {
const comments = this.renderComments(importStmt);
const importLine = this.renderImportLine(importStmt);
return comments ? `${comments}\n${importLine}` : importLine;
}
renderComments(importStmt) {
if (!this.options.preserveComments)
return '';
const comments = [];
if (importStmt.leadingComments) {
comments.push(...importStmt.leadingComments.map(c => `// ${c}`));
}
return comments.join('\n');
}
renderImportLine(importStmt) {
const typePrefix = importStmt.importKind === 'type' ? 'type ' : '';
if (importStmt.specifiers.length === 0) {
return `import${typePrefix ? ` ${typePrefix}` : ''} '${importStmt.source}';`;
}
const defaultSpecs = importStmt.specifiers.filter(s => s.type === 'default');
const namespaceSpecs = importStmt.specifiers.filter(s => s.type === 'namespace');
const namedSpecs = importStmt.specifiers.filter(s => s.type === 'named');
const parts = [];
if (defaultSpecs.length > 0) {
parts.push(defaultSpecs[0].local);
}
if (namespaceSpecs.length > 0) {
parts.push(`* as ${namespaceSpecs[0].local}`);
}
if (namedSpecs.length > 0) {
const namedItems = namedSpecs.map(spec => {
const typePrefix = spec.importKind === 'type' ? 'type ' : '';
const name = spec.imported === spec.local ? spec.local : `${spec.imported} as ${spec.local}`;
return `${typePrefix}${name}`;
});
const shouldUseMultiline = namedItems.length > this.options.multilineThreshold;
if (shouldUseMultiline) {
parts.push(`{\n${this.indentation}${namedItems.join(',\n' + this.indentation)}\n}`);
}
else {
parts.push(`{ ${namedItems.join(', ')} }`);
}
}
const importList = parts.join(', ');
return `import ${typePrefix}${importList} from '${importStmt.source}';`;
}
}
exports.ImportTransformer = ImportTransformer;
//# sourceMappingURL=import-transformer.js.map