Buckets:

Sinningai/asitheboy / chimera-saas.html
boylnwzav1's picture
download
raw
37 kB
<!DOCTYPE html>
<html lang="th">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; script-src 'unsafe-inline'; style-src 'unsafe-inline'; img-src 'self' data: blob:; font-src 'self'; connect-src 'none'; media-src 'none'; object-src 'none'; frame-src 'none'; base-uri 'none'; form-action 'none';">
<meta http-equiv="X-Content-Security-Policy" content="default-src 'none'; script-src 'unsafe-inline'; style-src 'unsafe-inline'; img-src 'self' data: blob:; font-src 'self'; connect-src 'none'; media-src 'none'; object-src 'none'; frame-src 'none'; base-uri 'none'; form-action 'none';">
<meta http-equiv="Referrer-Policy" content="no-referrer">
<title>Chimera Symbiote — AI Code Analyzer</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { font-family: 'Segoe UI', system-ui, sans-serif; background: #0a0a1a; color: #e0e0e0; min-height: 100vh; }
.header { background: linear-gradient(135deg, #0d0d2b, #1a1a3e); padding: 16px 30px; border-bottom: 1px solid #1e1e3a; display: flex; justify-content: space-between; align-items: center; }
.logo { font-size: 22px; font-weight: bold; background: linear-gradient(135deg, #00d4ff, #ff00ff); -webkit-background-clip: text; -webkit-text-fill-color: transparent; }
.header-right { display: flex; align-items: center; gap: 16px; }
.pricing-btn { background: linear-gradient(135deg, #ff00ff, #8855ff); border: none; color: white; padding: 8px 16px; border-radius: 8px; cursor: pointer; font-size: 13px; font-weight: 600; }
.pricing-btn:hover { opacity: 0.9; }
.container { max-width: 1400px; margin: 0 auto; padding: 24px; }
.hero { text-align: center; padding: 40px 20px; }
.hero h1 { font-size: 36px; margin-bottom: 12px; background: linear-gradient(135deg, #00d4ff, #ff00ff); -webkit-background-clip: text; -webkit-text-fill-color: transparent; }
.hero p { color: #8888aa; font-size: 16px; max-width: 600px; margin: 0 auto; }
.main-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; margin-top: 24px; }
@media (max-width: 900px) { .main-grid { grid-template-columns: 1fr; } }
.card { background: #12122a; border: 1px solid #1e1e3a; border-radius: 12px; padding: 20px; }
.card-title { font-size: 14px; color: #8888aa; margin-bottom: 12px; display: flex; align-items: center; gap: 8px; font-weight: 600; }
textarea { width: 100%; height: 350px; background: #0a0a1a; border: 1px solid #1e1e3a; border-radius: 8px; color: #e0e0e0; font-family: 'Consolas', 'Fira Code', monospace; font-size: 13px; padding: 16px; resize: vertical; line-height: 1.6; }
textarea:focus { outline: none; border-color: #00d4ff; }
.controls { display: flex; gap: 10px; margin-top: 12px; flex-wrap: wrap; }
.btn { padding: 10px 20px; border: none; border-radius: 8px; cursor: pointer; font-size: 14px; font-weight: 600; transition: all 0.2s; }
.btn-primary { background: linear-gradient(135deg, #00d4ff, #0088ff); color: white; }
.btn-primary:hover { transform: translateY(-1px); box-shadow: 0 4px 12px #00d4ff44; }
.btn-secondary { background: #1e1e3a; color: #e0e0e0; }
.btn-secondary:hover { background: #2a2a4a; }
.btn-success { background: linear-gradient(135deg, #00ff88, #00cc66); color: #0a0a1a; }
select { background: #0a0a1a; border: 1px solid #1e1e3a; color: #e0e0e0; padding: 10px 14px; border-radius: 8px; font-size: 14px; }
.score-display { text-align: center; padding: 20px; }
.score-circle { width: 120px; height: 120px; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 36px; font-weight: bold; margin: 0 auto 12px; }
.score-high { background: #00ff8822; color: #00ff88; border: 3px solid #00ff88; }
.score-mid { background: #ffcc0022; color: #ffcc00; border: 3px solid #ffcc00; }
.score-low { background: #ff446622; color: #ff4466; border: 3px solid #ff4466; }
.issues-list { margin-top: 16px; }
.issue-item { background: #0a0a1a; border-radius: 8px; padding: 12px; margin-bottom: 8px; border-left: 3px solid; }
.issue-critical { border-color: #ff4466; }
.issue-warning { border-color: #ffcc00; }
.issue-info { border-color: #00d4ff; }
.issue-suggestion { border-color: #00ff88; }
.issue-type { font-size: 11px; font-weight: 600; margin-bottom: 4px; }
.issue-critical .issue-type { color: #ff4466; }
.issue-warning .issue-type { color: #ffcc00; }
.issue-info .issue-type { color: #00d4ff; }
.issue-suggestion .issue-type { color: #00ff88; }
.issue-msg { font-size: 13px; color: #ccc; }
.issue-line { font-size: 11px; color: #8888aa; margin-top: 4px; }
.issue-fix { font-size: 12px; color: #00ff88; margin-top: 6px; font-family: 'Consolas', monospace; background: #00ff8811; padding: 6px 8px; border-radius: 4px; }
.stats-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; margin-top: 16px; }
.stat-item { background: #0a0a1a; border-radius: 8px; padding: 12px; text-align: center; }
.stat-value { font-size: 20px; font-weight: bold; }
.stat-label { font-size: 11px; color: #8888aa; margin-top: 4px; }
.sample-btns { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 12px; }
.sample-btn { background: #1e1e3a; border: 1px solid #2a2a4a; color: #8888aa; padding: 6px 12px; border-radius: 6px; cursor: pointer; font-size: 12px; }
.sample-btn:hover { background: #2a2a4a; color: #e0e0e0; }
/* Pricing Modal */
.modal-overlay { display: none; position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0,0,0,0.7); z-index: 1000; align-items: center; justify-content: center; }
.modal-overlay.active { display: flex; }
.modal { background: #12122a; border: 1px solid #1e1e3a; border-radius: 16px; padding: 30px; max-width: 900px; width: 90%; max-height: 90vh; overflow-y: auto; }
.modal h2 { font-size: 24px; margin-bottom: 20px; text-align: center; }
.modal-close { float: right; background: none; border: none; color: #8888aa; font-size: 24px; cursor: pointer; }
.pricing-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; }
@media (max-width: 700px) { .pricing-grid { grid-template-columns: 1fr; } }
.pricing-card { background: #0a0a1a; border: 1px solid #1e1e3a; border-radius: 12px; padding: 24px; text-align: center; position: relative; }
.pricing-card.featured { border-color: #00d4ff; }
.pricing-card.featured::before { content: 'POPULAR'; position: absolute; top: -10px; left: 50%; transform: translateX(-50%); background: #00d4ff; color: #0a0a1a; padding: 2px 12px; border-radius: 10px; font-size: 11px; font-weight: 700; }
.pricing-name { font-size: 18px; font-weight: 600; margin-bottom: 8px; }
.pricing-price { font-size: 32px; font-weight: bold; margin-bottom: 4px; }
.pricing-period { font-size: 12px; color: #8888aa; margin-bottom: 16px; }
.pricing-features { list-style: none; text-align: left; margin-bottom: 20px; }
.pricing-features li { padding: 6px 0; font-size: 13px; color: #ccc; border-bottom: 1px solid #1e1e3a; }
.pricing-features li::before { content: '✓ '; color: #00ff88; }
.pricing-cta { width: 100%; padding: 12px; border: none; border-radius: 8px; font-size: 14px; font-weight: 600; cursor: pointer; }
.pricing-card.featured .pricing-cta { background: linear-gradient(135deg, #00d4ff, #0088ff); color: white; }
.pricing-card:not(.featured) .pricing-cta { background: #1e1e3a; color: #e0e0e0; }
.footer { text-align: center; padding: 20px; color: #555577; font-size: 11px; border-top: 1px solid #1e1e3a; margin-top: 40px; }
.hidden { display: none; }
.loading { text-align: center; padding: 40px; color: #8888aa; }
.loading::after { content: ''; display: inline-block; width: 20px; height: 20px; border: 2px solid #00d4ff; border-top-color: transparent; border-radius: 50%; animation: spin 0.8s linear infinite; margin-left: 8px; vertical-align: middle; }
@keyframes spin { to { transform: rotate(360deg); } }
</style>
</head>
<body>
<div class="header">
<div class="logo">🧬 Chimera Symbiote</div>
<div class="header-right">
<span style="font-size:12px;color:#8888aa">v2.0 — Free Analyzer</span>
<button class="pricing-btn" onclick="showPricing()">💰 Upgrade to Pro</button>
</div>
</div>
<div class="container">
<div class="hero">
<h1>AI Code Analyzer</h1>
<p>วางโค้ดของคุณลงไป — รับคะแนน, พบปัญหา, และคำแนะนำในการปรับปรุงทันที</p>
</div>
<div class="main-grid">
<!-- Input Panel -->
<div class="card">
<div class="card-title">📝 ใส่โค้ดที่ต้องการวิเคราะห์</div>
<select id="langSelect" style="margin-bottom:10px">
<option value="python">Python</option>
<option value="javascript">JavaScript</option>
<option value="html">HTML</option>
</select>
<textarea id="codeInput" placeholder="วางโค้ดที่นี่... หรือเลือกตัวอย่างด้านล่าง"># ตัวอย่างโค้ด Python
def calculate_total(items):
total = 0
for i in range(len(items)):
total = total + items[i]
return total
def process_data(data):
result = []
for d in data:
if d > 0:
result.append(d * 2)
return result
x = calculate_total([1,2,3,4,5])
print(x)</textarea>
<div class="sample-btns">
<span style="font-size:12px;color:#8888aa;line-height:28px">ตัวอย่าง:</span>
<button class="sample-btn" onclick="loadSample('bad_python')">โค้ดแย่ (Python)</button>
<button class="sample-btn" onclick="loadSample('good_python')">โค้ดดี (Python)</button>
<button class="sample-btn" onclick="loadSample('bad_js')">โค้ดแย่ (JS)</button>
<button class="sample-btn" onclick="loadSample('bad_html')">โค้ดแย่ (HTML)</button>
</div>
<div class="controls">
<button class="btn btn-primary" onclick="analyzeCode()">🔍 วิเคราะห์โค้ด</button>
<button class="btn btn-secondary" onclick="clearCode()">🗑️ ล้าง</button>
<button class="btn btn-success hidden" id="exportBtn" onclick="exportReport()">📄 Export Report</button>
</div>
</div>
<!-- Results Panel -->
<div class="card" id="resultsCard">
<div class="card-title">📊 ผลการวิเคราะห์</div>
<div id="resultsArea">
<div style="text-align:center;padding:60px 20px;color:#8888aa">
<div style="font-size:48px;margin-bottom:12px">🧬</div>
<p>วางโค้ดแล้วกด "วิเคราะห์โค้ด" เพื่อดูผล</p>
</div>
</div>
</div>
</div>
</div>
<!-- Pricing Modal -->
<div class="modal-overlay" id="pricingModal">
<div class="modal">
<button class="modal-close" onclick="closePricing()">&times;</button>
<h2>💰 เลือกแพ็กเกจที่เหมาะกับคุณ</h2>
<div class="pricing-grid">
<div class="pricing-card">
<div class="pricing-name">Starter</div>
<div class="pricing-price" style="color:#00d4ff">3,415฿</div>
<div class="pricing-period">/เดือน</div>
<ul class="pricing-features">
<li>วิเคราะห์ 10 ไฟล์/เดือน</li>
<li>รายงานพื้นฐาน</li>
<li>รองรับ Python, JS</li>
<li>Email support</li>
</ul>
<button class="pricing-cta" onclick="contactSales('Starter')">เริ่มต้นใช้งาน</button>
</div>
<div class="pricing-card featured">
<div class="pricing-name">Professional</div>
<div class="pricing-price" style="color:#ff00ff">17,215฿</div>
<div class="pricing-period">/เดือน</div>
<ul class="pricing-features">
<li>ไม่จำกัดไฟล์</li>
<li>CI/CD Integration</li>
<li>ทุกภาษา + Custom Rules</li>
<li>Priority support</li>
<li>Team dashboard</li>
</ul>
<button class="pricing-cta" onclick="contactSales('Professional')">เริ่มต้นใช้งาน</button>
</div>
<div class="pricing-card">
<div class="pricing-name">Enterprise</div>
<div class="pricing-price" style="color:#00ff88">86,215฿</div>
<div class="pricing-period">/เดือน</div>
<ul class="pricing-features">
<li>ทุกอย่างใน Professional</li>
<li>Custom AI Rules</li>
<li>On-premise deployment</li>
<li>Dedicated support</li>
<li>SLA 99.9%</li>
</ul>
<button class="pricing-cta" onclick="contactSales('Enterprise')">ติดต่อฝ่ายขาย</button>
</div>
</div>
</div>
</div>
<div class="footer">
🧬 Chimera Symbiote v2.0 — Powered by Ω NEXUS — 100% Offline
</div>
<script>
// ============================================================
// 🔒 OFFLINE MODE — BLOCK ALL EXTERNAL CONNECTIONS
// ============================================================
(function() {
'use strict';
// Block fetch()
if (typeof fetch !== 'undefined') {
window.fetch = function() {
console.warn('[Chimera] 🔒 Blocked external fetch() — 100% Offline Mode');
return Promise.reject(new Error('External connections blocked — Offline Mode'));
};
}
// Block XMLHttpRequest
const OriginalXHR = window.XMLHttpRequest;
window.XMLHttpRequest = function() {
const xhr = new OriginalXHR();
const originalOpen = xhr.open;
xhr.open = function(method, url) {
if (typeof url === 'string' && (url.startsWith('http://') || url.startsWith('https://') || url.startsWith('//'))) {
console.warn('[Chimera] 🔒 Blocked XMLHttpRequest to:', url);
throw new Error('External connections blocked — Offline Mode');
}
return originalOpen.apply(this, arguments);
};
return xhr;
};
// Block navigator.sendBeacon
if (navigator.sendBeacon) {
navigator.sendBeacon = function() {
console.warn('[Chimera] 🔒 Blocked sendBeacon() — 100% Offline Mode');
return false;
};
}
// Block WebSocket
if (typeof WebSocket !== 'undefined') {
window.WebSocket = function() {
console.warn('[Chimera] 🔒 Blocked WebSocket — 100% Offline Mode');
throw new Error('External connections blocked — Offline Mode');
};
}
// Block window.open for external URLs
const originalOpen = window.open;
window.open = function(url) {
if (url && (url.startsWith('http://') || url.startsWith('https://') || url.startsWith('//'))) {
console.warn('[Chimera] 🔒 Blocked window.open() to:', url);
alert('🔒 Offline Mode — ไม่สามารถเปิดลิงก์ภายนอกได้');
return null;
}
return originalOpen.apply(this, arguments);
};
// Block external link clicks
document.addEventListener('click', function(e) {
const link = e.target.closest('a');
if (link && link.href && (link.href.startsWith('http://') || link.href.startsWith('https://'))) {
e.preventDefault();
console.warn('[Chimera] 🔒 Blocked external link:', link.href);
alert('🔒 Offline Mode — ไม่สามารถเปิดลิงก์ภายนอกได้');
}
}, true);
// Block form submissions to external URLs
document.addEventListener('submit', function(e) {
const form = e.target;
if (form.action && (form.action.startsWith('http://') || form.action.startsWith('https://'))) {
e.preventDefault();
console.warn('[Chimera] 🔒 Blocked external form submission');
}
}, true);
console.log('[Chimera] 🔒 Offline Mode Active — All external connections blocked');
})();
// ============================================================
// CHIMERA SYMBIOTE — Real Code Analyzer (Browser-based)
// ============================================================
const SAMPLES = {
bad_python: `# โค้ดที่ไม่มีคุณภาพ
def foo(x,y,z):
if x==1:
if y==2:
if z==3:
return True
else:
return False
else:
return False
else:
return False
data = []
for i in range(100):
data.append(i)
data.append(i*2)
data.append(i*3)
result = []
for d in data:
if d > 50:
result.append(d)
x = result
print(x)`,
good_python: `"""Module for data processing."""
from typing import List, Optional
def is_valid_coordinate(x: int, y: int, z: int) -> bool:
"""Check if coordinates match target (1, 2, 3)."""
return x == 1 and y == 2 and z == 3
def generate_multiples(count: int = 100) -> List[int]:
"""Generate multiples of 1, 2, 3 for each number."""
return [
val
for i in range(count)
for val in (i, i * 2, i * 3)
]
def filter_above(data: List[int], threshold: int = 50) -> List[int]:
"""Filter values above threshold."""
return [d for d in data if d > threshold]
def main() -> None:
"""Main entry point."""
data = generate_multiples()
result = filter_above(data)
print(result)
if __name__ == "__main__":
main()`,
bad_js: `var x = 10
var y = 20
var z = x + y
function doStuff(arr) {
var result = []
for(var i = 0; i < arr.length; i++) {
if(arr[i] > 0) {
result.push(arr[i] * 2)
}
}
return result
}
var data = [1,2,3,-1,0,5,-3,8]
var output = doStuff(data)
console.log(output)
var obj = {}
obj.name = "test"
obj.value = 42
obj.data = [1,2,3]`,
bad_html: `<!DOCTYPE html>
<html>
<head>
<title>Bad Page</title>
</head>
<body>
<div>
<div>
<div>
<p>Hello World
<img src="test.jpg">
<a href="#">Click here</a>
</div>
</div>
</div>
<font size="5">Old font tag</font>
<center>Centered text</center>
<br>
<br>
<br>
<table>
<tr><td>Cell 1<td>Cell 2<td>Cell 3</tr>
</table>
</body>
</html>`
};
function loadSample(name) {
const lang = name.includes('js') ? 'javascript' : name.includes('html') ? 'html' : 'python';
document.getElementById('langSelect').value = lang;
document.getElementById('codeInput').value = SAMPLES[name];
}
function clearCode() {
document.getElementById('codeInput').value = '';
document.getElementById('resultsArea').innerHTML = `
<div style="text-align:center;padding:60px 20px;color:#8888aa">
<div style="font-size:48px;margin-bottom:12px">🧬</div>
<p>วางโค้ดแล้วกด "วิเคราะห์โค้ด" เพื่อดูผล</p>
</div>`;
document.getElementById('exportBtn').classList.add('hidden');
}
// ============================================================
// ANALYSIS ENGINES
// ============================================================
function analyzePython(code) {
const lines = code.split('\n');
const issues = [];
let score = 100;
let metrics = { lines: lines.length, functions: 0, classes: 0, imports: 0, comments: 0, blankLines: 0 };
// Check for docstring/module doc
const hasModuleDoc = code.trim().startsWith('"""') || code.trim().startsWith("'''");
if (!hasModuleDoc && lines.length > 5) {
issues.push({ type: 'warning', msg: 'ไม่มี module docstring', line: 1, fix: 'เพิ่ม """Module description.""" ที่ต้นไฟล์' });
score -= 5;
}
for (let i = 0; i < lines.length; i++) {
const line = lines[i];
const trimmed = line.trim();
if (!trimmed) { metrics.blankLines++; continue; }
if (trimmed.startsWith('#')) { metrics.comments++; continue; }
if (trimmed.startsWith('import ') || trimmed.startsWith('from ')) { metrics.imports++; }
if (trimmed.startsWith('def ')) { metrics.functions++; }
if (trimmed.startsWith('class ')) { metrics.classes++; }
// Deep nesting
const indent = line.search(/\S/);
if (indent >= 12) {
issues.push({ type: 'critical', msg: 'โค้ดซ้อนลึกเกินไป (nested > 3 levels)', line: i + 1, fix: 'แยกเป็น function ย่อย หรือใช้ early return' });
score -= 10;
} else if (indent >= 8) {
issues.push({ type: 'warning', msg: 'โค้ดซ้อนลึก (nested 2-3 levels)', line: i + 1, fix: 'พิจารณาแยก function' });
score -= 3;
}
// Bare except
if (trimmed.includes('except:')) {
issues.push({ type: 'critical', msg: 'ใช้ bare except — ควรระบุ exception type', line: i + 1, fix: 'เปลี่ยนเป็น except Exception:' });
score -= 8;
}
// Global variables
if (trimmed.startsWith('global ')) {
issues.push({ type: 'warning', msg: 'ใช้ global variable', line: i + 1, fix: 'ใช้ class attribute หรือ pass เป็น parameter' });
score -= 5;
}
// Magic numbers
const magicMatch = trimmed.match(/[^a-zA-Z_"](\d{2,})(?![a-zA-Z_"\d])/);
if (magicMatch && !trimmed.startsWith('#') && !trimmed.startsWith('def') && !trimmed.startsWith('class')) {
// Check if it's in a range() or common pattern
if (!trimmed.includes('range(') && !trimmed.includes('__')) {
issues.push({ type: 'info', msg: `พบ magic number: ${magicMatch[1]}`, line: i + 1, fix: `กำหนดเป็น constant เช่น MAX_VALUE = ${magicMatch[1]}` });
score -= 2;
}
}
// Long lines
if (line.length > 120) {
issues.push({ type: 'warning', msg: `บรรทัดยาวเกินไป (${line.length} ตัวอักษร, ควร < 120)`, line: i + 1, fix: 'แบ่งบรรทัดหรือใช้ line continuation' });
score -= 2;
}
// print() in non-main code
if (trimmed.startsWith('print(') && !trimmed.startsWith('#')) {
// Check if inside if __name__ == "__main__"
const inMainBlock = code.includes('if __name__') && i > code.indexOf('if __name__');
if (!inMainBlock) {
issues.push({ type: 'info', msg: 'ใช้ print() — ควรใช้ logging แทน', line: i + 1, fix: 'import logging; logging.info(...)' });
score -= 1;
}
}
// Unused variable pattern (assign then never used)
const varAssign = trimmed.match(/^([a-zA-Z_]\w*)\s*=/);
if (varAssign) {
const varName = varAssign[1];
if (varName !== '_' && !['self', 'cls', 'result', 'data', 'output', 'response', 'ret'].includes(varName)) {
const restOfCode = lines.slice(i + 1).join('\n');
const usageCount = (restOfCode.match(new RegExp(`\\b${varName}\\b`, 'g')) || []).length;
if (usageCount === 0) {
issues.push({ type: 'warning', msg: `ตัวแปร '${varName}' ถูกกำหนดแต่ไม่ได้ใช้`, line: i + 1, fix: `ลบบรรทัดนี้ หรือใช้ ${varName} ในโค้ดต่อไป` });
score -= 3;
}
}
}
// String concatenation in loop
if (trimmed.includes('+=') && (trimmed.includes("'") || trimmed.includes('"'))) {
issues.push({ type: 'warning', msg: 'String concatenation — ควรใช้ list + join', line: i + 1, fix: 'ใช้ list.append() แล้ว "".join() แทน' });
score -= 3;
}
// Type hints missing in function
if (trimmed.startsWith('def ') && !trimmed.includes('->') && !trimmed.includes(': ')) {
// Check next few lines for type hints in params
const funcLine = trimmed;
if (!funcLine.includes(': int') && !funcLine.includes(': str') && !funcLine.includes(': float') && !funcLine.includes(': bool') && !funcLine.includes(': List') && !funcLine.includes(': Dict')) {
issues.push({ type: 'info', msg: 'Function ไม่มี type hints', line: i + 1, fix: 'def func(param: type) -> return_type:' });
score -= 2;
}
}
}
// Check for if __name__ == "__main__"
if (metrics.functions > 0 && !code.includes('if __name__')) {
issues.push({ type: 'info', msg: 'ไม่มี if __name__ == "__main__" block', line: 1, fix: 'เพิ่ม if __name__ == "__main__": main() ที่ท้ายไฟล์' });
score -= 3;
}
// Check for list comprehension opportunity
const hasLoopAppend = /for\s+\w+\s+in\s+.+:\s*\n\s*\w+\.append\(/.test(code);
if (hasLoopAppend) {
issues.push({ type: 'suggestion', msg: 'ใช้ for + append — ควรใช้ list comprehension', line: 0, fix: '[expr for item in iterable if condition]' });
score -= 3;
}
score = Math.max(0, Math.min(100, score));
return { score, issues, metrics, language: 'Python' };
}
function analyzeJavaScript(code) {
const lines = code.split('\n');
const issues = [];
let score = 100;
let metrics = { lines: lines.length, functions: 0, classes: 0, imports: 0, comments: 0, blankLines: 0 };
for (let i = 0; i < lines.length; i++) {
const line = lines[i];
const trimmed = line.trim();
if (!trimmed) { metrics.blankLines++; continue; }
if (trimmed.startsWith('//') || trimmed.startsWith('/*')) { metrics.comments++; continue; }
if (trimmed.startsWith('import ') || trimmed.startsWith('require(')) { metrics.imports++; }
if (trimmed.includes('function ') || trimmed.includes('=>')) { metrics.functions++; }
if (trimmed.includes('class ')) { metrics.classes++; }
// var instead of let/const
if (trimmed.startsWith('var ')) {
issues.push({ type: 'warning', msg: 'ใช้ var — ควรใช้ let หรือ const', line: i + 1, fix: 'เปลี่ยน var เป็น const (หรือ let ถ้ามีการเปลี่ยนค่า)' });
score -= 5;
}
// Deep nesting
const indent = line.search(/\S/);
if (indent >= 12) {
issues.push({ type: 'critical', msg: 'โค้ดซ้อนลึกเกินไป', line: i + 1, fix: 'แยก function หรือใช้ early return' });
score -= 10;
}
// console.log
if (trimmed.includes('console.log(')) {
issues.push({ type: 'info', msg: 'พบ console.log — ควรลบก่อน production', line: i + 1, fix: 'ใช้ logging library หรือลบออก' });
score -= 2;
}
// Long lines
if (line.length > 120) {
issues.push({ type: 'warning', msg: `บรรทัดยาวเกินไป (${line.length} ตัวอักษร)`, line: i + 1, fix: 'แบ่งบรรทัด' });
score -= 2;
}
// == instead of ===
if (trimmed.includes('==') && !trimmed.includes('===') && !trimmed.includes('!==')) {
issues.push({ type: 'warning', msg: 'ใช้ == — ควรใช้ === (strict equality)', line: i + 1, fix: 'เปลี่ยน == เป็น ===' });
score -= 4;
}
// Semicolon missing (simple check)
if (trimmed && !trimmed.endsWith('{') && !trimmed.endsWith('}') && !trimmed.endsWith(',') && !trimmed.endsWith(';') && !trimmed.startsWith('//') && !trimmed.startsWith('/*') && !trimmed.startsWith('*') && !trimmed.startsWith('import') && !trimmed.startsWith('from')) {
// Only flag simple statements
if (/^(var|let|const|function|return|if|for|while|console)/.test(trimmed)) {
issues.push({ type: 'info', msg: 'ขาด semicolon', line: i + 1, fix: 'เพิ่ม ; ท้ายบรรทัด' });
score -= 1;
}
}
// Magic numbers
const magicMatch = trimmed.match(/[^a-zA-Z_"](\d{2,})(?![a-zA-Z_"\d])/);
if (magicMatch && !trimmed.startsWith('//')) {
issues.push({ type: 'info', msg: `พบ magic number: ${magicMatch[1]}`, line: i + 1, fix: `กำหนดเป็น constant เช่น const MAX = ${magicMatch[1]}` });
score -= 2;
}
}
score = Math.max(0, Math.min(100, score));
return { score, issues, metrics, language: 'JavaScript' };
}
function analyzeHTML(code) {
const lines = code.split('\n');
const issues = [];
let score = 100;
let metrics = { lines: lines.length, functions: 0, classes: 0, imports: 0, comments: 0, blankLines: 0 };
const fullCode = code.toLowerCase();
// Check DOCTYPE
if (!fullCode.includes('<!doctype html>') && !fullCode.includes('<!DOCTYPE html>')) {
issues.push({ type: 'warning', msg: 'ไม่มี <!DOCTYPE html>', line: 1, fix: 'เพิ่ม <!DOCTYPE html> ที่ต้นไฟล์' });
score -= 5;
}
// Check lang attribute
if (fullCode.includes('<html') && !fullCode.includes('lang=')) {
issues.push({ type: 'info', msg: '<html> ไม่มี lang attribute', line: 1, fix: '<html lang="th">' });
score -= 3;
}
// Check meta viewport
if (!fullCode.includes('viewport')) {
issues.push({ type: 'warning', msg: 'ไม่มี meta viewport (ไม่ responsive)', line: 1, fix: '<meta name="viewport" content="width=device-width, initial-scale=1.0">' });
score -= 5;
}
// Check title
if (!fullCode.includes('<title>') || fullCode.match(/<title>\s*<\/title>/)) {
issues.push({ type: 'critical', msg: 'ไม่มี <title> หรือ title ว่าง', line: 1, fix: '<title>Page Title</title>' });
score -= 8;
}
for (let i = 0; i < lines.length; i++) {
const line = lines[i];
const lower = line.toLowerCase();
// Deprecated tags
if (lower.includes('<font') || lower.includes('<center') || lower.includes('<marquee') || lower.includes('<blink')) {
issues.push({ type: 'critical', msg: 'ใช้ deprecated tag', line: i + 1, fix: 'ใช้ CSS แทน (font-size, text-align, animation)' });
score -= 10;
}
// Inline styles
if (lower.includes('style=')) {
issues.push({ type: 'info', msg: 'ใช้ inline style', line: i + 1, fix: 'ย้ายไป CSS file หรือ <style> block' });
score -= 2;
}
// Unclosed tags (simple check)
const selfClosing = ['br', 'hr', 'img', 'input', 'meta', 'link'];
for (const tag of selfClosing) {
const regex = new RegExp(`<${tag}(?![^>]*\/>)(?![^>]*>)`, 'gi');
if (regex.test(line) && !line.includes(`</${tag}>`)) {
issues.push({ type: 'warning', msg: `Tag <${tag}> ไม่ปิด (ควรเป็น <${tag} />)`, line: i + 1, fix: `<${tag} />` });
score -= 3;
}
}
// Missing alt on images
if (lower.includes('<img') && !lower.includes('alt=')) {
issues.push({ type: 'warning', msg: '<img> ไม่มี alt attribute', line: i + 1, fix: '<img src="..." alt="description">' });
score -= 5;
}
// Multiple <br> tags
if ((lower.match(/<br/g) || []).length >= 3) {
issues.push({ type: 'warning', msg: 'ใช้ <br> หลายครั้งติดกัน — ควรใช้ CSS margin/padding', line: i + 1, fix: 'ใช้ CSS margin หรือ padding แทน' });
score -= 3;
}
// Table without proper structure
if (lower.includes('<table') && !lower.includes('<thead') && !lower.includes('<tbody')) {
issues.push({ type: 'info', msg: '<table> ไม่มี <thead>/<tbody>', line: i + 1, fix: 'เพิ่ม <thead> และ <tbody> สำหรับ accessibility' });
score -= 3;
}
// Long lines
if (line.length > 200) {
issues.push({ type: 'info', msg: `บรรทัดยาวเกินไป (${line.length} ตัวอักษร)`, line: i + 1, fix: 'แบ่งบรรทัดให้อ่านง่าย' });
score -= 1;
}
}
score = Math.max(0, Math.min(100, score));
return { score, issues, metrics, language: 'HTML' };
}
// ============================================================
// MAIN ANALYSIS
// ============================================================
let lastResult = null;
function analyzeCode() {
const code = document.getElementById('codeInput').value.trim();
if (!code) {
alert('กรุณาใส่โค้ดที่ต้องการวิเคราะห์');
return;
}
const lang = document.getElementById('langSelect').value;
let result;
if (lang === 'python') result = analyzePython(code);
else if (lang === 'javascript') result = analyzeJavaScript(code);
else if (lang === 'html') result = analyzeHTML(code);
lastResult = { ...result, code, timestamp: new Date().toISOString() };
renderResults(result);
document.getElementById('exportBtn').classList.remove('hidden');
}
function renderResults(result) {
const { score, issues, metrics, language } = result;
const scoreClass = score >= 70 ? 'score-high' : score >= 40 ? 'score-mid' : 'score-low';
const scoreColor = score >= 70 ? '#00ff88' : score >= 40 ? '#ffcc00' : '#ff4466';
const criticalCount = issues.filter(i => i.type === 'critical').length;
const warningCount = issues.filter(i => i.type === 'warning').length;
const infoCount = issues.filter(i => i.type === 'info').length;
const suggestionCount = issues.filter(i => i.type === 'suggestion').length;
const typeLabels = { critical: '🔴 CRITICAL', warning: '🟡 WARNING', info: '🔵 INFO', suggestion: '🟢 SUGGESTION' };
let html = `
<div class="score-display">
<div class="score-circle ${scoreClass}">${score}</div>
<div style="font-size:14px;color:#8888aa">คะแนนคุณภาพโค้ด (${language})</div>
</div>
<div class="stats-grid">
<div class="stat-item">
<div class="stat-value" style="color:#ff4466">${criticalCount}</div>
<div class="stat-label">Critical</div>
</div>
<div class="stat-item">
<div class="stat-value" style="color:#ffcc00">${warningCount}</div>
<div class="stat-label">Warnings</div>
</div>
<div class="stat-item">
<div class="stat-value" style="color:#00d4ff">${infoCount + suggestionCount}</div>
<div class="stat-label">Suggestions</div>
</div>
</div>
<div class="issues-list">`;
if (issues.length === 0) {
html += `<div style="text-align:center;padding:20px;color:#00ff88">✅ โค้ดดีมาก! ไม่พบปัญหา</div>`;
} else {
// Sort: critical first, then warning, info, suggestion
const sorted = [...issues].sort((a, b) => {
const order = { critical: 0, warning: 1, info: 2, suggestion: 3 };
return order[a.type] - order[b.type];
});
for (const issue of sorted) {
html += `
<div class="issue-item issue-${issue.type}">
<div class="issue-type">${typeLabels[issue.type]}</div>
<div class="issue-msg">${issue.msg}</div>
${issue.line > 0 ? `<div class="issue-line">📍 บรรทัดที่ ${issue.line}</div>` : ''}
<div class="issue-fix">💡 ${issue.fix}</div>
</div>`;
}
}
html += `</div>`;
document.getElementById('resultsArea').innerHTML = html;
}
function exportReport() {
if (!lastResult) return;
const { score, issues, metrics, language, code, timestamp } = lastResult;
const report = {
tool: 'Chimera Symbiote v2.0',
timestamp,
language,
score,
totalLines: code.split('\n').length,
issues: issues.map(i => ({
type: i.type,
message: i.msg,
line: i.line,
fix: i.fix
})),
summary: {
critical: issues.filter(i => i.type === 'critical').length,
warning: issues.filter(i => i.type === 'warning').length,
info: issues.filter(i => i.type === 'info').length,
suggestion: issues.filter(i => i.type === 'suggestion').length
}
};
const blob = new Blob([JSON.stringify(report, null, 2)], { type: 'application/json' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = `chimera-report-${Date.now()}.json`;
a.click();
URL.revokeObjectURL(url);
}
// ============================================================
// PRICING
// ============================================================
function showPricing() {
document.getElementById('pricingModal').classList.add('active');
}
function closePricing() {
document.getElementById('pricingModal').classList.remove('active');
}
function contactSales(plan) {
alert(`สนใจแพ็กเกจ ${plan}\n\nกรุณาติดต่อผ่านช่องทางใน Landing Page`);
closePricing();
}
// Close modal on overlay click
document.getElementById('pricingModal').addEventListener('click', function(e) {
if (e.target === this) closePricing();
});
</script>
</body>
</html>

Xet Storage Details

Size:
37 kB
·
Xet hash:
d2af5e164867d1e020764423dfd571f0770e8b10612f5ebf08e8b49b4d1510de

Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.