sveltesveltekitsvelte-component

SvelteKit: SVG on HTML page, or as standalone SVG file depending on route


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.


Solution

  • 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"
            }
        })
    }