File
Edit
View
Help
Explorer
Welcome to VSCode Web Editor
Start by creating a new file or opening an existing project
New File
New Folder
main
0 ⚠ 0 ✗
Ln 1, Col 1
Plain Text
UTF-8
New File
New Folder
Rename
Delete
`, modified: false }, 'style.css': { type: 'file', content: `body { font-family: Arial, sans-serif; margin: 0; padding: 20px; background-color: #f0f0f0; } h1 { color: #333; text-align: center; }`, modified: false }, 'script.js': { type: 'file', content: `console.log('Hello from JavaScript!'); function greet(name) { return \`Hello, \${name}!\`; } document.addEventListener('DOMContentLoaded', () => { console.log(greet('World')); });`, modified: false }, 'src/': { type: 'folder', expanded: false }, 'src/components/': { type: 'folder', expanded: false }, 'src/utils.js': { type: 'file', content: `// Utility functions export function formatDate(date) { return date.toLocaleDateString(); } export function debounce(func, wait) { let timeout; return function executedFunction(...args) { const later = () => { clearTimeout(timeout); func(...args); }; clearTimeout(timeout); timeout = setTimeout(later, wait); }; }`, modified: false } }; saveFileSystem(); } function saveFileSystem() { localStorage.setItem('vscode-files', JSON.stringify(fileSystem)); } function renderFileTree() { const explorer = document.getElementById('fileExplorer'); explorer.innerHTML = ''; const sortedPaths = Object.keys(fileSystem).sort((a, b) => { const aIsFolder = fileSystem[a].type === 'folder'; const bIsFolder = fileSystem[b].type === 'folder'; if (aIsFolder && !bIsFolder) return -1; if (!aIsFolder && bIsFolder) return 1; return a.localeCompare(b); }); sortedPaths.forEach(path => { const item = fileSystem[path]; const element = createFileTreeItem(path, item); explorer.appendChild(element); }); } function createFileTreeItem(path, item) { const div = document.createElement('div'); div.className = 'file-tree-item'; div.dataset.path = path; const depth = (path.match(/\//g) || []).length; div.style.paddingLeft = `${15 + depth * 20}px`; if (item.type === 'folder') { const folderIcon = document.createElement('span'); folderIcon.className = `folder-icon ${item.expanded ? 'icon-folder-open' : 'icon-folder'}`; folderIcon.onclick = (e) => { e.stopPropagation(); toggleFolder(path); }; div.appendChild(folderIcon); } else { const fileIcon = document.createElement('span'); fileIcon.className = `file-icon ${getFileIcon(path)}`; div.appendChild(fileIcon); } const name = document.createElement('span'); name.textContent = path.split('/').pop() || path; div.appendChild(name); div.onclick = () => { if (item.type === 'file') { openFile(path); } }; div.oncontextmenu = (e) => { e.preventDefault(); showContextMenu(e, path); }; return div; } function getFileIcon(path) { const ext = path.split('.').pop().toLowerCase(); switch (ext) { case 'js': return 'icon-js'; case 'html': return 'icon-html'; case 'css': return 'icon-css'; default: return 'icon-file'; } } function toggleFolder(path) { fileSystem[path].expanded = !fileSystem[path].expanded; saveFileSystem(); renderFileTree(); } function openFile(path) { // Check if tab already exists const existingTab = openTabs.find(tab => tab.path === path); if (existingTab) { switchToTab(path); return; } // Create new tab const file = fileSystem[path]; const tab = { path: path, name: path.split('/').pop(), content: file.content, originalContent: file.content, modified: file.modified || false }; openTabs.push(tab); activeTab = tab; renderTabs(); loadFileInEditor(tab); updateStatusBar(); // Hide welcome screen document.getElementById('welcomeScreen').style.display = 'none'; document.getElementById('monaco-editor').style.display = 'block'; } function renderTabs() { const tabsContainer = document.getElementById('editorTabs'); tabsContainer.innerHTML = ''; openTabs.forEach(tab => { const tabElement = document.createElement('div'); tabElement.className = `editor-tab ${tab === activeTab ? 'active' : ''}`; tabElement.dataset.path = tab.path; const tabName = document.createElement('span'); tabName.textContent = tab.name + (tab.modified ? ' •' : ''); tabElement.appendChild(tabName); const closeButton = document.createElement('span'); closeButton.className = 'tab-close icon-close'; closeButton.onclick = (e) => { e.stopPropagation(); closeTab(tab.path); }; tabElement.appendChild(closeButton); tabElement.onclick = () => switchToTab(tab.path); tabsContainer.appendChild(tabElement); }); } function switchToTab(path) { const tab = openTabs.find(t => t.path === path); if (!tab) return; activeTab = tab; loadFileInEditor(tab); renderTabs(); updateStatusBar(); } function closeTab(path) { const tabIndex = openTabs.findIndex(tab => tab.path === path); if (tabIndex === -1) return; const tab = openTabs[tabIndex]; // Save content before closing if (tab.modified) { fileSystem[path].content = tab.content; fileSystem[path].modified = false; saveFileSystem(); } openTabs.splice(tabIndex, 1); if (activeTab && activeTab.path === path) { if (openTabs.length > 0) { const newActiveIndex = Math.min(tabIndex, openTabs.length - 1); activeTab = openTabs[newActiveIndex]; loadFileInEditor(activeTab); } else { activeTab = null; document.getElementById('welcomeScreen').style.display = 'flex'; document.getElementById('monaco-editor').style.display = 'none'; } } renderTabs(); updateStatusBar(); } function loadFileInEditor(tab) { if (!editor) return; const language = getLanguageFromPath(tab.path); const model = monaco.editor.createModel(tab.content, language); editor.setModel(model); // Update tab content when editor changes model.onDidChangeContent(() => { tab.content = editor.getValue(); tab.modified = tab.content !== tab.originalContent; fileSystem[tab.path].content = tab.content; fileSystem[tab.path].modified = tab.modified; updateTabTitle(tab.path); saveFileSystem(); }); } function getLanguageFromPath(path) { const ext = path.split('.').pop().toLowerCase(); switch (ext) { case 'js': return 'javascript'; case 'html': return 'html'; case 'css': return 'css'; case 'json': return 'json'; case 'py': return 'python'; case 'md': return 'markdown'; default: return 'plaintext'; } } function updateTabTitle(path) { const tab = openTabs.find(t => t.path === path); if (!tab) return; renderTabs(); } function updateStatusBar() { if (!editor || !activeTab) return; const position = editor.getPosition(); document.getElementById('statusPosition').textContent = `Ln ${position.lineNumber}, Col ${position.column}`; const language = getLanguageFromPath(activeTab.path); document.getElementById('statusLanguage').textContent = language.charAt(0).toUpperCase() + language.slice(1); } // Context menu function showContextMenu(e, path) { contextTarget = path; const menu = document.getElementById('contextMenu'); menu.style.display = 'block'; menu.style.left = e.pageX + 'px'; menu.style.top = e.pageY + 'px'; } function hideContextMenu() { document.getElementById('contextMenu').style.display = 'none'; contextTarget = null; } // File operations function createNewFile() { const name = prompt('Enter file name:'); if (!name) return; const path = contextTarget && fileSystem[contextTarget]?.type === 'folder' ? `${contextTarget}${name}` : name; if (fileSystem[path]) { alert('File already exists!'); return; } fileSystem[path] = { type: 'file', content: '', modified: false }; saveFileSystem(); renderFileTree(); openFile(path); hideContextMenu(); } function createNewFolder() { const name = prompt('Enter folder name:'); if (!name) return; const path = contextTarget && fileSystem[contextTarget]?.type === 'folder' ? `${contextTarget}${name}/` : `${name}/`; if (fileSystem[path]) { alert('Folder already exists!'); return; } fileSystem[path] = { type: 'folder', expanded: false }; saveFileSystem(); renderFileTree(); hideContextMenu(); } function renameItem() { if (!contextTarget) return; const currentName = contextTarget.split('/').pop() || contextTarget.slice(0, -1); const newName = prompt('Enter new name:', currentName); if (!newName || newName === currentName) return; const pathParts = contextTarget.split('/'); pathParts[pathParts.length - (contextTarget.endsWith('/') ? 2 : 1)] = newName; const newPath = pathParts.join('/'); if (fileSystem[newPath]) { alert('Item with this name already exists!'); return; } fileSystem[newPath] = fileSystem[contextTarget]; delete fileSystem[contextTarget]; // Update open tabs const tab = openTabs.find(t => t.path === contextTarget); if (tab) { tab.path = newPath; tab.name = newName; } saveFileSystem(); renderFileTree(); renderTabs(); hideContextMenu(); } function deleteItem() { if (!contextTarget) return; if (!confirm(`Are you sure you want to delete ${contextTarget}?`)) return; // Close tab if open const tabIndex = openTabs.findIndex(tab => tab.path === contextTarget); if (tabIndex !== -1) { closeTab(contextTarget); } delete fileSystem[contextTarget]; saveFileSystem(); renderFileTree(); hideContextMenu(); } // UI functions function toggleSidebar() { const sidebar = document.getElementById('sidebar'); sidebar.style.display = sidebar.style.display === 'none' ? 'flex' : 'none'; } function showMenu(menuType) { // Placeholder for menu functionality console.log(`${menuType} menu clicked`); } // Keyboard shortcuts document.addEventListener('keydown', (e) => { if (e.ctrlKey || e.metaKey) { switch (e.key) { case 's': e.preventDefault(); if (activeTab) { fileSystem[activeTab.path].content = activeTab.content; fileSystem[activeTab.path].modified = false; activeTab.modified = false; activeTab.originalContent = activeTab.content; saveFileSystem(); renderTabs(); } break; case 'n': e.preventDefault(); createNewFile(); break; case 'w': e.preventDefault(); if (activeTab) { closeTab(activeTab.path); } break; } } }); // Hide context menu on click outside document.addEventListener('click', hideContextMenu); // Prevent context menu on right click outside file tree document.addEventListener('contextmenu', (e) => { if (!e.target.closest('.file-explorer')) { e.preventDefault(); } }); // Initialize file tree on load window.addEventListener('load', () => { if (Object.keys(fileSystem).length > 0) { renderFileTree(); } });