smart-renamer
Version:
🚀 Intelligent file naming suggestions based on project-specific naming conventions. Interactive CLI tool that asks yes/no for each file renaming.
98 lines • 3.74 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.NamingValidator = void 0;
class NamingValidator {
static CONVENTION_PATTERNS = {
'camelCase': /^[a-z][a-zA-Z0-9]*$/,
'snake_case': /^[a-z][a-z0-9_]*$/,
'kebab-case': /^[a-z][a-z0-9-]*$/,
'PascalCase': /^[A-Z][a-zA-Z0-9]*$/,
'UPPER_SNAKE_CASE': /^[A-Z][A-Z0-9_]*$/
};
static validateName(name, convention, exceptions = []) {
const baseName = this.getBaseName(name);
if (exceptions.includes(baseName.toLowerCase())) {
return {
isValid: true,
convention,
message: `File '${name}' is in the exceptions list`
};
}
const pattern = this.CONVENTION_PATTERNS[convention];
const isValid = pattern.test(baseName);
if (isValid) {
return {
isValid: true,
convention,
message: `File '${name}' follows ${convention} convention`
};
}
const expectedName = this.convertToConvention(baseName, convention);
return {
isValid: false,
expectedName: expectedName + this.getExtension(name),
convention,
message: `File '${name}' should be '${expectedName + this.getExtension(name)}' to follow ${convention} convention`
};
}
static convertToConvention(name, convention) {
const baseName = this.getBaseName(name);
const words = this.extractWords(baseName);
switch (convention) {
case 'camelCase':
return words[0]?.toLowerCase() + words.slice(1).map(this.capitalize).join('');
case 'snake_case':
return words.map(w => w.toLowerCase()).join('_');
case 'kebab-case':
return words.map(w => w.toLowerCase()).join('-');
case 'PascalCase':
return words.map(this.capitalize).join('');
case 'UPPER_SNAKE_CASE':
return words.map(w => w.toUpperCase()).join('_');
default:
return baseName;
}
}
static detectConvention(names) {
const scores = {
'camelCase': 0,
'snake_case': 0,
'kebab-case': 0,
'PascalCase': 0,
'UPPER_SNAKE_CASE': 0
};
for (const name of names) {
const baseName = this.getBaseName(name);
for (const [convention, pattern] of Object.entries(this.CONVENTION_PATTERNS)) {
if (pattern.test(baseName)) {
scores[convention]++;
}
}
}
const maxScore = Math.max(...Object.values(scores));
if (maxScore === 0)
return null;
const detectedConvention = Object.entries(scores).find(([, score]) => score === maxScore)?.[0];
return detectedConvention || null;
}
static getBaseName(filename) {
const lastDotIndex = filename.lastIndexOf('.');
return lastDotIndex > 0 ? filename.substring(0, lastDotIndex) : filename;
}
static getExtension(filename) {
const lastDotIndex = filename.lastIndexOf('.');
return lastDotIndex > 0 ? filename.substring(lastDotIndex) : '';
}
static extractWords(name) {
return name
.replace(/([a-z])([A-Z])/g, '$1 $2')
.replace(/[_-]/g, ' ')
.split(/\s+/)
.filter(word => word.length > 0);
}
static capitalize(word) {
return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase();
}
}
exports.NamingValidator = NamingValidator;
//# sourceMappingURL=naming-validator.js.map