Show description
AI Code Refactor
AI Code Refactor
AI Code Refactor
Paste your code below, and the AI will split it into separate files.
Original Code
Refactor Code
Refactored files will appear here.
AI Code Refactor
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>AI Code Refactor</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.5/codemirror.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.5/theme/dracula.min.css">
<style>
body {
font-family: 'Inter', sans-serif;
}
/* Enforce theme styles to prevent conflicts */
.CodeMirror {
height: 100%;
border-radius: 0.5rem;
background: #282a36; /* Dracula theme background */
color: #f8f8f2; /* Dracula theme text color */
}
.file-window {
transition: all 0.3s ease-in-out;
}
</style>
</head>
<body class="bg-gray-900 text-white flex flex-col h-screen">
<header class="bg-gray-800 p-4 shadow-md z-10">
<h1 class="text-2xl font-bold text-center">AI Code Refactor</h1>
<p class="text-center text-gray-400">Paste your code below, and the AI will split it into separate files.</p>
</header>
<main class="flex-grow flex flex-col md:flex-row p-4 gap-4 overflow-hidden">
<!-- Input Code Editor -->
<div class="flex flex-col w-full md:w-1/2 h-full bg-gray-800 rounded-lg shadow-lg p-4">
<h2 class="text-lg font-semibold mb-2">Original Code</h2>
<!-- This div will now contain the editor and handle scrolling -->
<div class="flex-grow relative overflow-hidden">
<textarea id="codeInput" class="w-full h-full"></textarea>
</div>
<button id="refactorBtn" class="mt-4 bg-blue-600 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded-lg transition-colors disabled:bg-gray-500">
<span id="btn-text">Refactor Code</span>
<span id="loading-spinner" class="hidden animate-spin rounded-full h-5 w-5 border-b-2 border-white inline-block"></span>
</button>
</div>
<!-- Output Files -->
<div id="outputContainer" class="w-full md:w-1/2 h-full flex flex-col gap-4 overflow-y-auto p-1">
<div id="placeholder" class="text-center text-gray-500 self-center">
Refactored files will appear here.
</div>
</div>
</main>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.5/codemirror.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.5/mode/javascript/javascript.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.5/mode/xml/xml.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.5/mode/css/css.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.5/mode/php/php.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.5/mode/clike/clike.min.js"></script>
<script>
// Initialize the main code editor
const codeInput = CodeMirror.fromTextArea(document.getElementById('codeInput'), {
lineNumbers: true,
theme: 'dracula',
mode: 'javascript'
});
const refactorBtn = document.getElementById('refactorBtn');
const outputContainer = document.getElementById('outputContainer');
const placeholder = document.getElementById('placeholder');
const btnText = document.getElementById('btn-text');
const loadingSpinner = document.getElementById('loading-spinner');
// Function to display messages in the output area
function showMessage(message, type = 'info') {
let bgColor, textColor, borderColor, title;
switch(type) {
case 'error':
bgColor = 'bg-red-900';
textColor = 'text-red-300';
borderColor = 'border-red-500';
title = 'Error!';
break;
case 'warning':
bgColor = 'bg-yellow-900';
textColor = 'text-yellow-300';
borderColor = 'border-yellow-500';
title = 'Warning!';
break;
default:
bgColor = 'bg-gray-700';
textColor = 'text-gray-300';
borderColor = 'border-gray-600';
title = 'Info';
}
outputContainer.innerHTML = `
<div class="${bgColor} border ${borderColor} ${textColor} px-4 py-3 rounded-lg relative self-center" role="alert">
<strong class="font-bold">${title}</strong>
<span class="block sm:inline">${message}</span>
</div>`;
}
refactorBtn.addEventListener('click', async () => {
const userCode = codeInput.getValue();
if (!userCode.trim()) {
showMessage("Please paste some code into the editor before refactoring.", "warning");
return;
}
// Show loading state
btnText.classList.add('hidden');
loadingSpinner.classList.remove('hidden');
refactorBtn.disabled = true;
outputContainer.innerHTML = '<div class="text-center text-gray-500 self-center">AI is thinking...</div>';
try {
// IMPORTANT: An API key is required for this to work.
// Get a key from Google AI Studio: https://aistudio.google.com/app/apikey
const apiKey = ""; // <-- PASTE YOUR GEMINI API KEY HERE
if (!apiKey) {
throw new Error(`API key is not set. Get a free key from <a href="https://aistudio.google.com/app/apikey" target="_blank" class="text-blue-400 underline">Google AI Studio</a> and paste it into the script.`);
}
const prompt = `
Analyze the following code block. Your task is to act as an expert software architect.
Do not create new code. Do not modify the existing code.
Your only job is to review the code and separate it into logical files.
Cut and paste the relevant code into separate files.
Provide the output as a single, raw JSON object with an array named "files".
Each object in the "files" array should have two properties: "fileName" (e.g., "index.html", "style.css", "script.js") and "code" (the actual code for that file).
Do not include any explanations or markdown formatting (like \`\`\`json) in your response. Only provide the raw JSON object.
Here is the code:
\`\`\`
${userCode}
\`\`\`
`;
const apiUrl = `https://generativelanguage.googleapis.com/v1beta/models/gemini-pro:generateContent?key=${apiKey}`;
const payload = {
contents: [{
parts: [{
text: prompt
}]
}]
};
const response = await fetch(apiUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(payload)
});
if (!response.ok) {
const errorBody = await response.text();
throw new Error(`API request failed with status ${response.status}. Details: ${errorBody}`);
}
const result = await response.json();
if (result.candidates && result.candidates[0].content.parts.length > 0) {
let jsonString = result.candidates[0].content.parts[0].text;
// Clean the response to get only the JSON part, though the prompt now asks for raw JSON.
const jsonMatch = jsonString.match(/\n*```json\n([\s\S]*?)\n```/);
if (jsonMatch && jsonMatch[1]) {
jsonString = jsonMatch[1];
} else {
const jsonMatchPlain = jsonString.match(/\{[\s\S]*\}/);
if(jsonMatchPlain) {
jsonString = jsonMatchPlain[0];
}
}
try {
const refactoredData = JSON.parse(jsonString);
displayFiles(refactoredData.files);
// "Cut" the code from the original editor
codeInput.setValue('// Code successfully refactored and moved to the windows on the right.');
} catch (e) {
console.error("Failed to parse JSON response:", e);
console.error("Raw response from AI:", jsonString);
throw new Error("Could not parse the AI's response. It might not be valid JSON. Check the console for details.");
}
} else {
throw new Error("The AI returned an empty response.");
}
} catch (error) {
console.error('Error during refactoring:', error);
showMessage(error.message, 'error');
} finally {
// Hide loading state
btnText.classList.remove('hidden');
loadingSpinner.classList.add('hidden');
refactorBtn.disabled = false;
}
});
function displayFiles(files) {
outputContainer.innerHTML = ''; // Clear previous content
if (files && files.length > 0) {
placeholder.classList.add('hidden');
files.forEach(file => {
const fileWindow = document.createElement('div');
fileWindow.className = 'file-window bg-gray-800 rounded-lg shadow-lg flex flex-col h-2/3'; // Set a height for the window
const titleBar = document.createElement('div');
titleBar.className = 'bg-gray-700 p-2 rounded-t-lg font-semibold text-center cursor-pointer';
titleBar.textContent = file.fileName;
fileWindow.appendChild(titleBar);
const editorContainer = document.createElement('div');
editorContainer.className = 'flex-grow p-2 relative overflow-hidden';
fileWindow.appendChild(editorContainer);
const newEditor = document.createElement('textarea');
editorContainer.appendChild(newEditor);
outputContainer.appendChild(fileWindow);
const fileExtension = file.fileName.split('.').pop();
let mode = 'javascript';
if (fileExtension === 'html' || fileExtension === 'php') mode = 'xml';
if (fileExtension === 'css') mode = 'css';
const editorInstance = CodeMirror.fromTextArea(newEditor, {
value: file.code,
lineNumbers: true,
theme: 'dracula',
mode: mode,
readOnly: false
});
// Refresh editor to ensure it displays correctly after being added to the DOM
setTimeout(() => editorInstance.refresh(), 1);
});
} else {
showMessage("The AI did not create any files from the provided code.", "info");
}
}
</script>
</body>
</html>