feat: web playground + LSP server + docs update

This commit is contained in:
2026-06-07 18:29:05 +03:00
parent b3af1208e8
commit 3ffa9f7d54
2 changed files with 205 additions and 0 deletions
+100
View File
@@ -0,0 +1,100 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Bux Playground</title>
<style>
* { box-sizing: border-box; margin: 0; padding: 0; }
body { font-family: 'Fira Code', 'JetBrains Mono', monospace; background: #1a1b26; color: #a9b1d6; min-height: 100vh; }
.header { background: #24283b; padding: 12px 20px; font-size: 14px; border-bottom: 1px solid #414868; display: flex; align-items: center; gap: 12px; }
.header .logo { font-weight: bold; color: #7aa2f7; font-size: 18px; }
.header .version { color: #565f89; font-size: 12px; }
.main { display: flex; flex-direction: column; height: calc(100vh - 50px); }
.toolbar { display: flex; gap: 8px; padding: 8px 16px; background: #1e2030; border-bottom: 1px solid #292e42; }
.toolbar button { padding: 6px 16px; border: 1px solid #414868; background: #24283b; color: #a9b1d6; cursor: pointer; border-radius: 4px; font-size: 13px; font-family: inherit; }
.toolbar button:hover { background: #2f334a; }
.toolbar button.run { background: #9ece6a; color: #1a1b26; border-color: #9ece6a; font-weight: bold; }
.toolbar button.run:hover { background: #b9f27c; }
.editor { flex: 1; display: flex; }
.editor textarea { flex: 1; background: #1a1b26; color: #a9b1d6; border: none; padding: 16px; font-family: 'Fira Code', 'JetBrains Mono', monospace; font-size: 14px; line-height: 1.6; resize: none; outline: none; tab-size: 4; }
.output { background: #13141c; border-top: 1px solid #292e42; min-height: 0; height: 30%; overflow-y: auto; padding: 12px 16px; font-size: 13px; line-height: 1.5; white-space: pre-wrap; word-break: break-all; }
.output.error { color: #f7768e; }
.output.success { color: #9ece6a; }
.shortcuts { color: #565f89; font-size: 11px; padding: 4px 16px; background: #1e2030; border-top: 1px solid #292e42; }
</style>
</head>
<body>
<div class="header">
<span class="logo">Bux Playground</span>
<span class="version">Try Bux in your browser — no install needed</span>
</div>
<div class="main">
<div class="toolbar">
<button class="run" onclick="runCode()" title="Ctrl+Enter">▶ Run</button>
<button onclick="clearOutput()">Clear</button>
</div>
<div class="editor">
<textarea id="code" spellcheck="false" placeholder="Write your Bux code here...">import Std::Io::PrintLine;
func Main() -> int {
PrintLine("Hello, Bux!");
return 0;
}</textarea>
</div>
<div class="output" id="output"></div>
<div class="shortcuts">Ctrl+Enter to run</div>
</div>
<script>
const codeArea = document.getElementById('code');
const outputDiv = document.getElementById('output');
async function runCode() {
const code = codeArea.value;
outputDiv.textContent = 'Running...';
outputDiv.className = 'output';
try {
const resp = await fetch('/compile', {
method: 'POST',
headers: { 'Content-Type': 'text/plain' },
body: code
});
const data = await resp.json();
// Filter build lines (only show compile errors + program output)
let output = data.output || '';
let lines = output.split('\n');
let filtered = [];
for (let i = 0; i < lines.length; i++) {
let line = lines[i];
// Skip verbose build headers
if (line.includes('[Package]') || line.includes('[Build]') ||
line.includes('Hint:') || line.includes('Bux compiler')) continue;
if (line.startsWith('Compiling') || line.startsWith('Linking')) continue;
filtered.push(line);
}
outputDiv.textContent = filtered.join('\n').trim() || '(no output)';
outputDiv.className = 'output' + (data.isError ? ' error' : ' success');
} catch (e) {
outputDiv.textContent = 'Error: ' + e.message;
outputDiv.className = 'output error';
}
}
function clearOutput() {
outputDiv.textContent = '';
outputDiv.className = 'output';
}
// Ctrl+Enter shortcut
codeArea.addEventListener('keydown', (e) => {
if (e.ctrlKey && e.key === 'Enter') {
e.preventDefault();
runCode();
}
});
</script>
</body>
</html>