代码格式化工具edit icon

作者:
藤原
Fork(复制)
下载
嵌入
设置
BUG反馈
index.html
现在支持上传本地图片了!
            
            <!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Code Formatter | 高级代码格式化工具</title>
    <style>
        :root {
            --primary: #2563eb;
            --primary-light: #3b82f6;
            --primary-dark: #1d4ed8;
            --dark: #1e293b;
            --light: #f8fafc;
            --gray: #94a3b8;
            --gray-light: #e2e8f0;
            --success: #10b981;
            --error: #ef4444;
        }
        
        * {
            box-sizing: border-box;
            margin: 0;
            padding: 0;
        }
        
        body {
            font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
            line-height: 1.6;
            background-color: #f1f5f9;
            color: var(--dark);
            min-height: 100vh;
            padding: 0;
        }
        
        .app-container {
            max-width: 1200px;
            margin: 0 auto;
            padding: 1rem;
            display: flex;
            flex-direction: column;
            min-height: 100vh;
        }
        
        header {
            margin-bottom: 1.5rem;
            text-align: center;
            padding: 0 0.5rem;
        }
        
        h1 {
            font-size: 1.5rem;
            font-weight: 600;
            color: var(--dark);
            margin-bottom: 0.25rem;
            letter-spacing: -0.025em;
        }
        
        .subtitle {
            color: var(--gray);
            font-size: 0.875rem;
            font-weight: 400;
        }
        
        .main-content {
            display: flex;
            flex-direction: column;
            flex: 1;
            background: white;
            border-radius: 0.75rem;
            box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
            overflow: hidden;
        }
        
        .toolbar {
            display: flex;
            flex-direction: column;
            gap: 0.75rem;
            padding: 0.75rem;
            border-bottom: 1px solid var(--gray-light);
            background: white;
        }
        
        .toolbar-row {
            display: flex;
            gap: 0.75rem;
            align-items: center;
        }
        
        .mode-selector {
            display: flex;
            gap: 0.25rem;
            overflow-x: auto;
            padding-bottom: 0.25rem;
            scrollbar-width: none;
            flex: 1;
        }
        
        .mode-selector::-webkit-scrollbar {
            display: none;
        }
        
        .mode-btn {
            padding: 0.5rem 0.75rem;
            font-size: 0.8125rem;
            font-weight: 500;
            border-radius: 0.375rem;
            cursor: pointer;
            border: 1px solid var(--gray-light);
            background: white;
            color: var(--dark);
            transition: all 0.2s ease;
            white-space: nowrap;
        }
        
        .mode-btn:hover {
            background: #f8fafc;
        }
        
        .mode-btn.active {
            background: var(--primary);
            color: white;
            border-color: var(--primary);
        }
        
        .settings {
            display: flex;
            gap: 0.5rem;
            align-items: center;
        }
        
        .indent-control {
            display: flex;
            align-items: center;
            gap: 0.25rem;
        }
        
        .indent-control label {
            font-size: 0.8125rem;
            color: var(--dark);
            white-space: nowrap;
        }
        
        .indent-control input {
            width: 3rem;
            padding: 0.25rem 0.5rem;
            border: 1px solid var(--gray-light);
            border-radius: 0.25rem;
            text-align: center;
        }
        
        .action-buttons {
            display: flex;
            gap: 0.5rem;
            justify-content: space-between;
        }
        
        .btn {
            padding: 0.5rem 0.75rem;
            font-size: 0.8125rem;
            font-weight: 500;
            border-radius: 0.375rem;
            cursor: pointer;
            border: none;
            transition: all 0.2s ease;
            display: flex;
            align-items: center;
            gap: 0.375rem;
            flex: 1;
            justify-content: center;
        }
        
        .btn-primary {
            background: var(--primary);
            color: white;
        }
        
        .btn-primary:hover {
            background: var(--primary-light);
        }
        
        .btn-secondary {
            background: white;
            color: var(--dark);
            border: 1px solid var(--gray-light);
        }
        
        .btn-secondary:hover {
            background: #f8fafc;
        }
        
        .btn-success {
            background: var(--success);
            color: white;
        }
        
        .btn-success:hover {
            background: #0d9f6e;
        }
        
        .code-editor {
            display: flex;
            flex-direction: column;
            flex: 1;
            min-height: 400px;
            position: relative;
        }
        
        .input-section, .output-section {
            flex: 1;
            display: flex;
            flex-direction: column;
            padding: 1rem;
        }
        
        .input-section {
            border-bottom: 1px solid var(--gray-light);
        }
        
        .section-header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 0.75rem;
        }
        
        .section-title {
            font-size: 0.8125rem;
            font-weight: 600;
            color: var(--dark);
            text-transform: uppercase;
            letter-spacing: 0.05em;
        }
        
        textarea, .output-content {
            flex: 1;
            width: 100%;
            padding: 0.75rem;
            font-family: 'Fira Code', 'Consolas', monospace;
            font-size: 0.8125rem;
            line-height: 1.7;
            border: 1px solid var(--gray-light);
            border-radius: 0.5rem;
            resize: none;
            background: #f8fafc;
            color: var(--dark);
            min-height: 150px;
        }
        
        textarea:focus {
            outline: none;
            border-color: var(--primary);
            box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.1);
        }
        
        .output-content {
            overflow: auto;
            white-space: pre-wrap;
            background: #f8fafc;
        }
        
        .status-bar {
            padding: 0.75rem;
            border-top: 1px solid var(--gray-light);
            background: white;
            display: flex;
            flex-direction: column;
            gap: 0.5rem;
            font-size: 0.8125rem;
        }
        
        .status-info {
            display: flex;
            align-items: center;
            gap: 0.5rem;
            justify-content: space-between;
        }
        
        .status-message {
            color: var(--dark);
            font-size: 0.8125rem;
            overflow: hidden;
            text-overflow: ellipsis;
            white-space: nowrap;
        }
        
        .status-message.success {
            color: var(--success);
        }
        
        .status-message.error {
            color: var(--error);
        }
        
        .detected-type {
            background: var(--gray-light);
            padding: 0.25rem 0.5rem;
            border-radius: 0.25rem;
            font-size: 0.75rem;
            font-weight: 500;
            white-space: nowrap;
        }
        
        @media (min-width: 768px) {
            .app-container {
                padding: 2rem;
            }
            
            .toolbar {
                flex-direction: row;
                flex-wrap: wrap;
                justify-content: space-between;
                align-items: center;
                padding: 1rem 1.5rem;
                gap: 1rem;
            }
            
            .toolbar-row {
                flex: 1;
                gap: 1rem;
            }
            
            .mode-selector {
                gap: 0.5rem;
            }
            
            .mode-btn {
                padding: 0.5rem 1rem;
                font-size: 0.875rem;
            }
            
            .action-buttons {
                gap: 0.75rem;
                justify-content: flex-end;
            }
            
            .btn {
                padding: 0.5rem 1rem;
                font-size: 0.875rem;
                flex: none;
            }
            
            .code-editor {
                flex-direction: row;
                min-height: 500px;
            }
            
            .input-section {
                border-bottom: none;
                border-right: 1px solid var(--gray-light);
            }
            
            .input-section, .output-section {
                padding: 1.5rem;
            }
            
            .status-bar {
                flex-direction: row;
                justify-content: space-between;
                align-items: center;
                padding: 1rem 1.5rem;
            }
            
            h1 {
                font-size: 2rem;
                margin-bottom: 0.5rem;
            }
            
            .subtitle {
                font-size: 1rem;
            }
            
            .settings {
                gap: 1rem;
            }
        }
    </style>
    <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&family=Fira+Code&display=swap" rel="stylesheet">
</head>
<body>
    <div class="app-container">
        <header>
            <h1>代码格式化工具</h1>
            <p class="subtitle">高级简约的代码格式化解决方案</p>
        </header>
        
        <div class="main-content">
            <div class="toolbar">
                <div class="toolbar-row">
                    <div class="mode-selector">
                        <div class="mode-btn active" data-mode="auto">自动</div>
                        <div class="mode-btn" data-mode="sql">SQL</div>
                        <div class="mode-btn" data-mode="json">JSON</div>
                        <div class="mode-btn" data-mode="html">HTML</div>
                        <div class="mode-btn" data-mode="css">CSS</div>
                        <div class="mode-btn" data-mode="js">JS</div>
                    </div>
                    
                    <div class="settings">
                        <div class="indent-control">
                            <label for="indent-size">缩进:</label>
                            <input type="number" id="indent-size" min="1" max="8" value="4">
                            <span>空格</span>
                        </div>
                    </div>
                </div>
                
                <div class="action-buttons">
                    <button class="btn btn-primary" onclick="formatCode()">
                        <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                            <polyline points="4 17 10 11 4 5"></polyline>
                            <line x1="12" y1="19" x2="20" y2="19"></line>
                        </svg>
                        格式化
                    </button>
                    <button class="btn btn-secondary" onclick="minifyCode()">
                        <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                            <polyline points="5 12 12 5 19 12"></polyline>
                            <polyline points="12 19 12 5"></polyline>
                        </svg>
                        压缩
                    </button>
                </div>
            </div>
            
            <div class="code-editor">
                <div class="input-section">
                    <div class="section-header">
                        <div class="section-title">输入代码</div>
                        <button class="btn btn-secondary" onclick="clearCode()">
                            <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                                <polyline points="3 6 5 6 21 6"></polyline>
                                <path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"></path>
                            </svg>
                            清空
                        </button>
                    </div>
                    <textarea id="code-input" placeholder="在此粘贴您的代码..."></textarea>
                </div>
                
                <div class="output-section">
                    <div class="section-header">
                        <div class="section-title">格式化结果</div>
                        <button class="btn btn-success" onclick="copyToClipboard()">
                            <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                                <rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect>
                                <path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path>
                            </svg>
                            复制
                        </button>
                    </div>
                    <div id="code-output" class="output-content"></div>
                </div>
            </div>
            
            <div class="status-bar">
                <div class="status-info">
                    <span id="status-message" class="status-message">准备就绪</span>
                    <span id="detected-type" class="detected-type" style="display: none;"></span>
                </div>
                <button class="btn btn-secondary" onclick="autoDetect()">
                    <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                        <circle cx="12" cy="12" r="10"></circle>
                        <path d="M12 8v4l3 3"></path>
                    </svg>
                    重新检测
                </button>
            </div>
        </div>
    </div>

    <script>
        let currentMode = 'auto';
        let detectedType = null;
        let indentSize = 4;
        
        // 初始化模式选择
        document.querySelectorAll('.mode-btn').forEach(btn => {
            btn.addEventListener('click', () => {
                document.querySelectorAll('.mode-btn').forEach(b => b.classList.remove('active'));
                btn.classList.add('active');
                currentMode = btn.dataset.mode;
                updateStatus();
            });
        });
        
        // 监听缩进设置变化
        document.getElementById('indent-size').addEventListener('change', function() {
            indentSize = parseInt(this.value) || 4;
            if (indentSize < 1) indentSize = 1;
            if (indentSize > 8) indentSize = 8;
            this.value = indentSize;
        });
        
        // 更新状态显示
        function updateStatus() {
            const statusElement = document.getElementById('status-message');
            const typeElement = document.getElementById('detected-type');
            
            if (currentMode === 'auto') {
                statusElement.textContent = '自动模式';
                if (detectedType) {
                    typeElement.textContent = `检测到: ${detectedType.toUpperCase()}`;
                    typeElement.style.display = 'block';
                } else {
                    typeElement.style.display = 'none';
                }
            } else {
                statusElement.textContent = `手动模式: ${currentMode.toUpperCase()}`;
                typeElement.style.display = 'none';
            }
            
            statusElement.className = 'status-message';
        }
        
        // 复制到剪贴板
        function copyToClipboard() {
            const element = document.getElementById('code-output');
            const range = document.createRange();
            range.selectNode(element);
            window.getSelection().removeAllRanges();
            window.getSelection().addRange(range);
            
            try {
                const successful = document.execCommand('copy');
                if (successful) {
                    showStatus('已复制到剪贴板', 'success');
                } else {
                    showStatus('复制失败', 'error');
                }
            } catch (err) {
                showStatus('复制失败', 'error');
            }
            
            window.getSelection().removeAllRanges();
        }
        
        // 自动检测代码类型
        function autoDetectCode(input) {
            if (!input.trim()) {
                detectedType = null;
                return null;
            }
            
            // 尝试检测JSON
            try {
                JSON.parse(input);
                detectedType = 'json';
                return 'json';
            } catch (e) {}
            
            // 检测HTML
            if (/<[a-z][\s\S]*>/i.test(input)) {
                detectedType = 'html';
                return 'html';
            }
            
            // 检测SQL
            const sqlKeywords = ['SELECT', 'INSERT', 'UPDATE', 'DELETE', 'CREATE', 'ALTER', 'DROP', 'FROM', 'WHERE', 'JOIN'];
            const sqlScore = sqlKeywords.reduce((score, keyword) => {
                return score + (new RegExp(`\\b${keyword}\\b`, 'gi').test(input) ? 1 : 0);
            }, 0);
            
            if (sqlScore >= 2) {
                detectedType = 'sql';
                return 'sql';
            }
            
            // 检测CSS
            const cssPatterns = [/\{[^{}]*\}/, /:[^:;]*;/, /\.\w+\s*\{/, /#\w+\s*\{/];
            const cssScore = cssPatterns.reduce((score, pattern) => {
                return score + (pattern.test(input) ? 1 : 0);
            }, 0);
            
            if (cssScore >= 2) {
                detectedType = 'css';
                return 'css';
            }
            
            // 检测JavaScript
            const jsPatterns = [/function\s*\(/, /=\s*\{/, /\)\s*\{/, /;\s*$/, /\/\/|\/\*/];
            const jsScore = jsPatterns.reduce((score, pattern) => {
                return score + (pattern.test(input) ? 1 : 0);
            }, 0);
            
            if (jsScore >= 2) {
                detectedType = 'js';
                return 'js';
            }
            
            detectedType = null;
            return null;
        }
        
        // 自动检测按钮
        function autoDetect() {
            const input = document.getElementById('code-input').value;
            autoDetectCode(input);
            updateStatus();
            
            if (detectedType) {
                showStatus(`已检测为 ${detectedType.toUpperCase()}`, 'success');
            } else {
                showStatus('无法识别代码类型', 'error');
            }
        }
        
        // 生成缩进字符串
        function getIndent() {
            return ' '.repeat(indentSize);
        }
        
        // 格式化代码
        function formatCode() {
            const input = document.getElementById('code-input').value;
            if (!input.trim()) {
                showStatus('请输入代码', 'error');
                return;
            }
            
            const type = currentMode === 'auto' ? autoDetectCode(input) : currentMode;
            if (!type && currentMode === 'auto') {
                showStatus('无法识别代码格式,请手动选择', 'error');
                return;
            }
            
            try {
                let formatted;
                switch (type) {
                    case 'sql':
                        formatted = formatSql(input);
                        break;
                    case 'json':
                        formatted = formatJson(input);
                        break;
                    case 'html':
                        formatted = formatHtml(input);
                        break;
                    case 'css':
                        formatted = formatCss(input);
                        break;
                    case 'js':
                        formatted = formatJs(input);
                        break;
                    default:
                        showStatus('不支持的类型', 'error');
                        return;
                }
                
                document.getElementById('code-output').textContent = formatted;
                showStatus(`格式化成功 (${type.toUpperCase()})`, 'success');
            } catch (e) {
                document.getElementById('code-output').textContent = `格式化错误: ${e.message}`;
                showStatus('格式化失败', 'error');
            }
        }
        
        // 压缩代码
        function minifyCode() {
            const input = document.getElementById('code-input').value;
            if (!input.trim()) {
                showStatus('请输入代码', 'error');
                return;
            }
            
            const type = currentMode === 'auto' ? autoDetectCode(input) : currentMode;
            if (!type && currentMode === 'auto') {
                showStatus('无法识别代码格式,请手动选择', 'error');
                return;
            }
            
            try {
                let minified;
                switch (type) {
                    case 'sql':
                        minified = minifySql(input);
                        break;
                    case 'json':
                        minified = minifyJson(input);
                        break;
                    case 'html':
                        minified = minifyHtml(input);
                        break;
                    case 'css':
                        minified = minifyCss(input);
                        break;
                    case 'js':
                        minified = minifyJs(input);
                        break;
                    default:
                        showStatus('不支持的类型', 'error');
                        return;
                }
                
                document.getElementById('code-output').textContent = minified;
                showStatus(`压缩成功 (${type.toUpperCase()})`, 'success');
            } catch (e) {
                document.getElementById('code-output').textContent = `压缩错误: ${e.message}`;
                showStatus('压缩失败', 'error');
            }
        }
        
        // 清空代码
        function clearCode() {
            document.getElementById('code-input').value = '';
            document.getElementById('code-output').textContent = '';
            detectedType = null;
            updateStatus();
            showStatus('已清空', 'success');
        }
        
        // 显示状态信息
        function showStatus(message, type = 'success') {
            const statusElement = document.getElementById('status-message');
            statusElement.textContent = message;
            statusElement.className = `status-message ${type}`;
        }
        
        // ========== 格式化函数 ==========
        
        // SQL 格式化
        function formatSql(sql) {
            // 简单的SQL格式化逻辑
            let formatted = sql
                .replace(/\b(SELECT|FROM|WHERE|GROUP BY|HAVING|ORDER BY|INSERT INTO|UPDATE|DELETE FROM|CREATE TABLE|ALTER TABLE|DROP TABLE|JOIN|LEFT JOIN|RIGHT JOIN|INNER JOIN|OUTER JOIN|UNION|VALUES|SET)\b/gi, '\n$1')
                .replace(/,/g, ',\n' + getIndent())
                .replace(/\)\s*\(/g, ')\n(')
                .replace(/\b(AND|OR)\b/gi, '\n' + getIndent() + '$1');
            
            // 添加缩进
            let indent = 0;
            formatted = formatted.split('\n').map(line => {
                const trimmed = line.trim();
                if (trimmed.match(/^\)/) || trimmed.match(/^(END|ELSE|ELSIF|WHEN)\b/i)) {
                    indent--;
                }
                
                const indentedLine = getIndent().repeat(Math.max(0, indent)) + trimmed;
                
                if (trimmed.match(/\(|\b(BEGIN|CASE|IF|ELSE|ELSIF|WHEN)\b/i)) {
                    indent++;
                }
                
                return indentedLine;
            }).join('\n');
            
            return formatted.trim();
        }
        
        function minifySql(sql) {
            // 简单的SQL压缩逻辑
            return sql
                .replace(/\/\*.*?\*\//gs, '')  // 删除注释
                .replace(/--.*$/gm, '')      // 删除行注释
                .replace(/\s+/g, ' ')        // 多个空格变一个
                .replace(/\s*([,;()=+\-*\/])\s*/g, '$1') // 删除运算符周围的空格
                .trim();
        }
        
        // JSON 格式化
        function formatJson(json) {
            const obj = JSON.parse(json);
            return JSON.stringify(obj, null, indentSize);
        }
        
        function minifyJson(json) {
            const obj = JSON.parse(json);
            return JSON.stringify(obj);
        }
        
        // HTML 格式化
        function formatHtml(html) {
            // 添加换行
            let formatted = html
                .replace(/></g, '>\n<')
                .replace(/\n\n/g, '\n');
            
            // 添加缩进
            let indent = 0;
            let inTag = false;
            let inComment = false;
            
            formatted = formatted.split('\n').map(line => {
                const trimmed = line.trim();
                
                // 跳过空行
                if (!trimmed) return '';
                
                // 处理注释
                if (trimmed.startsWith('<!--')) {
                    inComment = true;
                }
                if (inComment && trimmed.endsWith('-->')) {
                    inComment = false;
                    return getIndent().repeat(indent) + trimmed;
                }
                if (inComment) {
                    return getIndent().repeat(indent) + trimmed;
                }
                
                // 处理结束标签
                if (trimmed.startsWith('</')) {
                    indent = Math.max(0, indent - 1);
                }
                
                const indentedLine = getIndent().repeat(indent) + trimmed;
                
                // 处理开始标签(非自闭合)
                if (trimmed.startsWith('<') && !trimmed.endsWith('/>') && 
                    !trimmed.match(/<(meta|link|img|br|hr|input|area|base|col|command|embed|keygen|param|source|track|wbr)[^>]*>/i)) {
                    if (!trimmed.match(/<\/[^>]+>$/)) {
                        indent++;
                    }
                }
                
                return indentedLine;
            }).filter(line => line !== '').join('\n');
            
            return formatted;
        }
        
        function minifyHtml(html) {
            return html
                .replace(/<!--.*?-->/gs, '')  // 删除注释
                .replace(/\s+/g, ' ')        // 多个空格变一个
                .replace(/>\s+</g, '><')     // 删除标签间的空格
                .trim();
        }
        
        // CSS 格式化
        function formatCss(css) {
            // 添加基本格式化
            let formatted = css
                .replace(/\{/g, ' {\n' + getIndent())
                .replace(/\}/g, '\n}\n\n')
                .replace(/;/g, ';\n' + getIndent())
                .replace(/,\s*/g, ',\n' + getIndent());
            
            // 处理媒体查询
            formatted = formatted.replace(/@media[^{]+\{/g, match => {
                return match.replace(/\s+/g, ' ') + ' {\n';
            });
            
            return formatted.trim();
        }
        
        function minifyCss(css) {
            return css
                .replace(/\/\*.*?\*\//gs, '')  // 删除注释
                .replace(/\s+/g, ' ')        // 多个空格变一个
                .replace(/\s*([{:;,])\s*/g, '$1') // 删除符号周围的空格
                .replace(/;}/g, '}')          // 删除最后一个分号
                .trim();
        }
        
        // JavaScript 格式化
        function formatJs(js) {
            // 使用简单缩进格式化
            let formatted = '';
            let indent = 0;
            let inString = false;
            let stringChar = '';
            let inComment = false;
            let inLineComment = false;
            
            for (let i = 0; i < js.length; i++) {
                const char = js[i];
                const nextChar = js[i+1];
                
                // 处理注释
                if (!inString && !inComment && char === '/' && nextChar === '*') {
                    inComment = true;
                    formatted += '/*';
                    i++;
                    continue;
                }
                
                if (inComment && char === '*' && nextChar === '/') {
                    inComment = false;
                    formatted += '*/';
                    i++;
                    continue;
                }
                
                if (!inString && !inComment && !inLineComment && char === '/' && nextChar === '/') {
                    inLineComment = true;
                    formatted += '//';
                    i++;
                    continue;
                }
                
                if (inLineComment && char === '\n') {
                    inLineComment = false;
                }
                
                if (inComment || inLineComment) {
                    formatted += char;
                    continue;
                }
                
                // 处理字符串
                if (inString) {
                    formatted += char;
                    if (char === stringChar && js[i-1] !== '\\') {
                        inString = false;
                    }
                    continue;
                } else if (char === '"' || char === "'" || char === '`') {
                    inString = true;
                    stringChar = char;
                    formatted += char;
                    continue;
                }
                
                // 处理大括号和缩进
                if (char === '{' || char === '[') {
                    formatted += char + '\n' + getIndent().repeat(++indent);
                } else if (char === '}' || char === ']') {
                    formatted += '\n' + getIndent().repeat(--indent) + char;
                } else if (char === ';') {
                    formatted += ';\n' + getIndent().repeat(indent);
                } else if (char === ',') {
                    formatted += ',\n' + getIndent().repeat(indent);
                } else if (char === ':') {
                    formatted += ': ';
                } else {
                    formatted += char;
                }
            }
            
            return formatted.trim();
        }
        
        function minifyJs(js) {
            // 简单的JS压缩逻辑
            return js
                .replace(/\/\/.*$/gm, '')  // 删除单行注释
                .replace(/\/\*.*?\*\//gs, '')  // 删除多行注释
                .replace(/\s+/g, ' ')      // 多个空格变一个
                .replace(/\s*([=+\-*\/%&|^~!<>?:;,{}()[\]])\s*/g, '$1') // 删除运算符周围的空格
                .replace(/;}/g, '}')       // 删除最后一个分号
                .trim();
        }
        
        // 初始化
        updateStatus();
        
        // 监听输入变化自动检测
        document.getElementById('code-input').addEventListener('input', function() {
            if (currentMode === 'auto') {
                autoDetectCode(this.value);
                updateStatus();
            }
        });
    </script>
</body>
</html>
        
预览
控制台