Skip to content

Commit cd149da

Browse files
committed
working with svelte 5
1 parent 1961d1d commit cd149da

File tree

9 files changed

+933
-601
lines changed

9 files changed

+933
-601
lines changed

package.json

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,19 +20,20 @@
2020
},
2121
"devDependencies": {
2222
"@playwright/test": "^1.29.1",
23-
"@sveltejs/adapter-auto": "^1.0.0",
24-
"@sveltejs/kit": "^1.20.4",
23+
"@sveltejs/adapter-auto": "^3.0.0",
24+
"@sveltejs/kit": "^2.5.27",
2525
"@sveltejs/package": "^1.0.2",
26+
"@sveltejs/vite-plugin-svelte": "^4.0.0",
2627
"@typescript-eslint/eslint-plugin": "^5.48.0",
2728
"@typescript-eslint/parser": "^5.48.0",
2829
"eslint": "^8.31.0",
2930
"eslint-plugin-svelte3": "^4.0.0",
30-
"svelte": "^4.0.0",
31-
"svelte-check": "^3.4.3",
31+
"svelte": "^5.0.0",
32+
"svelte-check": "^4.0.0",
3233
"tslib": "^2.4.1",
33-
"typescript": "^5.0.0",
34-
"vite": "^4.0.4",
35-
"vitest": "^0.26.3"
34+
"typescript": "^5.5.0",
35+
"vite": "^5.4.4",
36+
"vitest": "^1.0.0"
3637
},
3738
"dependencies": {
3839
"@resvg/resvg-js": "^2.2.0",

pnpm-lock.yaml

Lines changed: 782 additions & 466 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/lib/font-handling/index.ts

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,23 @@
1+
function isValidUrl(location: string): boolean {
2+
try {
3+
new URL(location);
4+
return true;
5+
} catch {
6+
return false;
7+
}
8+
}
19
// get local font and render as an array buffer
210
export const get_font_as_buffer = async (location: string) => {
3-
// check to make sure that we have a full URL
4-
const is_url = /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/
5-
if(!is_url.test(location)) console.error(`Font locations need to be specified with a full URL to work`)
11+
// check to make sure that we have a full URL
12+
if (!isValidUrl(location)) {
13+
console.error(
14+
`Font locations need to be specified with a full URL to work`,
15+
);
16+
throw new Error(`Invalid URL: ${location}`);
17+
}
618

7-
// the renderer
8-
const font = await(await fetch(location)).blob()
9-
const buf = await font.arrayBuffer()
10-
return buf
11-
}
19+
// the renderer
20+
const font = await (await fetch(location)).blob();
21+
const buf = await font.arrayBuffer();
22+
return buf;
23+
};

src/lib/processing/nodes_render.ts

Lines changed: 21 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,29 @@
11
// Take a svelte component, render it down to html, inline the styles
2-
// then return a set of satori ready nodes
3-
import pkg from 'juice'
4-
const { juiceResources } = pkg
5-
import { html as to_satori_nodes } from 'satori-html'
2+
// then return a set of satori ready nodes
3+
import pkg from "juice";
4+
const { juiceResources } = pkg;
5+
import { html as to_satori_nodes } from "satori-html";
6+
import { render } from "svelte/server";
67

78
export const nodes_render = async (
8-
Component: any,
9-
props?: {
10-
[key: string]: any
11-
},
9+
Component: any,
10+
props?: {
11+
[key: string]: any;
12+
},
1213
) => {
14+
// render the body and the head
15+
const { head, body } = render(Component, { props });
1316

14-
// convert the component into strings
15-
const { html: rawHtml, css, head } = Component.render(props)
16-
17-
// display an error if <svelte:head> is included in component
18-
if (head) {
19-
console.error(`<svelte:head> not supported while rendering image from component`)
20-
}
17+
const inline_html: string = await new Promise((resolve, reject) => {
18+
juiceResources(head ? head + body : body, {}, (err, result) =>
19+
err ? reject(err) : resolve(result),
20+
);
21+
});
2122

22-
// render our styles as inline styles through Juice
23-
// thank you svelte mailer for this piece of code
24-
const inline_html: string = await new Promise((resolve, reject) => {
25-
juiceResources(
26-
`${css.code ? `<style>${css.code}</style>` : ''}${rawHtml}`, {},
27-
(err, result) => (err ? reject(err) : resolve(result))
28-
)
29-
})
23+
console.log(inline_html);
3024

31-
// render satori friendly HTML and return it
32-
const satori_nodes = to_satori_nodes(inline_html)
25+
// render satori friendly HTML and return it
26+
const satori_nodes = to_satori_nodes(inline_html);
3327

34-
return satori_nodes
35-
}
28+
return satori_nodes;
29+
};

src/routes/+page.svelte

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<script lang="ts">
2-
let value: string = "hello"
3-
let second: string = "absolutely positioned"
2+
let value: string = $state("hello")
3+
let second: string = $state("absolutely positioned")
44
</script>
55

66
<main>

src/routes/image/+server.ts

Lines changed: 31 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,35 @@
1-
import { error } from '@sveltejs/kit'
2-
import type { RequestHandler } from './$types'
1+
import { error } from "@sveltejs/kit";
2+
import type { RequestHandler } from "./$types";
33

44
// import my test stuff
5-
import { image_from_component } from '$lib/index.js'
5+
import { image_from_component, type RenderOptions } from "$lib/index.js";
66

7+
import HelloWorld from "./HelloWorld.svelte";
78

8-
import HelloWorld from './HelloWorld.svelte'
9-
10-
export const GET: RequestHandler = (async ({url}) => {
11-
12-
try {
13-
const options: RenderOptions = {
14-
width: 1200,
15-
height: 600,
16-
props: {
17-
text: url.searchParams.get('text') ?? 'text not found',
18-
second: url.searchParams.get('second') ?? 'text not found'
19-
},
20-
fonts: [
21-
{
22-
name: 'Typewriter',
23-
url: `${url.origin}/TYPEWR__.TTF`,
24-
weight: 400,
25-
style: 'normal'
26-
}
27-
]
28-
}
29-
const image = await image_from_component(HelloWorld, options)
30-
const response = new Response(image)
31-
response.headers.append('content-type', 'image/png')
32-
return response
33-
} catch (e) {
34-
console.error(e)
35-
throw error(500, 'Error')
36-
}
37-
}) satisfies RequestHandler
9+
export const GET: RequestHandler = (async ({ url }) => {
10+
try {
11+
const options: RenderOptions = {
12+
width: 1200,
13+
height: 600,
14+
props: {
15+
text: url.searchParams.get("text") ?? "text not found",
16+
second: url.searchParams.get("second") ?? "text not found",
17+
},
18+
fonts: [
19+
{
20+
name: "Typewriter",
21+
url: `${url.origin}/TYPEWR__.TTF`,
22+
weight: 400,
23+
style: "normal",
24+
},
25+
],
26+
};
27+
const image = await image_from_component(HelloWorld, options);
28+
const response = new Response(image);
29+
response.headers.append("content-type", "image/png");
30+
return response;
31+
} catch (e) {
32+
console.error(e);
33+
error(500, "Error");
34+
}
35+
}) satisfies RequestHandler;

src/routes/image/HelloWorld.svelte

Lines changed: 42 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,49 @@
11
<script lang="ts">
2-
export let text: string
3-
export let second: string
2+
interface Props {
3+
text: string;
4+
second: string;
5+
}
6+
7+
let { text, second }: Props = $props();
48
</script>
59

610
<div id="container">
7-
<h1>
8-
{text} world!
9-
</h1>
10-
<div class="square">
11-
{second}
12-
</div>
11+
<h1>
12+
{text} world!
13+
</h1>
14+
<div class="square">
15+
{second}
16+
</div>
1317
</div>
1418

15-
1619
<style>
17-
#container {
18-
width: 1200px;
19-
height: 600px;
20-
display: flex;
21-
align-items: center;
22-
justify-content: center;
23-
position: relative;
24-
background: rgb(63,94,251);
25-
background: radial-gradient(circle, rgba(63,94,251,1) 0%, rgba(252,70,107,1) 100%);
26-
}
27-
h1 {
28-
color: red;
29-
font-size: 75px;
30-
31-
}
32-
.square {
33-
position: absolute;
34-
bottom: 1rem;
35-
left: 1rem;
36-
background: black;
37-
color: white;
38-
padding: 2rem;
39-
font-size: 50px;
40-
}
41-
</style>
20+
#container {
21+
width: 1200px;
22+
height: 600px;
23+
display: flex;
24+
align-items: center;
25+
justify-content: center;
26+
position: relative;
27+
background: rgb(63, 94, 251);
28+
background: radial-gradient(
29+
circle,
30+
rgba(63, 94, 251, 1) 0%,
31+
rgba(252, 70, 107, 1) 100%
32+
);
33+
}
34+
h1 {
35+
color: red;
36+
font-size: 75px;
37+
}
38+
.square {
39+
position: absolute;
40+
bottom: 1rem;
41+
left: 1rem;
42+
display: flex;
43+
background: black;
44+
color: white;
45+
padding: 2rem;
46+
font-size: 50px;
47+
}
48+
</style>
49+

svelte.config.js

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,18 @@
1-
import adapter from '@sveltejs/adapter-auto';
2-
import { vitePreprocess } from '@sveltejs/kit/vite';
1+
import adapter from "@sveltejs/adapter-auto";
2+
import { vitePreprocess } from "@sveltejs/vite-plugin-svelte";
33

44
/** @type {import('@sveltejs/kit').Config} */
55
const config = {
6-
// Consult https://kit.svelte.dev/docs/integrations#preprocessors
7-
// for more information about preprocessors
8-
preprocess: vitePreprocess(),
6+
// Consult https://kit.svelte.dev/docs/integrations#preprocessors
7+
// for more information about preprocessors
8+
preprocess: vitePreprocess(),
9+
compilerOptions: {
10+
css: "injected",
11+
},
912

10-
kit: {
11-
adapter: adapter()
12-
}
13+
kit: {
14+
adapter: adapter(),
15+
},
1316
};
1417

1518
export default config;

tsconfig.json

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
{
2-
"extends": "./.svelte-kit/tsconfig.json",
3-
"compilerOptions": {
4-
"moduleResolution": "NodeNext",
5-
"allowJs": true,
6-
"checkJs": true,
7-
"esModuleInterop": true,
8-
"forceConsistentCasingInFileNames": true,
9-
"resolveJsonModule": true,
10-
"skipLibCheck": true,
11-
"sourceMap": true,
12-
"strict": true
13-
}
14-
// Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias
15-
//
16-
// If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes
17-
// from the referenced tsconfig.json - TypeScript does not merge them in
2+
"extends": "./.svelte-kit/tsconfig.json",
3+
"compilerOptions": {
4+
"allowJs": true,
5+
"checkJs": true,
6+
"esModuleInterop": true,
7+
"forceConsistentCasingInFileNames": true,
8+
"resolveJsonModule": true,
9+
"skipLibCheck": true,
10+
"sourceMap": true,
11+
"strict": true,
12+
"moduleResolution": "bundler"
13+
}
14+
// Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias
15+
//
16+
// If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes
17+
// from the referenced tsconfig.json - TypeScript does not merge them in
1818
}

0 commit comments

Comments
 (0)