feat(*): svelte 5 panel view sharing the gateway ui, obsidian theme, preview and tests
This commit is contained in:
@@ -0,0 +1,126 @@
|
||||
import {
|
||||
createReadStream,
|
||||
existsSync,
|
||||
mkdtempSync,
|
||||
readdirSync,
|
||||
statSync,
|
||||
writeFileSync,
|
||||
} from "node:fs";
|
||||
import { createServer } from "node:http";
|
||||
import { homedir, tmpdir } from "node:os";
|
||||
import { extname, join, normalize } from "node:path";
|
||||
import { extractFile } from "@electron/asar";
|
||||
import esbuild from "esbuild";
|
||||
import { root, sharedLib, svelte } from "../esbuild.config.mjs";
|
||||
|
||||
const port = Number(process.env.PORT ?? 4174);
|
||||
|
||||
const ASAR_CANDIDATES = [
|
||||
process.env.OBSIDIAN_ASAR,
|
||||
"/Applications/Obsidian.app/Contents/Resources/obsidian.asar",
|
||||
join(homedir(), "Applications/Obsidian.app/Contents/Resources/obsidian.asar"),
|
||||
"/opt/Obsidian/resources/obsidian.asar",
|
||||
"/usr/lib/obsidian/resources/obsidian.asar",
|
||||
].filter(Boolean);
|
||||
|
||||
function findAppCss() {
|
||||
for (const candidate of ASAR_CANDIDATES) {
|
||||
if (!existsSync(candidate)) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
const path = join(mkdtempSync(join(tmpdir(), "beaver-app-")), "app.css");
|
||||
writeFileSync(path, extractFile(candidate, "app.css"));
|
||||
return path;
|
||||
} catch {
|
||||
/* try the next candidate */
|
||||
}
|
||||
}
|
||||
console.warn(
|
||||
"preview: could not read app.css from an Obsidian install. Set OBSIDIAN_ASAR to point at obsidian.asar; without it the chrome will not match the real app."
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
function findTheme() {
|
||||
if (process.env.THEME) {
|
||||
return process.env.THEME;
|
||||
}
|
||||
const vault = process.env.VAULT;
|
||||
if (!vault) {
|
||||
return null;
|
||||
}
|
||||
const themes = join(vault, ".obsidian/themes");
|
||||
if (!existsSync(themes)) {
|
||||
return null;
|
||||
}
|
||||
for (const name of readdirSync(themes)) {
|
||||
const css = join(themes, name, "theme.css");
|
||||
if (existsSync(css)) {
|
||||
return css;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
const appCss = findAppCss();
|
||||
const theme = findTheme();
|
||||
|
||||
const ctx = await esbuild.context({
|
||||
bundle: true,
|
||||
conditions: ["svelte", "browser"],
|
||||
entryPoints: [join(root, "preview/entry.ts")],
|
||||
format: "iife",
|
||||
logLevel: "info",
|
||||
mainFields: ["svelte", "browser", "module", "main"],
|
||||
outfile: join(root, "preview/bundle.js"),
|
||||
plugins: [
|
||||
sharedLib({ obsidian: join(root, "tests/obsidian-stub.ts") }),
|
||||
svelte(),
|
||||
],
|
||||
sourcemap: "inline",
|
||||
target: "es2022",
|
||||
});
|
||||
await ctx.rebuild();
|
||||
await ctx.watch();
|
||||
|
||||
const TYPES = {
|
||||
".css": "text/css; charset=utf-8",
|
||||
".html": "text/html; charset=utf-8",
|
||||
".js": "text/javascript; charset=utf-8",
|
||||
};
|
||||
|
||||
createServer((request, response) => {
|
||||
const url = decodeURIComponent((request.url ?? "/").split("?")[0]);
|
||||
const external = { "/app.css": appCss, "/theme.css": theme };
|
||||
|
||||
if (url in external) {
|
||||
const file = external[url];
|
||||
if (!file) {
|
||||
response.writeHead(200, { "content-type": TYPES[".css"] }).end("");
|
||||
return;
|
||||
}
|
||||
response.writeHead(200, {
|
||||
"cache-control": "no-store",
|
||||
"content-type": TYPES[".css"],
|
||||
});
|
||||
createReadStream(file).pipe(response);
|
||||
return;
|
||||
}
|
||||
|
||||
const file = join(root, normalize(url === "/" ? "/preview/index.html" : url));
|
||||
if (
|
||||
!(file.startsWith(root) && existsSync(file)) ||
|
||||
statSync(file).isDirectory()
|
||||
) {
|
||||
response.writeHead(404).end("not found");
|
||||
return;
|
||||
}
|
||||
response.writeHead(200, {
|
||||
"cache-control": "no-store",
|
||||
"content-type": TYPES[extname(file)] ?? "application/octet-stream",
|
||||
});
|
||||
createReadStream(file).pipe(response);
|
||||
}).listen(port, () => {
|
||||
console.log(`preview: http://localhost:${port}/`);
|
||||
});
|
||||
Reference in New Issue
Block a user