wechat-share-icon
🔍 实时预览
JavaScript 行 1, 列 1
UTF-8 未保存 预览: 开启
`, css: `/* 欢迎使用CSS编辑器 */ body { font-family: 'Arial', sans-serif; margin: 0; padding: 0; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); min-height: 100vh; display: flex; align-items: center; justify-content: center; } .container { background: rgba(255, 255, 255, 0.1); backdrop-filter: blur(20px); border-radius: 20px; padding: 40px; text-align: center; color: white; box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1); } .title { font-size: 2.5rem; margin-bottom: 20px; text-shadow: 0 2px 4px rgba(0, 0, 0, 0.3); } .description { font-size: 1.2rem; margin-bottom: 30px; opacity: 0.9; } .button { background: linear-gradient(135deg, #ff6b6b, #ee5a24); color: white; border: none; padding: 15px 30px; border-radius: 10px; font-size: 1rem; font-weight: 600; cursor: pointer; transition: all 0.3s ease; box-shadow: 0 4px 15px rgba(238, 90, 36, 0.3); } .button:hover { transform: translateY(-2px); box-shadow: 0 6px 20px rgba(238, 90, 36, 0.4); }`, python: `# 欢迎使用Python编辑器! print("Hello, World!") # 这是一个简单的Python示例 def greet_user(name): return f"Hello, {name}! 欢迎使用代码编辑器。" # 调用函数 message = greet_user("开发者") print(message) # 一个简单的计算器 def calculator(a, b, operation): if operation == "+": return a + b elif operation == "-": return a - b elif operation == "*": return a * b elif operation == "/": return a / b if b != 0 else "不能除以零" else: return "未知操作" # 测试计算器 result = calculator(10, 5, "+") print(f"10 + 5 = {result}") # 你可以在这里编写更多Python代码...`, json: `{ "name": "我的项目", "version": "1.0.0", "description": "这是一个示例JSON文件", "author": "开发者", "main": "index.js", "scripts": { "start": "node index.js", "build": "webpack --mode production", "dev": "webpack-dev-server --mode development" }, "dependencies": { "express": "^4.17.1", "lodash": "^4.17.21", "moment": "^2.29.1" }, "devDependencies": { "webpack": "^5.0.0", "webpack-cli": "^4.0.0" }, "keywords": [ "javascript", "nodejs", "web" ], "license": "MIT" }`, markdown: `# 📝 欢迎使用Markdown编辑器 这是一个功能强大的**Markdown编辑器**,支持实时预览。 ## 🚀 特性 - ✅ 实时预览 - ✅ 语法高亮 - ✅ 多种主题 - ✅ 自动保存 ## 📖 语法示例 ### 文本格式 *斜体文本* **粗体文本** ***粗斜体文本*** ~~删除线文本~~ ### 代码块 \`\`\`javascript function hello() { console.log("Hello, World!"); } \`\`\` ### 列表 1. 第一项 2. 第二项 3. 第三项 - 无序列表项一 - 无序列表项二 - 无序列表项三 ### 链接和图片 [GitHub](https://github.com) ### 表格 | 姓名 | 年龄 | 城市 | |------|------|------| | 张三 | 25 | 北京 | | 李四 | 30 | 上海 | ### 引用 > 这是一个引用块。 > 可以包含多行内容。 --- **开始编写你的Markdown文档吧!** 🎉` }; this.createFile('main.' + this.getFileExtension(this.currentLanguage), defaultContent[this.currentLanguage] || defaultContent.javascript); } createFile(name, content = '') { const fileId = `file_${++this.fileCounter}`; const file = { id: fileId, name: name, content: content, language: this.detectLanguage(name), modified: false, created: new Date() }; this.files.set(fileId, file); this.currentFile = fileId; this.updateFileList(); this.updateEditorTabs(); this.loadFile(fileId); return fileId; } createNewFile() { const name = prompt('请输入文件名:', 'untitled.' + this.getFileExtension(this.currentLanguage)); if (name) { this.createFile(name); } } addFileDialog() { this.createNewFile(); } loadFile(fileId) { const file = this.files.get(fileId); if (!file) return; this.currentFile = fileId; const codeEditor = document.getElementById('codeEditor'); codeEditor.value = file.content; this.setLanguage(file.language); this.updateLineNumbers(); this.updateCursorPosition(); this.updateFileStatus(); this.updateEditorTabs(); if (this.settings.livePreview) { this.updatePreview(); } } saveFile() { if (!this.currentFile) return; const file = this.files.get(this.currentFile); if (!file) return; const codeEditor = document.getElementById('codeEditor'); file.content = codeEditor.value; file.modified = false; file.lastSaved = new Date(); this.updateFileStatus(); this.updateEditorTabs(); // 模拟保存到本地存储 this.saveToLocalStorage(); this.showMessage('文件已保存', 'success'); } deleteFile(fileId) { if (this.files.size <= 1) { this.showMessage('至少需要保留一个文件', 'warning' ); return; } if (confirm('确定要删除这个文件吗?')) { this.files.delete(fileId); if (this.currentFile===fileId) { const remainingFiles=Array.from(this.files.keys()); this.loadFile(remainingFiles[0]); } this.updateFileList(); this.updateEditorTabs(); } } onCodeChange() { if (!this.currentFile) return; const file=this.files.get(this.currentFile); if (!file) return; const codeEditor=document.getElementById('codeEditor'); file.content=codeEditor.value; file.modified=true; this.updateFileStatus(); this.updateEditorTabs(); this.applySyntaxHighlighting(); } updateFileList() { const fileList=document.getElementById('fileList'); fileList.innerHTML='' ; this.files.forEach((file, fileId)=> { const fileItem = document.createElement('div'); fileItem.className = `file-item ${fileId === this.currentFile ? 'active' : ''}`; fileItem.innerHTML = ` ${this.getFileIcon(file.language)} ${file.name}${file.modified ? ' *' : ''} `; fileItem.addEventListener('click', () => this.loadFile(fileId)); fileItem.addEventListener('contextmenu', (e) => { e.preventDefault(); this.showFileContextMenu(e, fileId); }); fileList.appendChild(fileItem); }); } updateEditorTabs() { const editorTabs = document.getElementById('editorTabs'); editorTabs.innerHTML = ''; this.files.forEach((file, fileId) => { const tab = document.createElement('button'); tab.className = `editor-tab ${fileId === this.currentFile ? 'active' : ''}`; tab.innerHTML = ` ${file.name}${file.modified ? ' *' : ''} `; tab.addEventListener('click', () => this.loadFile(fileId)); editorTabs.appendChild(tab); }); } closeFile(fileId) { const file = this.files.get(fileId); if (file && file.modified) { if (!confirm('文件未保存,确定要关闭吗?')) { return; } } this.deleteFile(fileId); } getFileIcon(language) { const icons = { javascript: '📄', html: '🌐', css: '🎨', python: '🐍', json: '📋', markdown: '📝' }; return icons[language] || '📄'; } getFileExtension(language) { const extensions = { javascript: 'js', html: 'html', css: 'css', python: 'py', json: 'json', markdown: 'md' }; return extensions[language] || 'txt'; } detectLanguage(filename) { const ext = filename.split('.').pop().toLowerCase(); const languageMap = { js: 'javascript', html: 'html', htm: 'html', css: 'css', py: 'python', json: 'json', md: 'markdown' }; return languageMap[ext] || 'javascript'; } setLanguage(language) { this.currentLanguage = language; document.getElementById('languageStatus').textContent = language.charAt(0).toUpperCase() + language.slice(1); if (this.currentFile) { const file = this.files.get(this.currentFile); if (file) { file.language = language; } } this.applySyntaxHighlighting(); this.updateFileList(); } updateLineNumbers() { const codeEditor = document.getElementById('codeEditor'); const lineNumbers = document.getElementById('lineNumbers'); const lines = codeEditor.value.split('\n'); const lineNumbersText = lines.map((_, index) => index + 1).join('\n'); lineNumbers.textContent = lineNumbersText; } syncLineNumbers() { const codeEditor = document.getElementById('codeEditor'); const lineNumbers = document.getElementById('lineNumbers'); lineNumbers.scrollTop = codeEditor.scrollTop; } updateCursorPosition() { const codeEditor = document.getElementById('codeEditor'); const text = codeEditor.value; const cursorPos = codeEditor.selectionStart; const lines = text.substring(0, cursorPos).split('\n'); const currentLine = lines.length; const currentColumn = lines[lines.length - 1].length + 1; document.getElementById('positionStatus').textContent = `行 ${currentLine}, 列 ${currentColumn}`; const selectionLength = codeEditor.selectionEnd - codeEditor.selectionStart; if (selectionLength > 0) { document.getElementById('selectionStatus').textContent = `选中 ${selectionLength} 个字符`; } else { document.getElementById('selectionStatus').textContent = ''; } } updateFileStatus() { if (!this.currentFile) { document.getElementById('fileStatus').textContent = '无文件'; return; } const file = this.files.get(this.currentFile); if (!file) return; document.getElementById('fileStatus').textContent = file.modified ? '未保存' : '已保存'; } handleKeyDown(e) { const codeEditor = document.getElementById('codeEditor'); if (e.key === 'Tab') { e.preventDefault(); const start = codeEditor.selectionStart; const end = codeEditor.selectionEnd; const spaces = ' '.repeat(this.settings.tabSize); codeEditor.value = codeEditor.value.substring(0, start) + spaces + codeEditor.value.substring(end); codeEditor.selectionStart = codeEditor.selectionEnd = start + spaces.length; this.onCodeChange(); } else if (e.key === 'Enter') { // 自动缩进 setTimeout(() => { const lines = codeEditor.value.substring(0, codeEditor.selectionStart).split('\n'); const currentLine = lines[lines.length - 2] || ''; const indent = currentLine.match(/^\s*/)[0]; if (currentLine.trim().endsWith('{') || currentLine.trim().endsWith(':')) { const newIndent = indent + ' '.repeat(this.settings.tabSize); const start = codeEditor.selectionStart; codeEditor.value = codeEditor.value.substring(0, start) + newIndent + codeEditor.value.substring(start); codeEditor.selectionStart = codeEditor.selectionEnd = start + newIndent.length; } else if (indent) { const start = codeEditor.selectionStart; codeEditor.value = codeEditor.value.substring(0, start) + indent + codeEditor.value.substring(start); codeEditor.selectionStart = codeEditor.selectionEnd = start + indent.length; } this.onCodeChange(); }, 0); } this.updateCursorPosition(); } showAutocomplete() { const codeEditor = document.getElementById('codeEditor'); const popup = document.getElementById('autocompletePopup'); if (!this.settings.autoComplete) { popup.style.display = 'none'; return; } const cursorPos = codeEditor.selectionStart; const text = codeEditor.value.substring(0, cursorPos); const words = text.split(/\s+/); const currentWord = words[words.length - 1]; if (currentWord.length < 2) { popup.style.display='none' ; return; } const suggestions=this.getAutocompleteSuggestions(currentWord); if (suggestions.length===0) { popup.style.display='none' ; return; } this.showAutocompleteSuggestions(suggestions, currentWord); } getAutocompleteSuggestions(word) { const data=this.autocompleteData[this.currentLanguage] || []; return data.filter(item=> item.name.toLowerCase().startsWith(word.toLowerCase()) ).slice(0, 10); } showAutocompleteSuggestions(suggestions, word) { const popup = document.getElementById('autocompletePopup'); const codeEditor = document.getElementById('codeEditor'); popup.innerHTML = ''; suggestions.forEach((suggestion, index) => { const item = document.createElement('div'); item.className = `autocomplete-item ${index === 0 ? 'selected' : ''}`; item.innerHTML = ` ${this.getAutocompleteIcon(suggestion.type)} ${suggestion.name} `; item.addEventListener('click', () => { this.insertAutocompletion(word, suggestion.name); this.hideAutocomplete(); }); popup.appendChild(item); }); // 定位弹窗 const rect = codeEditor.getBoundingClientRect(); const textRect = this.getCursorPosition(); popup.style.left = `${textRect.left}px`; popup.style.top = `${textRect.top + 20}px`; popup.style.display = 'block'; } hideAutocomplete() { document.getElementById('autocompletePopup').style.display = 'none'; } insertAutocompletion(word, completion) { const codeEditor = document.getElementById('codeEditor'); const cursorPos = codeEditor.selectionStart; const text = codeEditor.value; const beforeCursor = text.substring(0, cursorPos - word.length); const afterCursor = text.substring(cursorPos); codeEditor.value = beforeCursor + completion + afterCursor; codeEditor.selectionStart = codeEditor.selectionEnd = beforeCursor.length + completion.length; this.onCodeChange(); codeEditor.focus(); } getAutocompleteIcon(type) { const icons = { keyword: 'K', function: 'F', method: 'M', property: 'P', tag: 'T', variable: 'V' }; return icons[type] || 'I'; } getCursorPosition() { const codeEditor = document.getElementById('codeEditor'); const rect = codeEditor.getBoundingClientRect(); // 简化实现,返回编辑器位置 return { left: rect.left + 50, top: rect.top + 50 }; } applySyntaxHighlighting() { // 简化的语法高亮实现 // 在实际项目中,可以使用更强大的语法高亮库如 Prism.js 或 highlight.js } formatCode() { const codeEditor = document.getElementById('codeEditor'); let code = codeEditor.value; try { switch (this.currentLanguage) { case 'javascript': code = this.formatJavaScript(code); break; case 'html': code = this.formatHTML(code); break; case 'css': code = this.formatCSS(code); break; case 'json': code = JSON.stringify(JSON.parse(code), null, this.settings.tabSize); break; } codeEditor.value = code; this.onCodeChange(); this.showMessage('代码格式化完成', 'success'); } catch (error) { this.showMessage('代码格式化失败: ' + error.message, 'error'); } } formatJavaScript(code) { // 简化的JavaScript格式化 return code .split('\n') .map(line => line.trim()) .filter(line => line.length > 0) .join('\n'); } formatHTML(code) { // 简化的HTML格式化 let indent = 0; const tabSize = this.settings.tabSize; return code .replace(/>\n<' ) .split('\n') .map(line=> { line = line.trim(); if (line.startsWith('')) { indent += tabSize; } return formatted; }) .join('\n'); } formatCSS(code) { // 简化的CSS格式化 return code .replace(/\{/g, ' {\n') .replace(/\}/g, '\n}\n') .replace(/;/g, ';\n') .split('\n') .map(line => { line = line.trim(); if (line && !line.includes('{') && !line.includes('}')) { return ' ' + line; } return line; }) .filter(line => line.length > 0) .join('\n'); } runCode() { if (this.currentLanguage === 'javascript') { this.runJavaScript(); } else if (this.currentLanguage === 'python') { this.runPython(); } else { this.updatePreview(); } } runJavaScript() { const codeEditor = document.getElementById('codeEditor'); const code = codeEditor.value; this.clearConsole(); this.showConsole(); try { // 重定向console.log const originalLog = console.log; console.log = (...args) => { this.addConsoleMessage(args.join(' '), 'info'); originalLog.apply(console, args); }; // 执行代码 eval(code); // 恢复console.log console.log = originalLog; this.addConsoleMessage('代码执行完成', 'info'); } catch (error) { this.addConsoleMessage(`错误: ${error.message}`, 'error'); } } runPython() { this.addConsoleMessage('Python代码执行需要服务器支持', 'warn'); this.showConsole(); } updatePreview() { const previewFrame = document.getElementById('previewFrame'); if (this.currentLanguage === 'html') { const content = document.getElementById('codeEditor').value; const blob = new Blob([content], { type: 'text/html' }); const url = URL.createObjectURL(blob); previewFrame.src = url; } else if (this.currentLanguage === 'markdown') { const content = this.renderMarkdown(document.getElementById('codeEditor').value); const blob = new Blob([content], { type: 'text/html' }); const url = URL.createObjectURL(blob); previewFrame.src = url; } else { previewFrame.src = 'data:text/html,

此语言不支持预览

'; } } renderMarkdown(markdown) { // 简化的Markdown渲染 return ` 在线游戏大全 - 免费HTML5休闲游戏集合 | 工具箱
${this.parseMarkdown(markdown)}
`; } parseMarkdown(text) { return text .replace(/^### (.*$)/gim, '

$1

') .replace(/^## (.*$)/gim, '

$1

') .replace(/^# (.*$)/gim, '

$1

') .replace(/\*\*\*(.*)\*\*\*/gim, '$1') .replace(/\*\*(.*)\*\*/gim, '$1') .replace(/\*(.*)\*/gim, '$1') .replace(/~~(.*)~~/gim, '$1') .replace(/`([^`]+)`/gim, '$1') .replace(/\n/gim, '
'); } openInNewTab() { if (this.currentLanguage === 'html') { const content = document.getElementById('codeEditor').value; const newWindow = window.open(); newWindow.document.write(content); newWindow.document.close(); } } toggleConsole() { const consolePanel = document.getElementById('consolePanel'); this.settings.showConsole = !this.settings.showConsole; if (this.settings.showConsole) { consolePanel.classList.add('show'); this.addConsoleMessage('控制台已打开', 'info'); } else { consolePanel.classList.remove('show'); } } showConsole() { const consolePanel = document.getElementById('consolePanel'); this.settings.showConsole = true; consolePanel.classList.add('show'); } clearConsole() { document.getElementById('consolePanel').innerHTML = ''; } addConsoleMessage(message, type = 'info') { const consolePanel = document.getElementById('consolePanel'); const line = document.createElement('div'); line.className = `console-line console-${type}`; line.textContent = `${new Date().toLocaleTimeString()} ${message}`; consolePanel.appendChild(line); consolePanel.scrollTop = consolePanel.scrollHeight; } toggleMinimap() { const minimap = document.getElementById('minimap'); this.settings.showMinimap = !this.settings.showMinimap; minimap.style.display = this.settings.showMinimap ? 'block' : 'none'; } toggleWordWrap() { const codeEditor = document.getElementById('codeEditor'); this.settings.wordWrap = !this.settings.wordWrap; codeEditor.style.whiteSpace = this.settings.wordWrap ? 'pre-wrap' : 'pre'; } toggleFullscreen() { if (!document.fullscreenElement) { document.documentElement.requestFullscreen(); } else { document.exitFullscreen(); } } saveToHistory() { if (!this.currentFile) return; const file = this.files.get(this.currentFile); if (!file) return; const state = { fileId: this.currentFile, content: file.content, timestamp: Date.now() }; this.history.push(state); if (this.history.length > this.maxHistorySize) { this.history.shift(); } this.historyIndex = this.history.length - 1; } undo() { if (this.historyIndex > 0) { this.historyIndex--; const state = this.history[this.historyIndex]; const file = this.files.get(state.fileId); if (file) { file.content = state.content; document.getElementById('codeEditor').value = state.content; this.updateLineNumbers(); } } } redo() { if (this.historyIndex < this.history.length - 1) { this.historyIndex++; const state=this.history[this.historyIndex]; const file=this.files.get(state.fileId); if (file) { file.content=state.content; document.getElementById('codeEditor').value=state.content; this.updateLineNumbers(); } } } showFindDialog() { const searchTerm=prompt('查找:'); if (searchTerm) { this.findText(searchTerm); } } showReplaceDialog() { const searchTerm=prompt('查找:'); if (searchTerm) { const replaceTerm=prompt('替换为:'); if (replaceTerm !==null) { this.replaceText(searchTerm, replaceTerm); } } } findText(searchTerm) { const codeEditor=document.getElementById('codeEditor'); const content=codeEditor.value; const index=content.indexOf(searchTerm); if (index !==-1) { codeEditor.focus(); codeEditor.setSelectionRange(index, index + searchTerm.length); this.showMessage(`找到 "${searchTerm}" `, 'success' ); } else { this.showMessage(`未找到 "${searchTerm}" `, 'warning' ); } } replaceText(searchTerm, replaceTerm) { const codeEditor=document.getElementById('codeEditor'); const content=codeEditor.value; const newContent=content.replace(new RegExp(searchTerm, 'g' ), replaceTerm); codeEditor.value=newContent; this.onCodeChange(); this.showMessage(`已替换所有 "${searchTerm}" `, 'success' ); } setTheme(theme) { this.settings.theme=theme; this.applyTheme(); this.saveSettings(); } applyTheme() { const themeData=this.themes[this.settings.theme]; if (!themeData) return; const codeEditor=document.getElementById('codeEditor'); const lineNumbers=document.getElementById('lineNumbers'); codeEditor.style.backgroundColor=themeData.background; codeEditor.style.color=themeData.color; lineNumbers.style.backgroundColor=themeData.lineNumberBg; lineNumbers.style.color=themeData.lineNumberColor; } applySettings() { const codeEditor=document.getElementById('codeEditor'); codeEditor.style.fontSize=this.settings.fontSize + 'px' ; codeEditor.style.fontFamily=this.settings.fontFamily; codeEditor.style.tabSize=this.settings.tabSize; document.getElementById('lineNumbers').style.fontSize=this.settings.fontSize + 'px' ; document.getElementById('lineNumbers').style.fontFamily=this.settings.fontFamily; this.updateLineNumbers(); this.saveSettings(); } saveSettings() { localStorage.setItem('codeEditorSettings', JSON.stringify(this.settings)); } loadSettings() { const saved=localStorage.getItem('codeEditorSettings'); if (saved) { try { this.settings={ ...this.settings, ...JSON.parse(saved) }; document.getElementById('fontSize').value=this.settings.fontSize; document.getElementById('tabSize').value=this.settings.tabSize; document.getElementById('fontFamily').value=this.settings.fontFamily; this.applySettings(); } catch (error) { console.error('加载设置失败:', error); } } } saveToLocalStorage() { const data={ files: Array.from(this.files.entries()), currentFile: this.currentFile, settings: this.settings }; localStorage.setItem('codeEditorData', JSON.stringify(data)); } loadFromLocalStorage() { const saved=localStorage.getItem('codeEditorData'); if (saved) { try { const data=JSON.parse(saved); this.files=new Map(data.files); this.currentFile=data.currentFile; this.settings={ ...this.settings, ...data.settings }; if (this.files.size> 0) { this.updateFileList(); this.updateEditorTabs(); if (this.currentFile && this.files.has(this.currentFile)) { this.loadFile(this.currentFile); } } } catch (error) { console.error('加载数据失败:', error); } } } showMessage(message, type = 'info') { // 简化的消息显示 console.log(`[${type.toUpperCase()}] ${message}`); // 可以在这里添加更好的消息显示UI const statusBar = document.querySelector('.status-bar .status-right'); const messageEl = document.createElement('span'); messageEl.textContent = message; messageEl.style.color = type === 'error' ? '#ff6b6b' : type === 'success' ? '#4ecdc4' : '#ffd93d'; statusBar.appendChild(messageEl); setTimeout(() => { statusBar.removeChild(messageEl); }, 3000); } showFileContextMenu(e, fileId) { // 简化的右键菜单实现 if (confirm('删除这个文件?')) { this.deleteFile(fileId); } } } // 全局变量用于访问编辑器实例 let editor; // 初始化编辑器 document.addEventListener('DOMContentLoaded', () => { editor = new CodeEditor(); });