mirror of
https://github.com/MercuryWorkshop/scramjet.git
synced 2025-05-13 14:30:02 -04:00
scramjet playground
This commit is contained in:
parent
883d8fb4a9
commit
544b18643c
4 changed files with 313 additions and 3 deletions
62
static/playground.html
Normal file
62
static/playground.html
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>Scramjet</title>
|
||||||
|
<link rel="icon" href="favicon.webp" />
|
||||||
|
<link rel="prefetch" href="/scram/scramjet.worker.js" />
|
||||||
|
<link rel="prefetch" href="/scram/scramjet.shared.js" />
|
||||||
|
<link
|
||||||
|
href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;1,100;1,200;1,300;1,400;1,500;1,600;1,700&family=Inter+Tight:ital,wght@0,100..900;1,100..900&family=Inter:wght@100..900&display=swap&"
|
||||||
|
rel="stylesheet"
|
||||||
|
/>
|
||||||
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||||
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||||
|
<link
|
||||||
|
href="https://fonts.googleapis.com/css2?family=Hind:wght@300;400;500;600;700&display=swap"
|
||||||
|
rel="stylesheet"
|
||||||
|
/>
|
||||||
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||||
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||||
|
<link
|
||||||
|
href="https://fonts.googleapis.com/css2?family=Hind:wght@300;400;500;600;700&family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap"
|
||||||
|
rel="stylesheet"
|
||||||
|
/>
|
||||||
|
<style>
|
||||||
|
body,
|
||||||
|
html,
|
||||||
|
#app {
|
||||||
|
font-family:
|
||||||
|
"Inter",
|
||||||
|
system-ui,
|
||||||
|
-apple-system,
|
||||||
|
BlinkMacSystemFont,
|
||||||
|
sans-serif;
|
||||||
|
width: 100vw;
|
||||||
|
height: 100vh;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
background-color: #050505;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes fade {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/dreamland"></script>
|
||||||
|
<script src="/baremux/index.js" defer></script>
|
||||||
|
<script src="/scram/scramjet.controller.js"></script>
|
||||||
|
<script src="config.js"></script>
|
||||||
|
<script src="playground.js" defer></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
217
static/playground.js
Normal file
217
static/playground.js
Normal file
|
@ -0,0 +1,217 @@
|
||||||
|
const scramjet = new ScramjetController({
|
||||||
|
files: {
|
||||||
|
wasm: "/scram/scramjet.wasm.js",
|
||||||
|
worker: "/scram/scramjet.worker.js",
|
||||||
|
client: "/scram/scramjet.client.js",
|
||||||
|
shared: "/scram/scramjet.shared.js",
|
||||||
|
sync: "/scram/scramjet.sync.js",
|
||||||
|
},
|
||||||
|
siteFlags: {
|
||||||
|
"https://worker-playground.glitch.me/.*": {
|
||||||
|
serviceworkers: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
scramjet.init("./sw.js");
|
||||||
|
|
||||||
|
const connection = new BareMux.BareMuxConnection("/baremux/worker.js");
|
||||||
|
const flex = css`
|
||||||
|
display: flex;
|
||||||
|
`;
|
||||||
|
const col = css`
|
||||||
|
flex-direction: column;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const store = $store(
|
||||||
|
{
|
||||||
|
url: "https://google.com",
|
||||||
|
wispurl:
|
||||||
|
_CONFIG?.wispurl ||
|
||||||
|
(location.protocol === "https:" ? "wss" : "ws") +
|
||||||
|
"://" +
|
||||||
|
location.host +
|
||||||
|
"/wisp/",
|
||||||
|
bareurl:
|
||||||
|
_CONFIG?.bareurl ||
|
||||||
|
(location.protocol === "https:" ? "https" : "http") +
|
||||||
|
"://" +
|
||||||
|
location.host +
|
||||||
|
"/bare/",
|
||||||
|
proxy: "",
|
||||||
|
},
|
||||||
|
{ ident: "settings", backing: "localstorage", autosave: "auto" }
|
||||||
|
);
|
||||||
|
connection.setTransport("/epoxy/index.mjs", [{ wisp: store.wispurl }]);
|
||||||
|
|
||||||
|
function PlaygroundApp() {
|
||||||
|
this.css = `
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
color: #f0fef4;
|
||||||
|
display: flex;
|
||||||
|
padding: 0.5em;
|
||||||
|
box-sizing: border-box;
|
||||||
|
gap: 0.5em;
|
||||||
|
|
||||||
|
|
||||||
|
.codesplit {
|
||||||
|
width: 50%;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
gap: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mcontainer {
|
||||||
|
background: #1e1e1e;
|
||||||
|
h2 {
|
||||||
|
margin: 0.1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
border: 1px solid #313131;
|
||||||
|
flex-basis: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
.monaco {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.frame {
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.5em;
|
||||||
|
iframe {
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
border: 1px solid #313131;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.config {
|
||||||
|
border: 1px solid #313131;
|
||||||
|
background: #1e1e1e;
|
||||||
|
padding: 0.5em;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
this.fakeorigin = "https://sandboxedorigin.com";
|
||||||
|
this.mount = async () => {
|
||||||
|
const monaco = await import(
|
||||||
|
"https://cdn.jsdelivr.net/npm/monaco-editor/+esm"
|
||||||
|
);
|
||||||
|
|
||||||
|
monaco.editor.setTheme("vs-dark");
|
||||||
|
const html = monaco.editor.create(this.htmlbox, {
|
||||||
|
value: `<html>
|
||||||
|
<head>
|
||||||
|
<!-- all resources are intercepted by the service worker -->
|
||||||
|
<link rel="stylesheet" href="/style.css"></link>
|
||||||
|
<script src="/script.js"></script>
|
||||||
|
|
||||||
|
<!-- external resources go through WISP -->
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Scramjet Sandbox Playground</h1>
|
||||||
|
<p>
|
||||||
|
Scramjet allows any webpage to be run on the same origin in an isolated manner
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
<button onclick="checkOrigin()">Test emulated origin</button>
|
||||||
|
<button onclick="loadResource('https://example.com/')">Load assets through sandbox</button>
|
||||||
|
</body>
|
||||||
|
</html>`,
|
||||||
|
language: "html",
|
||||||
|
});
|
||||||
|
const js = monaco.editor.create(this.jsbox, {
|
||||||
|
value: `function checkOrigin() {
|
||||||
|
alert("origin: " + window.origin);
|
||||||
|
}
|
||||||
|
|
||||||
|
// external resources fetched will be re-
|
||||||
|
// directed to the WISP server
|
||||||
|
function loadResource(url) {
|
||||||
|
fetch(url).then(r => {
|
||||||
|
console.log("loaded", r);
|
||||||
|
})
|
||||||
|
}`,
|
||||||
|
language: "javascript",
|
||||||
|
});
|
||||||
|
const css = monaco.editor.create(this.cssbox, {
|
||||||
|
value: `body, html {
|
||||||
|
background: #1e1e1e;
|
||||||
|
color: white;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}`,
|
||||||
|
language: "css",
|
||||||
|
});
|
||||||
|
let oldjs;
|
||||||
|
let oldhtml;
|
||||||
|
let oldcss;
|
||||||
|
|
||||||
|
setInterval(async () => {
|
||||||
|
if (
|
||||||
|
oldjs !== js.getValue() ||
|
||||||
|
oldhtml !== html.getValue() ||
|
||||||
|
oldcss !== css.getValue()
|
||||||
|
) {
|
||||||
|
oldjs = js.getValue();
|
||||||
|
oldhtml = html.getValue();
|
||||||
|
oldcss = css.getValue();
|
||||||
|
|
||||||
|
(await navigator.serviceWorker.ready).active.postMessage({
|
||||||
|
type: "playgroundData",
|
||||||
|
html: html.getValue(),
|
||||||
|
css: css.getValue(),
|
||||||
|
js: js.getValue(),
|
||||||
|
origin: this.fakeorigin,
|
||||||
|
});
|
||||||
|
|
||||||
|
this.frame.src = scramjet.encodeUrl(this.fakeorigin);
|
||||||
|
}
|
||||||
|
}, 1000);
|
||||||
|
};
|
||||||
|
|
||||||
|
return html`
|
||||||
|
<div>
|
||||||
|
<div class="codesplit">
|
||||||
|
<div class="mcontainer">
|
||||||
|
<h2>HTML</h2>
|
||||||
|
<div class="monaco" bind:this=${use(this.htmlbox)}></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mcontainer">
|
||||||
|
<h2>JS</h2>
|
||||||
|
<div class="monaco" bind:this=${use(this.jsbox)}></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mcontainer">
|
||||||
|
<h2>CSS</h2>
|
||||||
|
<div class="monaco" bind:this=${use(this.cssbox)}></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="frame" style="flex: 1">
|
||||||
|
<iframe style="flex: 1" bind:this=${use(this.frame)}></iframe>
|
||||||
|
<div class="config">
|
||||||
|
<h1>Config</h1>
|
||||||
|
<div>
|
||||||
|
<label>fake origin:</label>
|
||||||
|
<input bind:value=${use(this.fakeorigin)} />
|
||||||
|
|
||||||
|
<label>wisp server:</label>
|
||||||
|
<input bind:value=${use(store.wispurl)} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
window.addEventListener("load", async () => {
|
||||||
|
document.body.appendChild(h(PlaygroundApp));
|
||||||
|
});
|
32
static/sw.js
32
static/sw.js
|
@ -18,3 +18,35 @@ async function handleRequest(event) {
|
||||||
self.addEventListener("fetch", (event) => {
|
self.addEventListener("fetch", (event) => {
|
||||||
event.respondWith(handleRequest(event));
|
event.respondWith(handleRequest(event));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let playgroundData;
|
||||||
|
self.addEventListener("message", ({ data }) => {
|
||||||
|
if (data.type === "playgroundData") {
|
||||||
|
playgroundData = data;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
scramjet.addEventListener("request", (e) => {
|
||||||
|
let headers = {};
|
||||||
|
if (e.url.href === playgroundData.origin + "/") {
|
||||||
|
headers["content-type"] = "text/html";
|
||||||
|
e.response = new Response(playgroundData.html, {
|
||||||
|
headers,
|
||||||
|
});
|
||||||
|
} else if (e.url.href === playgroundData.origin + "/style.css") {
|
||||||
|
headers["content-type"] = "text/css";
|
||||||
|
e.response = new Response(playgroundData.css, {
|
||||||
|
headers,
|
||||||
|
});
|
||||||
|
} else if (e.url.href === playgroundData.origin + "/script.js") {
|
||||||
|
headers["content-type"] = "application/javascript";
|
||||||
|
e.response = new Response(playgroundData.js, {
|
||||||
|
headers,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
e.response.rawHeaders = headers;
|
||||||
|
e.response.finalURL = e.url;
|
||||||
|
});
|
||||||
|
|
|
@ -122,7 +122,7 @@ function Config() {
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function App() {
|
function BrowserApp() {
|
||||||
this.urlencoded = "";
|
this.urlencoded = "";
|
||||||
this.css = `
|
this.css = `
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
@ -253,9 +253,8 @@ function App() {
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
window.addEventListener("load", async () => {
|
window.addEventListener("load", async () => {
|
||||||
document.body.appendChild(h(App));
|
document.body.appendChild(h(BrowserApp));
|
||||||
function b64(buffer) {
|
function b64(buffer) {
|
||||||
let binary = "";
|
let binary = "";
|
||||||
const bytes = new Uint8Array(buffer);
|
const bytes = new Uint8Array(buffer);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue