去除代码注释

智能高清晰度去除 JS、TS、Python、C/C++、Java、HTML、CSS、SQL 等数十种编程语言的单行与多行注释,自动清理空白行并保护字符串内容。

编程语言:
载入示例:
输入源代码 (包含注释)
无注释代码 (清理完成) 体积已缩减 0%
原始: 0 行 (0 B)
清理后: 0 行 (0 B)
代码行数缩减: 0%

使用说明

  1. 1. 粘贴源代码或载入示例代码,选择目标编程语言
  2. 2. 可选配置是否保留 JSDoc/版权头、是否删除空行与多余空格
  3. 3. 实时生成无注释干净代码,支持一键复制与文件下载
`, css: `/*! * Reset CSS Stylesheet */ /* 全局布局配置 */ :root { --primary-color: #0a84ff; /* 主主题色 */ } /* 页面基本基调 */ body { font-family: sans-serif; // SCSS 单行注释 background-color: #f8fafc; /* 多行样式重置 */ color: var(--primary-color); }`, cpp: `/* * C++ Standard Example * Author: Antigravity */ #include // 主程序入口 int main() { // 输出 Hello World std::cout << "Hello World! // string test" << std::endl; /* 尾部多行 */ /* 多行块清理测试 */ return 0; }` }; // 示例加载 sampleJsBtn.addEventListener('click', () => loadSample('js')); samplePyBtn.addEventListener('click', () => loadSample('python')); sampleHtmlBtn.addEventListener('click', () => loadSample('html')); sampleCssBtn.addEventListener('click', () => loadSample('css')); sampleCppBtn.addEventListener('click', () => loadSample('cpp')); function loadSample(lang) { langSelect.value = lang; sourceInput.value = SAMPLES[lang] || ''; processCode(); } // 监听输入与设置变更 sourceInput.addEventListener('input', processCode); langSelect.addEventListener('change', processCode); keepLicenseCheck.addEventListener('change', processCode); removeBlankCheck.addEventListener('change', processCode); trimSpacesCheck.addEventListener('change', processCode); clearBtn.addEventListener('click', () => { sourceInput.value = ''; cleanOutput.value = ''; updateStats('', ''); }); cleanBtn.addEventListener('click', () => { processCode(); if (window.$tool && $tool.toast) $tool.toast('代码注释清理完成'); }); copyBtn.addEventListener('click', () => { const text = cleanOutput.value; if (!text) return; if (window.$tool && $tool.copy) { $tool.copy(text); } else { navigator.clipboard.writeText(text); alert('干净代码已复制'); } }); downloadBtn.addEventListener('click', () => { const text = cleanOutput.value; if (!text) return; const extMap = { js: 'js', python: 'py', html: 'html', css: 'css', cpp: 'cpp', sql: 'sql', shell: 'sh' }; const ext = extMap[langSelect.value] || 'txt'; const filename = `clean_code_${Date.now()}.${ext}`; if (window.$tool && $tool.download) { $tool.download(text, filename); } else { const blob = new Blob([text], { type: 'text/plain;charset=utf-8' }); const a = document.createElement('a'); a.href = URL.createObjectURL(blob); a.download = filename; a.click(); } }); // 2. 核心语法清理与状态机解析引擎 function processCode() { const code = sourceInput.value; if (!code) { cleanOutput.value = ''; updateStats('', ''); return; } const lang = langSelect.value; const keepLicense = keepLicenseCheck.checked; const removeBlank = removeBlankCheck.checked; const trimSpaces = trimSpacesCheck.checked; let cleaned = ''; if (lang === 'python') { cleaned = stripPythonComments(code, keepLicense); } else if (lang === 'html') { cleaned = stripHtmlComments(code, keepLicense); } else if (lang === 'css') { cleaned = stripCssComments(code, keepLicense); } else if (lang === 'sql') { cleaned = stripSqlComments(code, keepLicense); } else if (lang === 'shell') { cleaned = stripShellComments(code, keepLicense); } else { // js, ts, cpp, c, java, go, rust, csharp cleaned = stripCStyleComments(code, keepLicense); } // 后处理:移除空白行与擦除行尾空格 let lines = cleaned.split('\n'); if (trimSpaces) { lines = lines.map(line => line.trimEnd()); } if (removeBlank) { lines = lines.filter(line => line.trim().length > 0); } cleaned = lines.join('\n'); cleanOutput.value = cleaned; updateStats(code, cleaned); } // C 风格语言 (JS/TS/C/C++/Java/Go/Rust/C#) function stripCStyleComments(code, keepLicense) { let result = ''; let i = 0; const len = code.length; let inString = false; let stringChar = ''; while (i < len) { const char = code[i]; const next = code[i + 1]; // 1. 处理字符串字面量 ('...', "...", `...`) if (inString) { result += char; if (char === '\\') { // 转义字符 result += next || ''; i += 2; continue; } if (char === stringChar) { inString = false; } i++; continue; } if (char === "'" || char === '"' || char === '`') { inString = true; stringChar = char; result += char; i++; continue; } // 2. 处理单行注释 // ... if (char === '/' && next === '/') { let j = i; while (j < len && code[j] !== '\n') { j++; } i = j; continue; } // 3. 处理多行注释 /* ... */ if (char === '/' && next === '*') { let j = i + 2; let isLicense = false; if (keepLicense && (code[i + 2] === '!' || code[i + 2] === '*')) { isLicense = true; } while (j < len && !(code[j] === '*' && code[j + 1] === '/')) { j++; } j += 2; // 跳过 */ if (isLicense) { result += code.slice(i, j); } i = j; continue; } result += char; i++; } return result; } // Python 注释与 Docstring 清理 function stripPythonComments(code, keepLicense) { let result = ''; let i = 0; const len = code.length; let inString = false; let stringChar = ''; let isTriple = false; while (i < len) { const char = code[i]; const next1 = code[i + 1]; const next2 = code[i + 2]; // 处理多行字符串 / Docstring (""" ... """ 或 ''' ... ''') if (!inString && (char === '"' || char === "'")) { if (next1 === char && next2 === char) { // 遇到三引号 let j = i + 3; while (j < len && !(code[j] === char && code[j + 1] === char && code[j + 2] === char)) { j++; } j += 3; if (keepLicense && i === 0) { result += code.slice(i, j); } i = j; continue; } } // 字符串字面量 if (inString) { result += char; if (char === '\\') { result += next1 || ''; i += 2; continue; } if (char === stringChar) { inString = false; } i++; continue; } if (char === '"' || char === "'") { inString = true; stringChar = char; result += char; i++; continue; } // 单行 # 注释 if (char === '#') { let j = i; while (j < len && code[j] !== '\n') { j++; } i = j; continue; } result += char; i++; } return result; } // HTML / XML 注释清理 function stripHtmlComments(code, keepLicense) { // 替换 return code.replace(//g, (match) => { if (keepLicense && (match.includes('!') || match.includes('license'))) { return match; } return ''; }); } // CSS 注释清理 function stripCssComments(code, keepLicense) { return code.replace(/\/\*[\s\S]*?\*\//g, (match) => { if (keepLicense && (match.startsWith('/*!') || match.startsWith('/**'))) { return match; } return ''; }).replace(/\/\/.*/g, ''); // 支持 SCSS 单行 // } // SQL 注释清理 function stripSqlComments(code, keepLicense) { return code.replace(/--.*/g, '').replace(/\/\*[\s\S]*?\*\//g, ''); } // Shell 注释清理 function stripShellComments(code, keepLicense) { return code.replace(/^\s*#.*/gm, ''); } // 3. 数据统计更新 function updateStats(oldCode, newCode) { const oldLines = oldCode ? oldCode.split('\n').length : 0; const newLines = newCode ? newCode.split('\n').length : 0; const oldBytes = new Blob([oldCode]).size; const newBytes = new Blob([newCode]).size; statOldLines.textContent = oldLines; statNewLines.textContent = newLines; statOldSize.textContent = formatBytes(oldBytes); statNewSize.textContent = formatBytes(newBytes); const lineDiffPercent = oldLines > 0 ? Math.round(((oldLines - newLines) / oldLines) * 100) : 0; const byteDiffPercent = oldBytes > 0 ? Math.round(((oldBytes - newBytes) / oldBytes) * 100) : 0; statLineDiff.textContent = `${Math.max(0, lineDiffPercent)}% (体积缩小 ${Math.max(0, byteDiffPercent)}%)`; reductionBadge.textContent = `行数缩减 ${Math.max(0, lineDiffPercent)}%`; } function formatBytes(bytes) { if (bytes === 0) return '0 B'; const k = 1024; const sizes = ['B', 'KB', 'MB']; const i = Math.floor(Math.log(bytes) / Math.log(k)); return (bytes / Math.pow(k, i)).toFixed(1) + ' ' + sizes[i]; } // 默认装载 JS 示例 loadSample('js'); })();