https://mi-sitio.neocities.org 💾 Cambios locales
index.html Líneas: 0 Columna: 0
`, 'style.css': `body { font-family: Arial, sans-serif; max-width: 800px; margin: 50px auto; padding: 20px; background: #fafafa; color: #333; } h1 { color: #0077cc; }`, 'script.js': `console.log('Hola desde mi sitio!');` }; let fileSystem = JSON.parse(localStorage.getItem('siteFiles')) || JSON.parse(JSON.stringify(defaultFiles)); let openTabs = JSON.parse(localStorage.getItem('openTabs')) || ['index.html']; let activeTab = localStorage.getItem('activeTab') || 'index.html'; let currentModalAction = null; let selectedSidebarItem = null; function saveToLocalStorage() { localStorage.setItem('siteFiles', JSON.stringify(fileSystem)); localStorage.setItem('openTabs', JSON.stringify(openTabs)); localStorage.setItem('activeTab', activeTab); } function updateURL() { const name = document.getElementById('pageName').value.trim() || 'mi-sitio'; document.getElementById('urlPreview').textContent = `https://${name}.neocities.org`; } function renderSidebar() { const sidebar = document.getElementById('sidebar'); sidebar.innerHTML = '

📂 Archivos

'; const sorted = Object.keys(fileSystem).sort((a,b) => { const aIsFolder = !a.includes('.'); const bIsFolder = !b.includes('.'); if (aIsFolder && !bIsFolder) return -1; if (!aIsFolder && bIsFolder) return 1; return a.localeCompare(b); }); sorted.forEach(filename => { const div = document.createElement('div'); div.className = 'file-item'; const isFolder = !filename.includes('.'); if (isFolder) div.classList.add('folder'); if (filename === selectedSidebarItem) div.classList.add('active'); div.innerHTML = `${isFolder ? '📁' : '📄'} ${filename}`; div.onclick = (e) => { selectedSidebarItem = filename; if (!isFolder) openFile(filename); renderSidebar(); }; sidebar.appendChild(div); }); } function openFile(filename) { if (!openTabs.includes(filename)) { openTabs.push(filename); } activeTab = filename; renderTabs(); loadFileContent(filename); saveToLocalStorage(); } function loadFileContent(filename) { const editor = document.getElementById('editor'); const preview = document.getElementById('preview'); editor.value = fileSystem[filename] || ''; document.getElementById('statusFile').textContent = filename; updateLineCount(); if (filename.endsWith('.html') && preview.classList.contains('visible')) { updatePreview(); } document.getElementById('fileType').value = filename.includes('.') ? filename.split('.').pop() : 'txt'; } function renderTabs() { const tabBar = document.getElementById('tabBar'); tabBar.innerHTML = ''; openTabs.forEach(tab => { const div = document.createElement('div'); div.className = 'tab' + (tab === activeTab ? ' active' : ''); div.innerHTML = `${tab} ✕`; div.onclick = () => { activeTab = tab; selectedSidebarItem = tab; loadFileContent(tab); renderTabs(); renderSidebar(); saveToLocalStorage(); }; tabBar.appendChild(div); }); if (openTabs.length === 0) { activeTab = 'index.html'; if (!fileSystem['index.html']) fileSystem['index.html'] = defaultFiles['index.html']; openTabs = ['index.html']; renderTabs(); loadFileContent('index.html'); renderSidebar(); saveToLocalStorage(); } } function closeTab(filename) { const index = openTabs.indexOf(filename); if (index > -1) { openTabs.splice(index, 1); if (activeTab === filename) { activeTab = openTabs[Math.max(0, index - 1)] || null; if (activeTab) loadFileContent(activeTab); } renderTabs(); saveToLocalStorage(); } } function updateLineCount() { const editor = document.getElementById('editor'); const lines = editor.value.split('\n').length; document.getElementById('statusLines').textContent = `Líneas: ${lines}`; } document.getElementById('editor').addEventListener('input', () => { if (activeTab && fileSystem[activeTab] !== undefined) { fileSystem[activeTab] = document.getElementById('editor').value; updateLineCount(); saveToLocalStorage(); if (activeTab.endsWith('.html') && document.getElementById('preview').classList.contains('visible')) { updatePreview(); } } }); document.getElementById('editor').addEventListener('keydown', (e) => { const pos = e.target.selectionStart; const lines = e.target.value.substr(0, pos).split('\n'); document.getElementById('statusCol').textContent = `Columna: ${lines[lines.length-1].length + 1}`; }); document.getElementById('editor').addEventListener('click', function(e) { const pos = e.target.selectionStart; const lines = e.target.value.substr(0, pos).split('\n'); document.getElementById('statusCol').textContent = `Columna: ${lines[lines.length-1].length + 1}`; }); function togglePreview() { const editor = document.getElementById('editor'); const preview = document.getElementById('preview'); const btn = document.querySelector('.toolbar button.run'); if (preview.classList.contains('visible')) { preview.classList.remove('visible'); editor.classList.remove('hidden'); btn.textContent = '▶️ Run / Preview'; btn.classList.remove('active'); } else { preview.classList.add('visible'); editor.classList.add('hidden'); btn.textContent = '📝 Volver al código'; btn.classList.add('active'); updatePreview(); } } function updatePreview() { const preview = document.getElementById('preview'); const htmlContent = document.getElementById('editor').value; let fullHTML = htmlContent; if (activeTab && activeTab.endsWith('.html')) { const cssContent = fileSystem['style.css'] || ''; const jsContent = fileSystem['script.js'] || ''; fullHTML = htmlContent .replace('', ``) .replace('', ``); if (!fullHTML.includes('`); } if (!fullHTML.includes('`); } } preview.srcdoc = fullHTML; } function newFile() { currentModalAction = 'file'; document.getElementById('modalTitle').textContent = 'Nuevo archivo'; document.getElementById('modalInput').value = ''; document.getElementById('modal').style.display = 'flex'; document.getElementById('modalInput').focus(); } function newFolder() { currentModalAction = 'folder'; document.getElementById('modalTitle').textContent = 'Nueva carpeta'; document.getElementById('modalInput').value = ''; document.getElementById('modal').style.display = 'flex'; document.getElementById('modalInput').focus(); } function confirmModal() { const name = document.getElementById('modalInput').value.trim(); if (!name) return; if (currentModalAction === 'file') { let filename = name.includes('.') ? name : name + '.html'; if (fileSystem[filename]) { alert('Ya existe un archivo con ese nombre'); return; } fileSystem[filename] = ''; openFile(filename); } else if (currentModalAction === 'folder') { let foldername = name.includes('.') ? name : name + '/'; if (!foldername.endsWith('/')) foldername += '/'; if (fileSystem[foldername]) { alert('Ya existe una carpeta con ese nombre'); return; } fileSystem[foldername] = {}; } closeModal(); renderSidebar(); saveToLocalStorage(); } function closeModal() { document.getElementById('modal').style.display = 'none'; currentModalAction = null; } function deleteSelected() { if (!selectedSidebarItem) { alert('Selecciona un archivo o carpeta en la barra lateral'); return; } if (confirm(`¿Eliminar "${selectedSidebarItem}"?`)) { delete fileSystem[selectedSidebarItem]; const tabIndex = openTabs.indexOf(selectedSidebarItem); if (tabIndex > -1) { openTabs.splice(tabIndex, 1); if (activeTab === selectedSidebarItem) { activeTab = openTabs[0] || null; if (!activeTab) { fileSystem['index.html'] = defaultFiles['index.html']; activeTab = 'index.html'; openTabs = ['index.html']; } loadFileContent(activeTab); } } selectedSidebarItem = null; renderSidebar(); renderTabs(); saveToLocalStorage(); } } function duplicateFile() { if (!selectedSidebarItem || !selectedSidebarItem.includes('.')) { alert('Selecciona un archivo para duplicar'); return; } const parts = selectedSidebarItem.split('.'); const ext = parts.pop(); const base = parts.join('.'); let newName = `${base}-copia.${ext}`; let counter = 1; while (fileSystem[newName]) { newName = `${base}-copia${counter}.${ext}`; counter++; } fileSystem[newName] = fileSystem[selectedSidebarItem]; renderSidebar(); saveToLocalStorage(); openFile(newName); } function changeFileType() { if (!activeTab || !activeTab.includes('.')) return; const newExt = document.getElementById('fileType').value; const parts = activeTab.split('.'); const oldExt = parts.pop(); const base = parts.join('.'); if (newExt === oldExt) return; const newName = `${base}.${newExt}`; if (fileSystem[newName] && newName !== activeTab) { alert('Ya existe un archivo con esa extensión'); document.getElementById('fileType').value = oldExt; return; } fileSystem[newName] = fileSystem[activeTab]; delete fileSystem[activeTab]; const tabIndex = openTabs.indexOf(activeTab); if (tabIndex > -1) openTabs[tabIndex] = newName; if (activeTab === activeTab) activeTab = newName; if (selectedSidebarItem === activeTab) selectedSidebarItem = newName; renderSidebar(); renderTabs(); loadFileContent(newName); saveToLocalStorage(); } document.getElementById('modalInput').addEventListener('keydown', (e) => { if (e.key === 'Enter') confirmModal(); if (e.key === 'Escape') closeModal(); }); document.getElementById('modal').addEventListener('click', function(e) { if (e.target === this) closeModal(); }); document.addEventListener('keydown', (e) => { if ((e.ctrlKey || e.metaKey) && e.key === 's') { e.preventDefault(); saveToLocalStorage(); const statusBar = document.querySelector('.status-bar span:first-child'); statusBar.textContent = `💾 Guardado: ${activeTab}`; setTimeout(() => { document.getElementById('statusFile').textContent = activeTab; }, 1500); } }); updateURL(); renderSidebar(); renderTabs(); loadFileContent(activeTab); selectedSidebarItem = activeTab; renderSidebar();