mirror of
https://github.com/getpaseo/paseo.git
synced 2026-10-22 09:12:44 +00:00
Use one source-editor contract and shared editing runtime across browser and native hosts so file-pane persistence, conflicts, and line endings keep the same semantics on every platform.
96 lines
3.0 KiB
JavaScript
96 lines
3.0 KiB
JavaScript
import esbuild from "esbuild";
|
|
import fs from "node:fs/promises";
|
|
import path from "node:path";
|
|
import { fileURLToPath } from "node:url";
|
|
|
|
const scriptDirectory = path.dirname(fileURLToPath(import.meta.url));
|
|
const appRoot = path.resolve(scriptDirectory, "..");
|
|
const repoRoot = path.resolve(appRoot, "../..");
|
|
const entry = path.join(appRoot, "src/source-editor/codemirror/webview-entry.ts");
|
|
const output = path.join(appRoot, "src/source-editor/codemirror/webview-html.ts");
|
|
const checkOnly = process.argv.includes("--check");
|
|
|
|
async function resolveTsPath(basePath) {
|
|
const candidates = [
|
|
basePath,
|
|
`${basePath}.ts`,
|
|
`${basePath}.tsx`,
|
|
`${basePath}.js`,
|
|
`${basePath}.jsx`,
|
|
path.join(basePath, "index.ts"),
|
|
path.join(basePath, "index.tsx"),
|
|
];
|
|
for (const candidate of candidates) {
|
|
try {
|
|
if ((await fs.stat(candidate)).isFile()) return candidate;
|
|
} catch {
|
|
// Try the next TypeScript resolution candidate.
|
|
}
|
|
}
|
|
return basePath;
|
|
}
|
|
|
|
const aliasPlugin = {
|
|
name: "paseo-alias",
|
|
setup(build) {
|
|
build.onResolve({ filter: /^@\// }, async (args) => ({
|
|
path: await resolveTsPath(path.join(appRoot, "src", args.path.slice(2))),
|
|
}));
|
|
},
|
|
};
|
|
|
|
const result = await esbuild.build({
|
|
entryPoints: [entry],
|
|
bundle: true,
|
|
write: false,
|
|
format: "iife",
|
|
platform: "browser",
|
|
target: ["ios15", "chrome100"],
|
|
plugins: [aliasPlugin],
|
|
logLevel: "info",
|
|
});
|
|
|
|
const javascript = result.outputFiles[0]?.text;
|
|
if (!javascript) throw new Error("source editor WebView bundle produced no JavaScript");
|
|
|
|
const html = `<!doctype html>
|
|
<html>
|
|
<head>
|
|
<meta charset="utf-8" />
|
|
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; script-src 'unsafe-inline'; style-src 'unsafe-inline'; img-src data:" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, viewport-fit=cover, interactive-widget=resizes-content" />
|
|
<style>
|
|
html, body, #source-editor-root, #source-editor-host {
|
|
width: 100%; height: 100%; margin: 0; padding: 0; overflow: hidden;
|
|
}
|
|
html, body { overscroll-behavior: none; }
|
|
#source-editor-root, #source-editor-host { display: flex; min-width: 0; min-height: 0; }
|
|
#source-editor-host { flex: 1; }
|
|
* { -webkit-tap-highlight-color: transparent; }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<script>${javascript}</script>
|
|
</body>
|
|
</html>`;
|
|
|
|
const contents = `// Generated by packages/app/scripts/build-source-editor-webview-html.mjs.
|
|
// Do not edit by hand.
|
|
|
|
export const sourceEditorWebViewHtml =
|
|
${JSON.stringify(html)};
|
|
`;
|
|
|
|
if (checkOnly) {
|
|
const existing = await fs.readFile(output, "utf8").catch(() => null);
|
|
if (existing !== contents) {
|
|
throw new Error(
|
|
`${path.relative(repoRoot, output)} is stale. Run npm --prefix packages/app run build:source-editor-webview.`,
|
|
);
|
|
}
|
|
console.log(`${path.relative(repoRoot, output)} is current (${html.length} bytes)`);
|
|
} else {
|
|
await fs.writeFile(output, contents);
|
|
console.log(`Wrote ${path.relative(repoRoot, output)} (${html.length} bytes)`);
|
|
}
|