68 lines · 2.6 KB
import { env } from "cloudflare:workers";
import bootSource from "./workbench-boot.js?raw";
import { toBase64 } from "../crypto";
import { forgeOriginFor } from "./origin";

const VSCODE_VERSION = "1.91.1";
const OPEN_VSX = "https://open-vsx.org https://*.open-vsx.org";

let bootHash: Promise<string> | null = null;

function sha256Base64(text: string): Promise<string> {
  return crypto.subtle
    .digest("SHA-256", new TextEncoder().encode(text))
    .then((digest) => toBase64(new Uint8Array(digest)));
}

function escapeJson(value: unknown): string {
  return JSON.stringify(value).replace(/</g, "\\u003c");
}

/**
 * The workbench document, served only on the editor origin. CSP limits scripts to the vendored build and
 * the hashed bootstrap, network access to the forge API (and Open VSX only when the gallery is enabled),
 * and embedding to the forge itself.
 */
export async function workbenchResponse(url: URL): Promise<Response> {
  bootHash ??= sha256Base64(bootSource);
  const forgeOrigin = forgeOriginFor(url);
  const forgeSocket = forgeOrigin.replace(/^http/, "ws");
  const gallery = env.EDITOR_OPEN_VSX === "on";
  const remote = gallery ? ` ${OPEN_VSX}` : "";
  const config = {
    forgeOrigin,
    assetBase: `${url.origin}/vscode-web/${VSCODE_VERSION}`,
    vscodeVersion: VSCODE_VERSION,
    gallery,
  };
  const html = `<!doctype html><html lang="en" style="color-scheme:dark;background:#1f1f1f"><head><meta charset="utf-8"><meta name="color-scheme" content="dark"><title>gitfor editor</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no">
<script type="application/json" id="gitfor-config">${escapeJson(config)}</script></head>