mirror of
https://github.com/LukeHagar/sveltekit-og.git
synced 2025-12-06 20:57:46 +00:00
Satori v0.0.43
This commit is contained in:
54
README.md
54
README.md
@@ -49,7 +49,7 @@ export const GET: RequestHandler = async () => {
|
|||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Then run `pnpm dev` and access localhost:5173/og, the React element will be rendered and responded as a PNG from that endpoint:
|
Then run `pnpm dev` and access localhost:5173/og, the api/route endpoint be rendered and responded as a PNG from that api/endpoint:
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
@@ -62,32 +62,53 @@ Read more about the API, supported features and check out the examples on Satori
|
|||||||
|
|
||||||
## API Reference
|
## API Reference
|
||||||
|
|
||||||
The package exposes an `ImageResponse` constructor, with the following options available:
|
The package exposes an `ImageResponse` and `componentToImageResponse` constructors, with the following options available:
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { ImageResponse } from '@ethercorps/sveltekit-og'
|
import {ImageResponse, componentToImageResponse} from '@ethercorps/sveltekit-og'
|
||||||
|
import {SvelteComponent} from "svelte";
|
||||||
|
|
||||||
// ...
|
// ...
|
||||||
new ImageResponse(
|
new ImageResponse(
|
||||||
element: string,
|
element : string,
|
||||||
options: {
|
options : {
|
||||||
width?: number = 1200
|
width ? : number = 1200
|
||||||
height?: number = 630
|
height ? : number = 630
|
||||||
fonts?: {
|
fonts ? : {
|
||||||
name: string,
|
name: string,
|
||||||
data: ArrayBuffer,
|
data: ArrayBuffer,
|
||||||
weight: number,
|
weight: number,
|
||||||
style: 'normal' | 'italic'
|
style: 'normal' | 'italic'
|
||||||
}[]
|
}[]
|
||||||
debug?: boolean = false
|
debug ? : boolean = false
|
||||||
graphemeImages?: Record<string, string>;
|
graphemeImages ? : Record<string, string>;
|
||||||
loadAdditionalAsset?: (languageCode: string, segment: string) => Promise<SatoriOptions["fonts"] | string | undefined>;
|
loadAdditionalAsset ? : (languageCode: string, segment: string) => Promise<SatoriOptions["fonts"] | string | undefined>;
|
||||||
// Options that will be passed to the HTTP response
|
// Options that will be passed to the HTTP response
|
||||||
status?: number = 200
|
status ? : number = 200
|
||||||
statusText?: string
|
statusText ? : string
|
||||||
headers?: Record<string, string>
|
headers ? : Record<string, string>
|
||||||
},
|
})
|
||||||
)
|
|
||||||
|
new componentToImageResponse(
|
||||||
|
component : typeof SvelteComponent,
|
||||||
|
props : {}, // All export let example inside prop dictionary
|
||||||
|
options : {
|
||||||
|
width ? : number = 1200
|
||||||
|
height ? : number = 630
|
||||||
|
fonts ? : {
|
||||||
|
name: string,
|
||||||
|
data: ArrayBuffer,
|
||||||
|
weight: number,
|
||||||
|
style: 'normal' | 'italic'
|
||||||
|
}[]
|
||||||
|
debug ? : boolean = false
|
||||||
|
graphemeImages ? : Record<string, string>;
|
||||||
|
loadAdditionalAsset ? : (languageCode: string, segment: string) => Promise<SatoriOptions["fonts"] | string | undefined>;
|
||||||
|
// Options that will be passed to the HTTP response
|
||||||
|
status ? : number = 200
|
||||||
|
statusText ? : string
|
||||||
|
headers ? : Record<string, string>
|
||||||
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
When running in production, these headers will be included by `@ethercorps/sveltekit-og`:
|
When running in production, these headers will be included by `@ethercorps/sveltekit-og`:
|
||||||
@@ -111,6 +132,7 @@ By default, `@ethercorps/sveltekit-og` only has the 'Noto Sans' font included. I
|
|||||||
This project will not be possible without the following projects:
|
This project will not be possible without the following projects:
|
||||||
|
|
||||||
- [Satori & @vercel/og](https://github.com/vercel/satori)
|
- [Satori & @vercel/og](https://github.com/vercel/satori)
|
||||||
|
- [Satori-Html](https://github.com/natemoo-re/satori-html)
|
||||||
- [Noto by Google Fonts](https://fonts.google.com/noto)
|
- [Noto by Google Fonts](https://fonts.google.com/noto)
|
||||||
- [Resvg.js](https://github.com/yisibl/resvg-js)
|
- [Resvg.js](https://github.com/yisibl/resvg-js)
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ethercorps/sveltekit-og",
|
"name": "@ethercorps/sveltekit-og",
|
||||||
"version": "0.1.1",
|
"version": "0.1.2",
|
||||||
"private": false,
|
"private": false,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite dev",
|
"dev": "vite dev",
|
||||||
@@ -35,8 +35,9 @@
|
|||||||
"type": "module",
|
"type": "module",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@resvg/resvg-wasm": "^2.1.0",
|
"@resvg/resvg-wasm": "^2.1.0",
|
||||||
"satori": "^0.0.42",
|
"satori": "^0.0.43",
|
||||||
"satori-html": "^0.2.0"
|
"satori-html": "^0.2.0",
|
||||||
|
"yoga-wasm-web": "0.1.2"
|
||||||
},
|
},
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"open graph image",
|
"open graph image",
|
||||||
|
|||||||
12
pnpm-lock.yaml
generated
12
pnpm-lock.yaml
generated
@@ -21,16 +21,18 @@ specifiers:
|
|||||||
tslib: ^2.4.0
|
tslib: ^2.4.0
|
||||||
typescript: ^4.8.4
|
typescript: ^4.8.4
|
||||||
vite: ^3.1.8
|
vite: ^3.1.8
|
||||||
|
yoga-wasm-web: 0.1.2
|
||||||
|
|
||||||
dependencies:
|
dependencies:
|
||||||
'@resvg/resvg-wasm': 2.1.0
|
'@resvg/resvg-wasm': 2.1.0
|
||||||
satori: 0.0.42
|
satori: 0.0.42
|
||||||
satori-html: 0.2.0
|
satori-html: 0.2.0
|
||||||
|
yoga-wasm-web: 0.1.2
|
||||||
|
|
||||||
devDependencies:
|
devDependencies:
|
||||||
'@playwright/test': 1.27.1
|
'@playwright/test': 1.27.1
|
||||||
'@sveltejs/adapter-auto': 1.0.0-next.84
|
'@sveltejs/adapter-auto': 1.0.0-next.84
|
||||||
'@sveltejs/kit': 1.0.0-next.520_svelte@3.52.0+vite@3.1.8
|
'@sveltejs/kit': 1.0.0-next.522_svelte@3.52.0+vite@3.1.8
|
||||||
'@sveltejs/package': 1.0.0-next.1_besnmoibwkhwtentvwuriss7pa
|
'@sveltejs/package': 1.0.0-next.1_besnmoibwkhwtentvwuriss7pa
|
||||||
'@typescript-eslint/eslint-plugin': 5.40.1_ukgdydjtebaxmxfqp5v5ulh64y
|
'@typescript-eslint/eslint-plugin': 5.40.1_ukgdydjtebaxmxfqp5v5ulh64y
|
||||||
'@typescript-eslint/parser': 5.40.1_z4bbprzjrhnsfa24uvmcbu7f5q
|
'@typescript-eslint/parser': 5.40.1_z4bbprzjrhnsfa24uvmcbu7f5q
|
||||||
@@ -256,8 +258,8 @@ packages:
|
|||||||
- supports-color
|
- supports-color
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/@sveltejs/kit/1.0.0-next.520_svelte@3.52.0+vite@3.1.8:
|
/@sveltejs/kit/1.0.0-next.522_svelte@3.52.0+vite@3.1.8:
|
||||||
resolution: {integrity: sha512-flroQQEwIHx6IEkskHGQ90Ri+gFCnAs4ZFRsG7QuTbuBu7XSeJNQs3J73pmBQoKp0pWnbwZ3YZMtwBJWF/I7qA==}
|
resolution: {integrity: sha512-dVVrRPbXlAut4vg8kbCeZOjUZnYB7ZvDKp/yAx8InpDF0P1bvUDlc++DXFeMBdXX8bakTA3NGonWnDjqslCsZw==}
|
||||||
engines: {node: '>=16.14'}
|
engines: {node: '>=16.14'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
requiresBuild: true
|
requiresBuild: true
|
||||||
@@ -2492,3 +2494,7 @@ packages:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@types/yoga-layout': 1.9.2
|
'@types/yoga-layout': 1.9.2
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/yoga-wasm-web/0.1.2:
|
||||||
|
resolution: {integrity: sha512-8SkgawHcA0RUbMrnhxbaQkZDBi8rMed8pQHixkFF9w32zGhAwZ9/cOHWlpYfr6RCx42Yp3siV45/jPEkJxsk6w==}
|
||||||
|
dev: false
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { html as toReactNode } from 'satori-html';
|
|||||||
import satori from 'satori';
|
import satori from 'satori';
|
||||||
import { Resvg, initWasm } from '@resvg/resvg-wasm';
|
import { Resvg, initWasm } from '@resvg/resvg-wasm';
|
||||||
import type { SatoriOptions } from 'satori';
|
import type { SatoriOptions } from 'satori';
|
||||||
|
import type {SvelteComponent} from "svelte";
|
||||||
|
|
||||||
const resSvgWasm = initWasm(fetch('https://sveltekit-og.ethercorps.io/resvg.wasm'));
|
const resSvgWasm = initWasm(fetch('https://sveltekit-og.ethercorps.io/resvg.wasm'));
|
||||||
const fontFile = await fetch('https://sveltekit-og.ethercorps.io/noto-sans.ttf');
|
const fontFile = await fetch('https://sveltekit-og.ethercorps.io/noto-sans.ttf');
|
||||||
@@ -27,7 +28,7 @@ export const ImageResponse = class {
|
|||||||
]
|
]
|
||||||
});
|
});
|
||||||
const pngData = new Resvg(svg, { fitTo: { mode: 'width', value: options.width } });
|
const pngData = new Resvg(svg, { fitTo: { mode: 'width', value: options.width } });
|
||||||
a.enqueue(await pngData.render().asPng());
|
a.enqueue(pngData.render().asPng());
|
||||||
a.close();
|
a.close();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -47,17 +48,22 @@ export const ImageResponse = class {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const componentToImageResponse = class {
|
export const componentToImageResponse = class {
|
||||||
constructor(component, props = {}, optionsByUser: ImageResponseOptions) {
|
constructor(component: typeof SvelteComponent, props = {}, optionsByUser: ImageResponseOptions) {
|
||||||
const SvelteRenderedMarkup = component.render(props);
|
const htmlTemplate = componentToMarkup(component, props)
|
||||||
let htmlTemplate = `${SvelteRenderedMarkup.html}`;
|
|
||||||
if (SvelteRenderedMarkup && SvelteRenderedMarkup.css && SvelteRenderedMarkup.css.code) {
|
|
||||||
htmlTemplate = `${SvelteRenderedMarkup.html}<style>${SvelteRenderedMarkup.css.code}</style>`;
|
|
||||||
}
|
|
||||||
return new ImageResponse(htmlTemplate, optionsByUser);
|
return new ImageResponse(htmlTemplate, optionsByUser);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ImageResponseOptions = ConstructorParameters<typeof Response>[1] & ImageOptions;
|
const componentToMarkup = (component: typeof SvelteComponent, props={}) => {
|
||||||
|
const SvelteRenderedMarkup = (component as any).render(props);
|
||||||
|
let htmlTemplate = `${SvelteRenderedMarkup.html}`;
|
||||||
|
if (SvelteRenderedMarkup && SvelteRenderedMarkup.css && SvelteRenderedMarkup.css.code) {
|
||||||
|
htmlTemplate = `${SvelteRenderedMarkup.html}<style>${SvelteRenderedMarkup.css.code}</style>`;
|
||||||
|
}
|
||||||
|
return htmlTemplate
|
||||||
|
}
|
||||||
|
|
||||||
|
type ImageResponseOptions = ConstructorParameters<typeof Response>[1] & ImageOptions;
|
||||||
|
|
||||||
type ImageOptions = {
|
type ImageOptions = {
|
||||||
width?: number;
|
width?: number;
|
||||||
|
|||||||
Reference in New Issue
Block a user