Reputation: 4324
I have a component, image.svelte
which renders an SVG file. On one route, say /image
, I want a page that includes that component rendered within an HTML document. But if you go to /image.svg
, I want just the SVG document by itself and I want the page to be served with Content-Type: image/svg+xml
.
I started by making creating a file like src/routes/image[ext]/+page.svelte
, but there doesn't seem to be a way to break out of src/app.html
.
Next I tried making two files, src/routes/image/+page.svelte
and src/routes/image.svg/+server.js
, but it doesn't seem to be possible to render components directly from a server-side script in SvelteKit.
So I'm at a loss and haven't find what I'm looking for in the docs.
Upvotes: 1
Views: 656
Reputation: 60428
I wanted to do something similar, and I found that the Svelte 5 API is a little different. Now, this is working for me:
/src/lib/image/image.svelte
<script>
let items = $state(["one", "two", "three"]);
</script>
<svg
version="1.1"
viewBox="0 0 200 200"
xmlns="http://www.w3.org/2000/svg"
>
<g>
{#each items as item, i}
<text x={i * 10} y={(i + 1) * 20}>{item}</text>
{/each}
</g>
</svg>
<style>
</style>
/src/routes/mysvg/+server.js
(no +page.svelte
necessary)
import { render } from 'svelte/server';
import image from "$lib/image/image.svelte";
/** @type {import('./$types').RequestHandler} */
export function GET() {
const { html } = render(image);
return new Response(html, {
headers: {
"Content-Type": "image/svg+xml",
"Content-Disposition": "inline;filename=image.svg",
},
});
}
Here's more about the API changes: Components are no longer classes
Upvotes: 0
Reputation: 4324
Turned out I was pretty close to the answer. I just needed to explore the svelte
module a little.
I accomplished what I wanted to do by creating one file, src/routes/image/+page.svelte
, for serving the HTML page with the SVG in it; and by creating a second file, src/routes/image.svg/+server.js
I pieced together from error messages and old documentation that importing svelte/register
no longer worked and I needed to import svelte/ssr
instead, and that svelte components have a .render()
method which returns an object with html
, css
, and head
properties. In my case I only needed the html
property.
This was the final result
import "svelte/ssr"
import Image from "$lib/Image/index.svelte"
export function GET() {
const {html} = Image.render({svg: true})
return new Response(html, {
headers: {
"Content-Type": "image/svg+xml",
"Content-Disposition": "inline;filename=image.svg"
}
})
}
Upvotes: 3