/ concept-collection / stan-web-ide
Sign in
concept-collection / stan-web-ide
stan-web-ide / src / main.ts
83 lines · 2.7 KBCodeBlameHistory
21efcb6stan web IDE: run Stan sampling in the browserJeremy Magland 1import { loadBuiltinTheme, registerBuiltinLanguages } from 'minwebide';
f66b0fbOpen GitHub repos as workspaces via #/github/<spec>Jeremy Magland 2import { openGitHubRoute } from './githubOpen';
21efcb6stan web IDE: run Stan sampling in the browserJeremy Magland 3import { openIde } from './ide';
4import { renderLanding } from './landing';
5import { registerStanLanguage } from './stan/language';
6import { registerStanLsp } from './stan/lsp';
7import { getProject } from './projects';
9// Routes:
10// #/ project picker (landing page)
11// #/project/<id> the IDE, opened on that project's file system
f66b0fbOpen GitHub repos as workspaces via #/github/<spec>Jeremy Magland 12// #/github/<spec> a GitHub repo as its own workspace (owner/repo[@ref],
13// or a URL-encoded github.com URL); imports on first
14// visit, then keeps a local editable copy — the URL
15// stays on this route and no project is created
17async function start(): Promise<void> {
f66b0fbOpen GitHub repos as workspaces via #/github/<spec>Jeremy Magland 18 // this app no longer uses a service worker (pure-WASI sampling needs no
19 // cross-origin isolation) — unregister the coi-serviceworker that earlier
20 // deployed versions registered, since a stale controlling SW keeps
21 // rewriting response headers
22 if ('serviceWorker' in navigator) {
21efcb6stan web IDE: run Stan sampling in the browserJeremy Magland 23 const registrations = await navigator.serviceWorker.getRegistrations();
24 if (registrations.length > 0) {
25 await Promise.all(registrations.map(r => r.unregister()));
26 if (navigator.serviceWorker.controller) {
27 location.reload();
28 return;
29 }
30 }
31 }
33 const app = document.getElementById('app')!;
35 // one-time global setup: theme + languages are shared by all views;
36 // Stan registers last so it owns .stan (and .sample maps to YAML)
37 const theme = await loadBuiltinTheme('dark_modern');
38 await registerBuiltinLanguages(theme);
39 registerStanLanguage();
40 // the Stan language server (diagnostics, hover, completion, format) runs
41 // in one worker for the whole session, across projects
42 registerStanLsp();
44 let current: { dispose(): void } | undefined;
45 let navigating = false;
47 const route = async () => {
48 if (navigating) {
49 return;
50 }
51 navigating = true;
52 try {
53 current?.dispose();
54 current = undefined;
55 app.textContent = '';
f66b0fbOpen GitHub repos as workspaces via #/github/<spec>Jeremy Magland 57 const github = location.hash.match(/^#\/github\/(.+)$/);
58 if (github) {
59 current = await openGitHubRoute(app, decodeURIComponent(github[1]), theme);
60 return;
61 }
21efcb6stan web IDE: run Stan sampling in the browserJeremy Magland 63 const match = location.hash.match(/^#\/project\/([a-z0-9]+)/i);
64 if (match) {
65 const project = getProject(match[1]);
66 if (project) {
67 current = await openIde(app, project, theme);
68 return;
69 }
70 // unknown project id: fall through to the landing page
71 history.replaceState(null, '', '#/');
72 }
73 current = renderLanding(app, theme);
74 } finally {
75 navigating = false;
76 }
77 };
79 window.addEventListener('hashchange', route);
80 await route();
83start();
moveopenescclose