feat(*): svelte 5 panel view sharing the gateway ui, obsidian theme, preview and tests
This commit is contained in:
+115
-34
@@ -1,40 +1,121 @@
|
||||
import esbuild from "esbuild";
|
||||
import path from "node:path";
|
||||
import process from "node:process";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import builtins from "builtin-modules";
|
||||
import esbuild from "esbuild";
|
||||
import sveltePlugin from "esbuild-svelte";
|
||||
|
||||
export const root = path.dirname(fileURLToPath(import.meta.url));
|
||||
export const LIB = path.resolve(root, "../beaver-gateway/ui/src/lib");
|
||||
|
||||
const EXTERNAL = [
|
||||
"obsidian",
|
||||
"electron",
|
||||
"@codemirror/autocomplete",
|
||||
"@codemirror/collab",
|
||||
"@codemirror/commands",
|
||||
"@codemirror/language",
|
||||
"@codemirror/lint",
|
||||
"@codemirror/search",
|
||||
"@codemirror/state",
|
||||
"@codemirror/view",
|
||||
"@lezer/common",
|
||||
"@lezer/highlight",
|
||||
"@lezer/lr",
|
||||
...builtins,
|
||||
];
|
||||
|
||||
const LIB_IMPORT = /^\$lib\//;
|
||||
const APP_IMPORT = /^\$app\//;
|
||||
const SONNER_IMPORT = /^svelte-sonner$/;
|
||||
const OBSIDIAN_IMPORT = /^obsidian$/;
|
||||
const BARE_IMPORT = /^[^./#]/;
|
||||
|
||||
function isExternal(specifier) {
|
||||
return (
|
||||
specifier.startsWith("node:") ||
|
||||
EXTERNAL.some(
|
||||
(name) => specifier === name || specifier.startsWith(`${name}/`)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// The panel is beaver-gateway's ``ui/src/lib``, compiled into this plugin.
|
||||
// Two rules keep it one bundle: ``$lib/*`` points at that directory, and
|
||||
// every bare import - svelte, bits-ui, the icons - resolves from this
|
||||
// plugin's node_modules, never from the gateway's, so there is exactly one
|
||||
// Svelte runtime. ``svelte-sonner`` becomes Obsidian notices; ``$app/*``
|
||||
// is SvelteKit-only and refused.
|
||||
export function sharedLib({ obsidian = "external" } = {}) {
|
||||
return {
|
||||
name: "beaver-shared-lib",
|
||||
setup(build) {
|
||||
build.onResolve({ filter: LIB_IMPORT }, (args) =>
|
||||
build.resolve(`./${args.path.slice("$lib/".length)}`, {
|
||||
kind: args.kind,
|
||||
pluginData: { pinned: true },
|
||||
resolveDir: LIB,
|
||||
})
|
||||
);
|
||||
build.onResolve({ filter: APP_IMPORT }, (args) => ({
|
||||
errors: [
|
||||
{
|
||||
text: `${args.path} is SvelteKit-only; the panel must not import it`,
|
||||
},
|
||||
],
|
||||
}));
|
||||
build.onResolve({ filter: SONNER_IMPORT }, () => ({
|
||||
path: path.join(root, "src/shims/sonner.ts"),
|
||||
}));
|
||||
build.onResolve({ filter: OBSIDIAN_IMPORT }, () =>
|
||||
obsidian === "external"
|
||||
? { external: true, path: "obsidian" }
|
||||
: { path: obsidian }
|
||||
);
|
||||
build.onResolve({ filter: BARE_IMPORT }, (args) => {
|
||||
if (args.pluginData?.pinned) {
|
||||
return;
|
||||
}
|
||||
if (isExternal(args.path)) {
|
||||
return { external: true, path: args.path };
|
||||
}
|
||||
return build.resolve(args.path, {
|
||||
kind: args.kind,
|
||||
pluginData: { pinned: true },
|
||||
resolveDir: root,
|
||||
});
|
||||
});
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export const svelte = () =>
|
||||
sveltePlugin({
|
||||
compilerOptions: { css: "injected", runes: true },
|
||||
filterWarnings: (warning) => !warning.filename?.includes("node_modules"),
|
||||
});
|
||||
|
||||
const prod = process.argv[2] === "production";
|
||||
|
||||
const ctx = await esbuild.context({
|
||||
entryPoints: ["src/main.ts"],
|
||||
bundle: true,
|
||||
external: [
|
||||
"obsidian",
|
||||
"electron",
|
||||
"@codemirror/autocomplete",
|
||||
"@codemirror/collab",
|
||||
"@codemirror/commands",
|
||||
"@codemirror/language",
|
||||
"@codemirror/lint",
|
||||
"@codemirror/search",
|
||||
"@codemirror/state",
|
||||
"@codemirror/view",
|
||||
"@lezer/common",
|
||||
"@lezer/highlight",
|
||||
"@lezer/lr",
|
||||
...builtins,
|
||||
],
|
||||
format: "cjs",
|
||||
target: "es2022",
|
||||
logLevel: "info",
|
||||
sourcemap: prod ? false : "inline",
|
||||
treeShaking: true,
|
||||
outfile: "main.js",
|
||||
minify: prod,
|
||||
});
|
||||
|
||||
if (prod) {
|
||||
await ctx.rebuild();
|
||||
await ctx.dispose();
|
||||
} else {
|
||||
await ctx.watch();
|
||||
if (process.argv[1] === fileURLToPath(import.meta.url)) {
|
||||
const ctx = await esbuild.context({
|
||||
bundle: true,
|
||||
conditions: ["svelte", "browser"],
|
||||
entryPoints: ["src/main.ts"],
|
||||
format: "cjs",
|
||||
logLevel: "info",
|
||||
mainFields: ["svelte", "browser", "module", "main"],
|
||||
minify: prod,
|
||||
outfile: "main.js",
|
||||
plugins: [sharedLib(), svelte()],
|
||||
sourcemap: prod ? false : "inline",
|
||||
target: "es2022",
|
||||
treeShaking: true,
|
||||
});
|
||||
if (prod) {
|
||||
await ctx.rebuild();
|
||||
await ctx.dispose();
|
||||
} else {
|
||||
await ctx.watch();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user