1// Bundles src/ into dist/ (the unpacked extension). `--watch` rebuilds on change.
2// `--store` writes dist-store/ for the Chrome Web Store instead: no pinned key (the store assigns the ID),
3// no bundled host or installer, and a version without leading zeros.
4import * as esbuild from "esbuild";
5import { chmodSync, cpSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
6import { dirname, join } from "node:path";
7import { fileURLToPath } from "node:url";
9const root = join(dirname(fileURLToPath(import.meta.url)), "..");
10const store = process.argv.includes("--store");
11const dist = join(root, store ? "dist-store" : "dist");
12const watch = process.argv.includes("--watch");
14rmSync(dist, { recursive: true, force: true });
15mkdirSync(dist, { recursive: true });
17const common = { bundle: true, target: "es2022", logLevel: "info", legalComments: "none", charset: "utf8" };
19 { entryPoints: { background: join(root, "src/background/index.ts") }, format: "esm" },
20 { entryPoints: { content: join(root, "src/content/meta.ts") }, format: "iife" },
21 { entryPoints: { popup: join(root, "src/popup/popup.ts"), options: join(root, "src/options/options.ts") }, format: "esm" },
24function copyStatic() {
25 const manifest = JSON.parse(readFileSync(join(root, "manifest.json"), "utf8"));
26 if (!manifest.key || manifest.key.startsWith("__")) {
27 console.warn("manifest.json has no pinned key yet: run scripts/gen-key.sh (the extension ID will not be stable)");
30 const stamp = process.env.DIAGONAL_VERSION;
32 // Release builds pass the commit time as YYYY.MM.DD.HHMM (see .github/workflows/release.yml).
33 if (!/^\d{4}\.\d{2}\.\d{2}\.\d{4}$/.test(stamp)) throw new Error(`DIAGONAL_VERSION must be YYYY.MM.DD.HHMM, got ${stamp}`);
34 manifest.version = stamp;
38 manifest.version = manifest.version.split(".").map((n) => String(Number(n))).join(".");
40 writeFileSync(join(dist, "manifest.json"), JSON.stringify(manifest, null, 2) + "\n");
41 cpSync(join(root, "src/popup/popup.html"), join(dist, "popup.html"));
42 cpSync(join(root, "src/options/options.html"), join(dist, "options.html"));
43 cpSync(join(root, "src/shared/ui.css"), join(dist, "ui.css"));
44 cpSync(join(root, "icons"), join(dist, "icons"), { recursive: true, filter: (p) => !p.endsWith("icon.png") });
45 if (store) return; // the store package is the extension alone; the host comes from Homebrew
46 // The native host and its installer ride along, so the release zip is all a user needs.
47 mkdirSync(join(dist, "host"));
48 for (const f of ["prompts.py", "validate.py", "emoji.txt"]) cpSync(join(root, "host", f), join(dist, "host", f));
49 // The host reports the same version as the extension it shipped with.
50 const hostSrc = readFileSync(join(root, "host/diagonal-host.py"), "utf8");
51 const stamped = hostSrc.replace(/^HOST_VERSION = "[^"]*"/m, `HOST_VERSION = "${manifest.version}"`);
52 if (stamped === hostSrc && !hostSrc.includes(`HOST_VERSION = "${manifest.version}"`)) throw new Error("HOST_VERSION line not found in host/diagonal-host.py");
53 writeFileSync(join(dist, "host/diagonal-host.py"), stamped);
54 chmodSync(join(dist, "host/diagonal-host.py"), 0o755);
55 cpSync(join(root, "extension-id"), join(dist, "extension-id"));
56 cpSync(join(root, "scripts/install-manifest.sh"), join(dist, "install-host.command"));
57 chmodSync(join(dist, "install-host.command"), 0o755);
62 for (const b of builds) await (await esbuild.context({ ...common, ...b, outdir: dist })).watch();
64 await Promise.all(builds.map((b) => esbuild.build({ ...common, ...b, outdir: dist })));
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list