Files
thermcool/refactor_buttons.cjs
T

135 lines
5.3 KiB
JavaScript

/* eslint-disable */
const fs = require('fs');
const path = require('path');
const directories = ['app', 'components'];
const patterns = [
{
regex: /className=["']flex items-center gap-2 px-6 py-3 bg-accent text-white rounded-xl font-bold hover:bg-accent\/90 transition-colors["']/g,
replace: "className={buttonClasses({ variant: 'primary', size: 'md' })}"
},
{
regex: /className=["']flex items-center gap-2 px-6 py-3 bg-white\/10 text-white rounded-xl font-bold hover:bg-white\/20 transition-colors border border-white\/20["']/g,
replace: "className={buttonClasses({ variant: 'outline', size: 'md' })}"
},
{
regex: /className=["']flex items-center gap-2 px-8 py-4 bg-accent text-white rounded-xl font-bold text-lg hover:bg-accent\/90 transition-colors["']/g,
replace: "className={buttonClasses({ variant: 'primary', size: 'lg' })}"
},
{
regex: /className=["']flex items-center gap-2 px-8 py-4 bg-white\/10 text-white rounded-xl font-bold text-lg hover:bg-white\/20 transition-colors border border-white\/20["']/g,
replace: "className={buttonClasses({ variant: 'outline', size: 'lg' })}"
},
{
regex: /className=["']btn btn-primary text-white font-bold["']/g,
replace: "className={buttonClasses({ variant: 'primary', size: 'md' })}"
},
{
regex: /className=["']btn btn-primary font-bold["']/g,
replace: "className={buttonClasses({ variant: 'primary', size: 'md' })}"
},
{
regex: /className=["']flex items-center gap-1\.5 px-4 py-2 bg-red-500 text-white rounded-\[var\(--radius-field\)\] font-bold text-sm hover:bg-red-600 transition-colors whitespace-nowrap["']/g,
replace: "className={buttonClasses({ variant: 'error', size: 'sm' })}"
}
];
// In case there are some dynamic classNames (template literals):
const dynamicPatterns = [
{
regex: /className=\{`flex items-center gap-2 px-6 py-3 bg-accent text-white rounded-xl font-bold hover:bg-accent\/90 transition-colors (.*?)`\}/g,
replace: "className={buttonClasses({ variant: 'primary', size: 'md', className: `$1` })}"
},
{
regex: /className=\{`btn btn-primary font-bold (.*?)`\}/g,
replace: "className={buttonClasses({ variant: 'primary', size: 'md', className: `$1` })}"
}
];
function processDirectory(dir) {
const files = fs.readdirSync(dir);
for (const file of files) {
const fullPath = path.join(dir, file);
const stat = fs.statSync(fullPath);
if (stat.isDirectory()) {
processDirectory(fullPath);
} else if (file.endsWith('.tsx') || file.endsWith('.jsx')) {
// Don't process the Button.tsx itself
if (fullPath.includes('Button.tsx')) continue;
let content = fs.readFileSync(fullPath, 'utf8');
let originalContent = content;
let changed = false;
let usedButtonClasses = false;
let usedButtonComponent = false;
// 1. Tag conversion: <button className={...} ...> to <Button ...>
// We'll first apply the className replacements
for (const p of patterns) {
if (p.regex.test(content)) {
content = content.replace(p.regex, p.replace);
changed = true;
usedButtonClasses = true;
}
}
for (const p of dynamicPatterns) {
if (p.regex.test(content)) {
content = content.replace(p.regex, p.replace);
changed = true;
usedButtonClasses = true;
}
}
// 2. Convert `<button className={buttonClasses({ variant: 'X', size: 'Y' })}>` to `<Button variant="X" size="Y">`
// This is a bit tricky with regex, but let's try safely:
// Pattern: <button (.*?)className=\{buttonClasses\(\{ variant: '([^']+)', size: '([^']+)' \}\)\}(.*?)>
const buttonToComponentRegex = /<button([^>]*)className=\{buttonClasses\(\{\s*variant:\s*'([^']+)',\s*size:\s*'([^']+)'\s*\}\)\}([^>]*)>/g;
if (buttonToComponentRegex.test(content)) {
content = content.replace(buttonToComponentRegex, '<Button$1variant="$2" size="$3"$4>');
usedButtonComponent = true;
}
// Also match closing tags
if (usedButtonComponent) {
content = content.replace(/<\/button>/g, '</Button>');
}
if (changed) {
// We still might have used buttonClasses for <Link> tags
const needsButtonClasses = content.includes('buttonClasses(');
// Inject imports
const imports = [];
if (needsButtonClasses) imports.push('buttonClasses');
if (usedButtonComponent) imports.push('Button');
if (imports.length > 0) {
const importStr = `import { ${imports.join(', ')} } from '@/components/ui/Button';\n`;
// Find the last import
const importRegex = /^import.*$/gm;
let match;
let lastImportIndex = -1;
while ((match = importRegex.exec(content)) !== null) {
lastImportIndex = match.index + match[0].length;
}
if (lastImportIndex !== -1) {
content = content.slice(0, lastImportIndex) + '\n' + importStr + content.slice(lastImportIndex);
} else {
content = importStr + content;
}
}
fs.writeFileSync(fullPath, content, 'utf8');
console.log(`Updated ${fullPath}`);
}
}
}
}
for (const dir of directories) {
processDirectory(path.join(__dirname, dir));
}