feat(wasm-emcc): add browser support for Neovim

This commit is contained in:
rawan10101
2026-07-16 21:17:54 +03:00
parent c15ac3d64c
commit 9cabba671d
8 changed files with 106 additions and 0 deletions

60
src/wasm/app.js Normal file
View File

@@ -0,0 +1,60 @@
const statusEl = document.getElementById('status');
const logEl = document.getElementById('log');
const setStatus = s => statusEl.textContent = s;
const log = (...args) => {
logEl.textContent += args.map(a => typeof a === 'string' ? a : JSON.stringify(a)).join(' ') + '\n';
console.log(...args);
};
if (!crossOriginIsolated) {
setStatus('NOT cross-origin isolated -- SharedArrayBuffer unavailable. Serve with COOP/COEP headers.');
} else {
main();
}
function main() {
const transport = new WorkerTransport('nvim-worker.js', { cols: 80, rows: 24 });
transport.onStatus(text => { setStatus(text); log('[status]', text); });
const nvim = new RpcClient(transport);
setTimeout(async () => {
console.log("Auto Request");
try {
const r = await nvim.request("nvim_get_api_info", []);
console.log(r);
} catch (e) {
console.error(e);
}
}, 10000);
nvim.on('redraw', params => log('Notification redraw', params));
document.getElementById('apiInfoBtn').addEventListener('click', async () => {
setStatus('sending nvim_get_api_info...');
try {
const result = await nvim.request('nvim_get_api_info', []);
log('RESPONSE nvim_get_api_info ->', result);
setStatus('got nvim_get_api_info response');
} catch (e) {
log('ERROR nvim_get_api_info ->', e);
setStatus('nvim_get_api_info failed, see log');
}
});
document.getElementById('attachBtn').addEventListener('click', async () => {
setStatus('sending nvim_ui_attach...');
try {
const result = await nvim.request('nvim_ui_attach', [80, 24, { rgb: true, ext_linegrid: true }]);
log('RESPONSE nvim_ui_attach ->', result);
setStatus('UI attached finally. Watching for redraw notifications...');
} catch (e) {
log('ERROR nvim_ui_attach ->', e);
setStatus('nvim_ui_attach failed, see log');
}
});
document.getElementById('persistBtn').addEventListener('click', () => {
transport.persist();
});
}

25
src/wasm/index.html Normal file
View File

@@ -0,0 +1,25 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>nvim.wasm RPC client</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div id="bar">
<button id="apiInfoBtn">1. Send nvim_get_api_info</button>
<button id="attachBtn">2. Send nvim_ui_attach</button>
<button id="persistBtn">Persist now</button>
<span id="status">booting…</span>
</div>
<div id="log"></div>
<!-- msgpack library -->
<script crossorigin src="https://unpkg.com/@msgpack/msgpack@3.1.2/dist.umd/msgpack.min.js"></script>
<script src="msgpack.js"></script>
<script src="protocol.js"></script>
<script src="rpc.js"></script>
<script src="app.js"></script>
</body>
</html>

0
src/wasm/msgpack.js Normal file
View File

0
src/wasm/nvim-worker.js Normal file
View File

0
src/wasm/protocol.js Normal file
View File

0
src/wasm/rpc.js Normal file
View File

16
src/wasm/serve.py Normal file
View File

@@ -0,0 +1,16 @@
#!/usr/bin/env python3
import http.server
import socketserver
PORT = 8001
class Handler(http.server.SimpleHTTPRequestHandler):
def end_headers(self):
self.send_header("Cross-Origin-Opener-Policy", "same-origin")
self.send_header("Cross-Origin-Embedder-Policy", "require-corp")
super().end_headers()
if __name__ == "__main__":
with socketserver.TCPServer(("", PORT), Handler) as httpd:
print(f"Serving with COOP/COEP on http://localhost:{PORT}")
httpd.serve_forever()

5
src/wasm/style.css Normal file
View File

@@ -0,0 +1,5 @@
body { font-family: monospace; background: #1e1e1e; color: #ddd; padding: 10px; margin: 0; }
#bar { margin-bottom: 10px; }
#bar button { margin-right: 8px; }
#status { color: #9c9; }
#log { white-space: pre-wrap; background: #111; padding: 10px; border-radius: 4px; }