Skip to content

Commit

Permalink
Support Svelte modules (#58)
Browse files Browse the repository at this point in the history
so we can use $runes inside `*.svelte.js` files!

- create a compileModule plugin
- add a svelte module to the header’s logo
  • Loading branch information
mxdvl authored Dec 7, 2024
1 parent d98e5e5 commit a7f6130
Show file tree
Hide file tree
Showing 9 changed files with 156 additions and 67 deletions.
2 changes: 1 addition & 1 deletion deno.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@mxdvl/mononykus",
"version": "0.8.1",
"version": "0.8.2",
"license": "MIT",
"exports": "./src/build.ts",
"tasks": {
Expand Down
4 changes: 1 addition & 3 deletions src/_site/components/Header.svelte
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
<script>
import Logo from "./Logo.svelte";
const items = ["One", "Two", "Three"];
import Logo from "./Logo.island.svelte";
</script>

<header>
Expand Down
45 changes: 45 additions & 0 deletions src/_site/components/Logo.island.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<script>
import { claws } from "./claws.svelte.js";
let { colour = "black" } = $props();
$effect.pre(() => {
claws.read();
});
$effect(() => {
claws.write();
});
const points = [
[9, 3],
[15, 5],
[4, 12],
].map(([x, y]) => `${x},${y}`);
</script>

<svg
style={`--colour:${colour}`}
viewBox="0 0 16 16"
width={32}
data-claws={claws.count}
>
<path
onclick={claws.scratch}
d="
M{points[0]}
A20,20 0 0 0 {points[1]}
A20,20 0 0 1 {points[2]}
A20,20 0 0 0 {points[0]}
Z
"
/>
</svg>

<style>
svg {
fill: var(--colour);
stroke: var(--colour);
stroke-width: 1px;
stroke-linejoin: round;
}
</style>
29 changes: 0 additions & 29 deletions src/_site/components/Logo.svelte

This file was deleted.

27 changes: 27 additions & 0 deletions src/_site/components/claws.svelte.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
const key = "claw:count";

export const claws = $state({
count: 1,
scratch() {
console.log("scratchin");
claws.count++;
},
read() {
try {
console.log("reading");
const saved = parseInt(localStorage.getItem(key) ?? "NaN", 10);
if (!isNaN(saved)) {
claws.count = saved;
}
} catch {
// do nothing
}
},
write() {
try {
localStorage.setItem(key, String(claws.count));
} catch {
// do nothing
}
},
});
3 changes: 3 additions & 0 deletions src/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { build_routes } from "./esbuild_plugins/build_routes.ts";
import { svelte_components } from "./esbuild_plugins/svelte_components.ts";
import { create_handler } from "./server.ts";
import { write_islands } from "./esbuild_plugins/write_islands.ts";
import { svelte_modules } from "./esbuild_plugins/svelte_modules.ts";

function slashify(path: string): string {
return normalize(path + "/");
Expand Down Expand Up @@ -96,6 +97,7 @@ export const rebuild = async ({
entryPoints: await get_svelte_files({ site_dir, dir: "routes/" }),
write: false,
plugins: [
svelte_modules("server"),
svelte_components(site_dir, base, "server"),
...denoPlugins(),
build_routes,
Expand All @@ -108,6 +110,7 @@ export const rebuild = async ({
entryPoints: await get_svelte_files({ site_dir, dir: "components/" }),
write: false,
plugins: [
svelte_modules("client"),
svelte_components(site_dir, base, "client"),
...denoPlugins(),
write_islands,
Expand Down
30 changes: 30 additions & 0 deletions src/esbuild_plugins/svelte.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { VERSION, type Warning } from "svelte/compiler";

const SVELTE_IMPORTS = /(from|import) ['"](?:svelte)(\/?[\w\/-]*)['"]/g;

/** Convert `svelte/*` imports to `npm:[email protected]/*` */
export const specifiers = (code: string) =>
code.replaceAll(SVELTE_IMPORTS, `$1 'npm:svelte@${VERSION}$2'`);

/** From https://esbuild.github.io/plugins/#svelte-plugin */
export const convertMessage = (
path: string,
source: string,
{ message, start, end }: Warning,
) => {
if (!start || !end) {
return { text: message };
}
const lineText = source.split(/\r\n|\r|\n/g)[start.line - 1];
const lineEnd = start.line === end.line ? end.column : lineText?.length ?? 0;
return {
text: message,
location: {
file: path,
line: start.line,
column: start.column,
length: lineEnd - start.column,
lineText,
},
};
};
37 changes: 3 additions & 34 deletions src/esbuild_plugins/svelte_components.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { basename, dirname, normalize as normalise, resolve } from "@std/path";
import type { Plugin } from "esbuild";
import { compile, VERSION, type Warning } from "svelte/compiler";
import { compile, VERSION } from "svelte/compiler";
import type { Component } from "svelte";
import type {} from "esbuild";
import { convertMessage, specifiers } from "./svelte.ts";

const filter = /\.svelte$/;
const name = "mononykus/svelte";
const name = "mononykus/svelte:component";

/** force wrapping the actual component in a synthetic one */
const ssr_island = "?ssr_island";
Expand Down Expand Up @@ -33,35 +33,6 @@ const OneClaw = (
</style>
`;

const SVELTE_IMPORTS = /(from|import) ['"](?:svelte)(\/?[\w\/-]*)['"]/g;

/** Convert `svelte/*` imports to `npm:[email protected]/*` */
const specifiers = (code: string) =>
code.replaceAll(SVELTE_IMPORTS, `$1 'npm:svelte@${VERSION}$2'`);

/** From https://esbuild.github.io/plugins/#svelte-plugin */
const convertMessage = (
path: string,
source: string,
{ message, start, end }: Warning,
) => {
if (!start || !end) {
return { text: message };
}
const lineText = source.split(/\r\n|\r|\n/g)[start.line - 1];
const lineEnd = start.line === end.line ? end.column : lineText?.length ?? 0;
return {
text: message,
location: {
file: path,
line: start.line,
column: start.column,
length: lineEnd - start.column,
lineText,
},
};
};

export const svelte_components = (
site_dir: string,
base_path: string,
Expand Down Expand Up @@ -192,5 +163,3 @@ export const svelte_components = (
});
},
});

export { VERSION };
46 changes: 46 additions & 0 deletions src/esbuild_plugins/svelte_modules.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { basename } from "@std/path";
import type { Plugin } from "esbuild";
import { compileModule } from "svelte/compiler";
import type {} from "esbuild";
import { convertMessage, specifiers } from "./svelte.ts";

const filter = /\.svelte\.js$/;
const name = "mononykus/svelte:module";

export const svelte_modules = (generate: "client" | "server"): Plugin => ({
name,
setup(build) {
build.onLoad({ filter }, async ({ path }) => {
const source = await Deno.readTextFile(path);

try {
const { js, warnings } = compileModule(source, {
generate,
filename: basename(path),
});

console.log(js.code);

return {
contents: specifiers(js.code),
warnings: warnings.map((warning) =>
convertMessage(path, source, warning)
),
};
} catch (error) {
// technically a CompileError
{
return {
contents: "",
warnings: [
convertMessage(path, source, {
message: "[svelte] " + String(error),
code: "???",
}),
],
};
}
}
});
},
});

0 comments on commit a7f6130

Please sign in to comment.