@ethercorps/sveltekit-og 4.3.0-next.6 → 4.3.0-next.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -11,6 +11,8 @@ export declare const ErrorCodes: {
11
11
  readonly RESVG_RENDER_FAILED: "RESVG_RENDER_FAILED";
12
12
  readonly SATORI_INIT_FAILED: "SATORI_INIT_FAILED";
13
13
  readonly EMOJI_LOAD_FAILED: "EMOJI_LOAD_FAILED";
14
+ readonly TAKUMI_INIT_FAILED: "TAKUMI_INIT_FAILED";
15
+ readonly TAKUMI_RENDER_FAILED: "TAKUMI_RENDER_FAILED";
14
16
  readonly UNKNOWN_ERROR: "UNKNOWN_ERROR";
15
17
  };
16
18
  /**
@@ -16,6 +16,8 @@ export const ErrorCodes = {
16
16
  RESVG_RENDER_FAILED: "RESVG_RENDER_FAILED",
17
17
  SATORI_INIT_FAILED: "SATORI_INIT_FAILED",
18
18
  EMOJI_LOAD_FAILED: "EMOJI_LOAD_FAILED",
19
+ TAKUMI_INIT_FAILED: "TAKUMI_INIT_FAILED",
20
+ TAKUMI_RENDER_FAILED: "TAKUMI_RENDER_FAILED",
19
21
  UNKNOWN_ERROR: "UNKNOWN_ERROR",
20
22
  };
21
23
  /**
@@ -0,0 +1,13 @@
1
+ import type { Component } from "svelte";
2
+ /**
3
+ * Renders a Svelte component to its server-side HTML parts.
4
+ *
5
+ * Shared by both rendering engines: the satori path feeds `body + head` into
6
+ * `satori-html`, while the takumi path passes an HTML string to its renderer.
7
+ * Components that need their styles inlined should use
8
+ * `<svelte:options css="injected" />` so the CSS lands in `head`.
9
+ */
10
+ export declare function renderComponentToHtml(component: Component<any>, props?: Record<string, unknown>): {
11
+ head: string;
12
+ body: string;
13
+ };
@@ -0,0 +1,13 @@
1
+ import { render } from "svelte/server";
2
+ import { handleSync, ErrorCodes } from "./error-handler.js";
3
+ /**
4
+ * Renders a Svelte component to its server-side HTML parts.
5
+ *
6
+ * Shared by both rendering engines: the satori path feeds `body + head` into
7
+ * `satori-html`, while the takumi path passes an HTML string to its renderer.
8
+ * Components that need their styles inlined should use
9
+ * `<svelte:options css="injected" />` so the CSS lands in `head`.
10
+ */
11
+ export function renderComponentToHtml(component, props = {}) {
12
+ return handleSync(() => render(component, { props }), ErrorCodes.VNODE_CREATION_FAILED, "Failed to render Svelte component to HTML");
13
+ }
@@ -1,9 +1,9 @@
1
- import { render } from "svelte/server";
2
1
  import { html } from "satori-html";
3
2
  import { handleSync, ErrorCodes } from "./error-handler.js";
3
+ import { renderComponentToHtml } from "./to-html.js";
4
4
  function svelteComponentToHTML(component, props = {}) {
5
5
  return handleSync(() => {
6
- const { body, head } = render(component, { props });
6
+ const { body, head } = renderComponentToHtml(component, props);
7
7
  return html(body + head);
8
8
  }, ErrorCodes.VNODE_CREATION_FAILED, "Failed to render Svelte component to HTML");
9
9
  }
@@ -6,14 +6,28 @@ import { formatBytes } from "./helpers/utils.js";
6
6
  export class ImageResponse extends Response {
7
7
  constructor(element, options, props) {
8
8
  const extended_options = Object.assign({ ...DEFAULT_OPTIONS }, options);
9
+ const isDebug = extended_options.debug ?? false;
10
+ const log = createLogger(isDebug);
11
+ log.debug("ImageResponse created");
9
12
  const create_image_function = extended_options.format === "png" ? createPng : createSvg;
10
13
  const body = new ReadableStream({
11
14
  async start(controller) {
12
- const buffer = await create_image_function(element, extended_options, {
13
- props,
14
- });
15
- controller.enqueue(buffer);
16
- controller.close();
15
+ try {
16
+ const buffer = (await handleAsync(() => create_image_function(element, extended_options, {
17
+ props,
18
+ }), ErrorCodes.UNKNOWN_ERROR, `Failed to generate ${extended_options.format?.toUpperCase()}`));
19
+ log.debug(buffer.length.toLocaleString());
20
+ log.info(`Generated ${extended_options.format.toUpperCase()}: ${formatBytes(buffer.length)}`);
21
+ controller.enqueue(buffer);
22
+ controller.close();
23
+ }
24
+ catch (error) {
25
+ const err = error instanceof ImageResponseError
26
+ ? error
27
+ : new ImageResponseError(error instanceof Error ? error.message : String(error), ErrorCodes.UNKNOWN_ERROR, error instanceof Error ? error : new Error(String(error)));
28
+ log.error("Failed to create image response:", err.message);
29
+ controller.error(err);
30
+ }
17
31
  },
18
32
  });
19
33
  super(body, {
@@ -0,0 +1,6 @@
1
+ declare namespace _default {
2
+ export let initWasmPromise: Promise<import("takumi-js/wasm", { with: { "resolution-mode": "require" } }).InitOutput>;
3
+ export { Renderer };
4
+ }
5
+ export default _default;
6
+ import { Renderer } from "takumi-js/wasm";
@@ -0,0 +1,16 @@
1
+ import { init, Renderer } from "takumi-js/wasm";
2
+
3
+ // Worker-like runtimes (Cloudflare Workers, Vercel Edge) can't compile WASM at
4
+ // runtime, so we hand the wasm-bindgen `init` a pre-compiled module. Importing
5
+ // the vendored takumi.wasm with `?module` makes the consumer bundler emit a real
6
+ // CompiledWasm module — mirrors providers/resvg/edge.js and providers/satori/edge.js.
7
+ export default {
8
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
9
+ // @ts-ignore
10
+ initWasmPromise: init({
11
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
12
+ // @ts-ignore
13
+ module_or_path: import("./takumi.wasm?module").then((r) => r.default || r),
14
+ }),
15
+ Renderer,
16
+ };
@@ -0,0 +1,6 @@
1
+ declare namespace _default {
2
+ export let initWasmPromise: Promise<void>;
3
+ export { Renderer };
4
+ }
5
+ export default _default;
6
+ import { Renderer } from "takumi-js/node";
@@ -0,0 +1,10 @@
1
+ import { Renderer } from "takumi-js/node";
2
+
3
+ /**
4
+ * Native Node.js backend (@takumi-rs/core). The renderer is a native addon, so
5
+ * there is no WASM to initialize — construction is synchronous.
6
+ * */
7
+ export default {
8
+ initWasmPromise: Promise.resolve(),
9
+ Renderer,
10
+ };
@@ -0,0 +1,26 @@
1
+ import type { FontDetails } from "takumi-js/node";
2
+ import { BaseFont } from "../fonts.js";
3
+ import type { MayBePromise } from "../types.js";
4
+ /** Font bytes Takumi accepts for registration. */
5
+ type ByteBuf = Uint8Array | ArrayBuffer | Buffer;
6
+ /**
7
+ * A Takumi-native font descriptor. `data` may be the bytes directly or a lazy
8
+ * loader returning them — matching `takumi-js`'s own font option shape.
9
+ */
10
+ export interface TakumiFontDescriptor {
11
+ name?: string;
12
+ data: ByteBuf | (() => MayBePromise<ByteBuf>);
13
+ weight?: number;
14
+ style?: FontDetails["style"];
15
+ }
16
+ /**
17
+ * Accepted font inputs on the Takumi path: this library's `GoogleFont` /
18
+ * `CustomFont` helpers (any `BaseFont`) or a raw Takumi descriptor.
19
+ */
20
+ export type TakumiFontInput = BaseFont | TakumiFontDescriptor;
21
+ /**
22
+ * Resolves mixed font inputs into Takumi `FontDetails` ready for
23
+ * `renderer.registerFont`. Loaders run in parallel.
24
+ */
25
+ export declare function resolveTakumiFonts(fonts: TakumiFontInput[]): Promise<FontDetails[]>;
26
+ export {};
@@ -0,0 +1,18 @@
1
+ import { BaseFont } from "../fonts.js";
2
+ import { handleAsync, ErrorCodes } from "../helpers/error-handler.js";
3
+ async function normalizeFont(font) {
4
+ if (font instanceof BaseFont) {
5
+ // GoogleFont/CustomFont: the `data` getter lazily loads (and caches) bytes.
6
+ const data = (await font.data);
7
+ return { name: font.name, data, weight: font.weight, style: font.style };
8
+ }
9
+ const data = typeof font.data === "function" ? await font.data() : await font.data;
10
+ return { name: font.name, data, weight: font.weight, style: font.style };
11
+ }
12
+ /**
13
+ * Resolves mixed font inputs into Takumi `FontDetails` ready for
14
+ * `renderer.registerFont`. Loaders run in parallel.
15
+ */
16
+ export async function resolveTakumiFonts(fonts) {
17
+ return handleAsync(() => Promise.all(fonts.map(normalizeFont)), ErrorCodes.FONT_LOAD_FAILED, "Failed to resolve fonts for Takumi");
18
+ }
@@ -0,0 +1,9 @@
1
+ import type { Component, ComponentProps } from "svelte";
2
+ import type { TakumiImageResponseOptions } from "./types.js";
3
+ /**
4
+ * Generates an Open Graph image with the Takumi engine and returns it as a
5
+ * `Response`. Accepts an HTML string or a Svelte component (with props).
6
+ */
7
+ export declare class ImageResponse<T extends string | Component<any>> extends Response {
8
+ constructor(element: T, options?: TakumiImageResponseOptions, props?: T extends Component<any> ? ComponentProps<T> : never);
9
+ }
@@ -0,0 +1,62 @@
1
+ import { createTakumiImage } from "./render.js";
2
+ import { createLogger } from "../helpers/logger.js";
3
+ import { handleAsync, ImageResponseError, ErrorCodes } from "../helpers/error-handler.js";
4
+ import { formatBytes } from "../helpers/utils.js";
5
+ const DEFAULT_OPTIONS = {
6
+ width: 1200,
7
+ height: 630,
8
+ format: "png",
9
+ emoji: "twemoji",
10
+ debug: false,
11
+ };
12
+ const CONTENT_TYPES = {
13
+ png: "image/png",
14
+ jpeg: "image/jpeg",
15
+ webp: "image/webp",
16
+ ico: "image/x-icon",
17
+ raw: "application/octet-stream",
18
+ svg: "image/svg+xml",
19
+ };
20
+ /**
21
+ * Generates an Open Graph image with the Takumi engine and returns it as a
22
+ * `Response`. Accepts an HTML string or a Svelte component (with props).
23
+ */
24
+ export class ImageResponse extends Response {
25
+ constructor(element, options, props) {
26
+ const opts = { ...DEFAULT_OPTIONS, ...options };
27
+ const log = createLogger(opts.debug);
28
+ log.debug("Takumi ImageResponse created");
29
+ const format = opts.format;
30
+ const body = new ReadableStream({
31
+ async start(controller) {
32
+ try {
33
+ const output = await handleAsync(() => createTakumiImage(element, opts, props), ErrorCodes.UNKNOWN_ERROR, `Failed to generate ${format.toUpperCase()}`);
34
+ // renderSvg returns a string; raster formats return bytes. A
35
+ // Response body stream must emit Uint8Array chunks.
36
+ const bytes = typeof output === "string" ? new TextEncoder().encode(output) : output;
37
+ log.info(`Generated ${format.toUpperCase()}: ${formatBytes(bytes.byteLength)}`);
38
+ controller.enqueue(bytes);
39
+ controller.close();
40
+ }
41
+ catch (error) {
42
+ const err = error instanceof ImageResponseError
43
+ ? error
44
+ : new ImageResponseError(error instanceof Error ? error.message : String(error), ErrorCodes.UNKNOWN_ERROR, error instanceof Error ? error : new Error(String(error)));
45
+ log.error("Failed to create Takumi image response:", err.message);
46
+ controller.error(err);
47
+ }
48
+ },
49
+ });
50
+ super(body, {
51
+ headers: {
52
+ "Content-Type": CONTENT_TYPES[format],
53
+ "Cache-Control": opts.debug
54
+ ? "no-cache, no-store"
55
+ : "public, immutable, no-transform, max-age=31536000",
56
+ ...opts.headers,
57
+ },
58
+ status: opts.status || 200,
59
+ statusText: opts.statusText || "Success",
60
+ });
61
+ }
62
+ }
@@ -0,0 +1,5 @@
1
+ export { ImageResponse } from "./image-response.js";
2
+ export type { TakumiImageResponseOptions, TakumiImageOptions, TakumiResponseOptions, TakumiFormat, } from "./types.js";
3
+ export type { TakumiFontInput, TakumiFontDescriptor } from "./fonts.js";
4
+ export { resolveTakumiFonts } from "./fonts.js";
5
+ export { GoogleFont, CustomFont, loadGoogleFont } from "../fonts.js";
@@ -0,0 +1,4 @@
1
+ export { ImageResponse } from "./image-response.js";
2
+ export { resolveTakumiFonts } from "./fonts.js";
3
+ // Re-export the font helpers so the Takumi path is usable from a single import.
4
+ export { GoogleFont, CustomFont, loadGoogleFont } from "../fonts.js";
@@ -0,0 +1,7 @@
1
+ import type { Component } from "svelte";
2
+ import type { TakumiImageOptions } from "./types.js";
3
+ /**
4
+ * Renders an HTML string or Svelte component to image bytes (or an SVG string)
5
+ * using a cached, font-registered Takumi renderer for the current runtime.
6
+ */
7
+ export declare function createTakumiImage(element: string | Component, options: TakumiImageOptions, props?: Record<string, unknown>): Promise<Uint8Array | string>;
@@ -0,0 +1,36 @@
1
+ import { render as takumiRender, renderSvg } from "takumi-js";
2
+ import { renderComponentToHtml } from "../helpers/to-html.js";
3
+ import { useTakumiRenderer, registerTakumiFonts } from "./renderer.js";
4
+ import { resolveTakumiFonts } from "./fonts.js";
5
+ import { createLogger } from "../helpers/logger.js";
6
+ import { handleAsync, handleSync, ErrorCodes } from "../helpers/error-handler.js";
7
+ function elementToHtml(element, props) {
8
+ if (typeof element === "string")
9
+ return element.replaceAll("\n", "").trim();
10
+ // Takumi reads inline `style`/`<style>`; `head` carries CSS injected via
11
+ // `<svelte:options css="injected" />`, so it goes first.
12
+ const { head, body } = renderComponentToHtml(element, props);
13
+ return head + body;
14
+ }
15
+ /**
16
+ * Renders an HTML string or Svelte component to image bytes (or an SVG string)
17
+ * using a cached, font-registered Takumi renderer for the current runtime.
18
+ */
19
+ export async function createTakumiImage(element, options, props) {
20
+ const log = createLogger(options.debug ?? false);
21
+ const html = handleSync(() => elementToHtml(element, props), ErrorCodes.VNODE_CREATION_FAILED, "Failed to create HTML for Takumi");
22
+ const renderer = await useTakumiRenderer(options.debug);
23
+ if (options.fonts?.length) {
24
+ const fonts = await resolveTakumiFonts(options.fonts);
25
+ await registerTakumiFonts(renderer, fonts);
26
+ }
27
+ const { width, height, format = "png", quality, stylesheets, emoji } = options;
28
+ // `renderer` is typed as the native Renderer; on edge it's the wasm Renderer,
29
+ // which is structurally compatible for takumi-js's managed render.
30
+ const shared = { renderer: renderer, width, height, stylesheets, emoji };
31
+ log.debug(`Rendering ${format.toUpperCase()} with Takumi`);
32
+ if (format === "svg") {
33
+ return handleAsync(() => renderSvg(html, shared), ErrorCodes.TAKUMI_RENDER_FAILED, "Failed to render SVG with Takumi");
34
+ }
35
+ return handleAsync(() => takumiRender(html, { ...shared, format, quality }), ErrorCodes.TAKUMI_RENDER_FAILED, "Failed to render image with Takumi");
36
+ }
@@ -0,0 +1,10 @@
1
+ import type { Renderer as NodeRenderer, FontDetails } from "takumi-js/node";
2
+ /** Either backend's Renderer; both expose `render`/`renderSvg`/`registerFont`. */
3
+ export type TakumiRenderer = NodeRenderer;
4
+ /** Lazily creates and caches the Takumi renderer for the current runtime. */
5
+ export declare function useTakumiRenderer(debug?: boolean): Promise<TakumiRenderer>;
6
+ /**
7
+ * Registers each font on the renderer once. Keyed by name/weight/style so the
8
+ * same face isn't re-registered across requests.
9
+ */
10
+ export declare function registerTakumiFonts(renderer: TakumiRenderer, fonts: FontDetails[]): Promise<void>;
@@ -0,0 +1,39 @@
1
+ import { isEdgeLight, isWorkerd } from "std-env";
2
+ import { createLogger } from "../helpers/logger.js";
3
+ import { handleAsync, ErrorCodes } from "../helpers/error-handler.js";
4
+ // Keep one renderer alive across requests (mirrors satori/resvg instance reuse
5
+ // and Takumi's own global renderer). Fonts registered on it accumulate, so we
6
+ // track which have already been registered to avoid duplicate work.
7
+ let rendererPromise;
8
+ const registeredFontKeys = new Set();
9
+ async function initRenderer(debug) {
10
+ const log = createLogger(debug);
11
+ const isWorkerLikeRuntime = isEdgeLight || isWorkerd;
12
+ log.info(`Detected runtime: ${isWorkerLikeRuntime ? "Edge Light or Workerd" : "Node.js"}`);
13
+ // Keep the imports as direct ternary expressions so the bundler can statically
14
+ // emit the wasm chunk for the edge build (see providers/takumi/edge.js).
15
+ const moduleImport = isWorkerLikeRuntime
16
+ ? import("../providers/takumi/edge.js")
17
+ : import("../providers/takumi/node.js");
18
+ const provider = (await handleAsync(() => moduleImport.then((m) => m.default), ErrorCodes.TAKUMI_INIT_FAILED, "Failed to import Takumi renderer module"));
19
+ await handleAsync(() => provider.initWasmPromise, ErrorCodes.TAKUMI_INIT_FAILED, "Failed to initialize Takumi WASM");
20
+ return new provider.Renderer();
21
+ }
22
+ /** Lazily creates and caches the Takumi renderer for the current runtime. */
23
+ export async function useTakumiRenderer(debug = false) {
24
+ rendererPromise ??= initRenderer(debug);
25
+ return rendererPromise;
26
+ }
27
+ /**
28
+ * Registers each font on the renderer once. Keyed by name/weight/style so the
29
+ * same face isn't re-registered across requests.
30
+ */
31
+ export async function registerTakumiFonts(renderer, fonts) {
32
+ for (const font of fonts) {
33
+ const key = `${font.name ?? "unnamed"}-${font.weight ?? "auto"}-${font.style ?? "normal"}`;
34
+ if (registeredFontKeys.has(key))
35
+ continue;
36
+ await handleAsync(() => renderer.registerFont(font), ErrorCodes.FONT_LOAD_FAILED, `Failed to register Takumi font: ${key}`);
37
+ registeredFontKeys.add(key);
38
+ }
39
+ }
@@ -0,0 +1,64 @@
1
+ import type { EmojiType } from "takumi-js/helpers/emoji";
2
+ import type { OutputFormat } from "takumi-js/node";
3
+ import type { TakumiFontInput } from "./fonts.js";
4
+ /** Static output formats Takumi can encode, plus vector `svg`. */
5
+ export type TakumiFormat = OutputFormat | "svg";
6
+ export type TakumiImageOptions = {
7
+ /**
8
+ * Width of the image.
9
+ * @default 1200
10
+ * */
11
+ width?: number;
12
+ /**
13
+ * Height of the image.
14
+ * @default 630
15
+ * */
16
+ height?: number;
17
+ /**
18
+ * Output format.
19
+ * @default png
20
+ * */
21
+ format?: TakumiFormat;
22
+ /**
23
+ * Quality for lossy formats (jpeg, lossy webp), 0-100.
24
+ * */
25
+ quality?: number;
26
+ /**
27
+ * Fonts to register. Accepts this library's `GoogleFont`/`CustomFont`
28
+ * helpers or raw Takumi font descriptors. If omitted, Takumi's built-in
29
+ * sans-serif is used.
30
+ * */
31
+ fonts?: TakumiFontInput[];
32
+ /**
33
+ * Extra CSS stylesheets applied before rendering.
34
+ * */
35
+ stylesheets?: string[];
36
+ /**
37
+ * Emoji provider, or `"from-font"` to source emoji glyphs from loaded fonts.
38
+ * @default twemoji
39
+ * */
40
+ emoji?: EmojiType | "from-font";
41
+ /**
42
+ * Enable debug logging.
43
+ * @default false
44
+ * */
45
+ debug?: boolean;
46
+ };
47
+ export type TakumiResponseOptions = {
48
+ /**
49
+ * Response status code.
50
+ * @default 200
51
+ * */
52
+ status?: number;
53
+ /**
54
+ * Response status text.
55
+ * @default Success
56
+ * */
57
+ statusText?: string;
58
+ /**
59
+ * Response headers.
60
+ * */
61
+ headers?: Record<string, string>;
62
+ };
63
+ /** Options for the Takumi `ImageResponse`. */
64
+ export type TakumiImageResponseOptions = TakumiImageOptions & TakumiResponseOptions;
@@ -0,0 +1 @@
1
+ export {};
package/package.json CHANGED
@@ -1,114 +1,131 @@
1
1
  {
2
- "name": "@ethercorps/sveltekit-og",
3
- "version": "4.3.0-next.6",
4
- "license": "MIT",
5
- "homepage": "https://sveltekit-og.dev",
6
- "repository": "github:ethercorps/sveltekit-og",
7
- "funding": "https://github.com/sponsors/ethercorps",
8
- "author": "Shivam Meena <https://github.com/theetherGit>",
9
- "description": "Dynamically generate Open Graph images from an HTML, CSS template or Svelte component using fast and efficient conversion from HTML > SVG > PNG",
10
- "contributors": [
11
- {
12
- "name": "Shivam Meena",
13
- "github": "https://github.com/theetherGit"
14
- },
15
- {
16
- "name": "Jason",
17
- "github": "https://github.com/jasongitmail"
18
- },
19
- {
20
- "name": "Mihkel Martin Kasterpalu",
21
- "github": "https://github.com/MihkelMK"
22
- },
23
- {
24
- "name": "Luke Parke",
25
- "github": "https://github.com/LukasParke"
26
- },
27
- {
28
- "name": "Willow (GHOST)",
29
- "github": "https://github.com/ghostdevv"
30
- },
31
- {
32
- "name": "Minseo Lee",
33
- "github": "https://github.com/quiple"
34
- }
35
- ],
36
- "exports": {
37
- ".": {
38
- "types": "./dist/index.d.ts",
39
- "svelte": "./dist/index.js",
40
- "import": "./dist/index.js"
41
- },
42
- "./fonts": {
43
- "types": "./dist/fonts.d.ts",
44
- "import": "./dist/fonts.js"
45
- },
46
- "./plugin": {
47
- "types": "./dist/plugin.d.ts",
48
- "import": "./dist/plugin.js"
49
- }
50
- },
51
- "files": [
52
- "dist",
53
- "!dist/**/*.test.*",
54
- "!dist/**/*.spec.*"
55
- ],
56
- "devDependencies": {
57
- "@eslint/compat": "^2.0.3",
58
- "@eslint/js": "^9.39.3",
59
- "@sveltejs/adapter-vercel": "^5.10.3",
60
- "@sveltejs/kit": "^2.53.4",
61
- "@sveltejs/package": "^2.5.7",
62
- "@sveltejs/vite-plugin-svelte": "^4.0.4",
63
- "@types/node": "^24.11.0",
64
- "@typescript-eslint/eslint-plugin": "^5.62.0",
65
- "@typescript-eslint/parser": "^5.62.0",
66
- "css-tree": "^2.3.1",
67
- "eslint": "^8.57.1",
68
- "eslint-config-prettier": "^8.10.2",
69
- "eslint-plugin-oxlint": "^1.55.0",
70
- "eslint-plugin-svelte": "^2.46.1",
71
- "globals": "^16.5.0",
72
- "oxlint": "^1.55.0",
73
- "prettier": "^3.8.1",
74
- "prettier-plugin-svelte": "^3.5.1",
75
- "prettier-plugin-tailwindcss": "^0.6.14",
76
- "publint": "^0.1.16",
77
- "rollup-plugin-visualizer": "^5.14.0",
78
- "svelte": "^5.53.10",
79
- "svelte-check": "^4.4.5",
80
- "tslib": "^2.8.1",
81
- "typescript": "^5.9.3",
82
- "typescript-eslint": "^8.57.0",
83
- "vite": "^5.4.21",
84
- "vitest": "^1.6.1"
85
- },
86
- "main": "./dist/index.js",
87
- "svelte": "./dist/index.js",
88
- "types": "./dist/index.d.ts",
89
- "type": "module",
90
- "dependencies": {
91
- "@resvg/resvg-wasm": "^2.6.2",
92
- "satori": "^0.25.0",
93
- "satori-html": "0.3.2",
94
- "std-env": "^4.1.0",
95
- "unwasm": "^0.5.3"
96
- },
97
- "peerDependencies": {
98
- "@sveltejs/kit": ">=2.0.0"
99
- },
100
- "scripts": {
101
- "dev": "vite dev",
102
- "build": "vite build && npm run package",
103
- "build:examples": "pnpm -F \"./examples/**\" --parallel --color build",
104
- "check:examples": "pnpm install -r",
105
- "preview": "vite preview",
106
- "package": "svelte-kit sync && svelte-package && publint",
107
- "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
108
- "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
109
- "test": "vitest",
110
- "lint": "oxlint . && eslint .",
111
- "format": "prettier --plugin-search-dir . --write .",
112
- "publishBeta": "npm publish --tag beta"
113
- }
114
- }
2
+ "name": "@ethercorps/sveltekit-og",
3
+ "version": "4.3.0-next.7",
4
+ "license": "MIT",
5
+ "homepage": "https://sveltekit-og.dev",
6
+ "repository": "github:ethercorps/sveltekit-og",
7
+ "funding": "https://github.com/sponsors/ethercorps",
8
+ "author": "Shivam Meena <https://github.com/theetherGit>",
9
+ "description": "Dynamically generate Open Graph images from an HTML, CSS template or Svelte component using fast and efficient conversion from HTML > SVG > PNG",
10
+ "contributors": [
11
+ {
12
+ "name": "Shivam Meena",
13
+ "github": "https://github.com/theetherGit"
14
+ },
15
+ {
16
+ "name": "Jason",
17
+ "github": "https://github.com/jasongitmail"
18
+ },
19
+ {
20
+ "name": "Mihkel Martin Kasterpalu",
21
+ "github": "https://github.com/MihkelMK"
22
+ },
23
+ {
24
+ "name": "Luke Parke",
25
+ "github": "https://github.com/LukasParke"
26
+ },
27
+ {
28
+ "name": "Willow (GHOST)",
29
+ "github": "https://github.com/ghostdevv"
30
+ },
31
+ {
32
+ "name": "Minseo Lee",
33
+ "github": "https://github.com/quiple"
34
+ }
35
+ ],
36
+ "scripts": {
37
+ "dev": "vite dev",
38
+ "build": "vite build && npm run package",
39
+ "build:examples": "pnpm -F \"./examples/**\" --parallel --color build",
40
+ "check:examples": "pnpm install -r",
41
+ "preview": "vite preview",
42
+ "package": "svelte-kit sync && svelte-package && publint",
43
+ "prepublishOnly": "pnpm run package",
44
+ "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
45
+ "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
46
+ "test": "vitest",
47
+ "bench": "vitest bench --run",
48
+ "bench:save": "vitest bench --run --outputJson benchmarks/baseline.json",
49
+ "bench:compare": "vitest bench --run --compare benchmarks/baseline.json",
50
+ "bench:snapshot": "node scripts/bench-snapshot.mjs",
51
+ "lint": "oxlint . && eslint .",
52
+ "format": "prettier --plugin-search-dir . --write .",
53
+ "publishBeta": "npm publish --tag beta"
54
+ },
55
+ "exports": {
56
+ ".": {
57
+ "types": "./dist/index.d.ts",
58
+ "svelte": "./dist/index.js",
59
+ "import": "./dist/index.js"
60
+ },
61
+ "./fonts": {
62
+ "types": "./dist/fonts.d.ts",
63
+ "import": "./dist/fonts.js"
64
+ },
65
+ "./takumi": {
66
+ "types": "./dist/takumi/index.d.ts",
67
+ "svelte": "./dist/takumi/index.js",
68
+ "import": "./dist/takumi/index.js"
69
+ },
70
+ "./plugin": {
71
+ "types": "./dist/plugin.d.ts",
72
+ "import": "./dist/plugin.js"
73
+ }
74
+ },
75
+ "files": [
76
+ "dist",
77
+ "!dist/**/*.test.*",
78
+ "!dist/**/*.spec.*"
79
+ ],
80
+ "devDependencies": {
81
+ "@eslint/compat": "^2.0.3",
82
+ "@eslint/js": "^9.39.3",
83
+ "@sveltejs/adapter-vercel": "^5.10.3",
84
+ "@sveltejs/kit": "^2.53.4",
85
+ "@sveltejs/package": "^2.5.7",
86
+ "@sveltejs/vite-plugin-svelte": "^4.0.4",
87
+ "@types/node": "^24.11.0",
88
+ "@typescript-eslint/eslint-plugin": "^5.62.0",
89
+ "@typescript-eslint/parser": "^5.62.0",
90
+ "css-tree": "^2.3.1",
91
+ "eslint": "^8.57.1",
92
+ "eslint-config-prettier": "^8.10.2",
93
+ "eslint-plugin-oxlint": "^1.55.0",
94
+ "eslint-plugin-svelte": "^2.46.1",
95
+ "globals": "^16.5.0",
96
+ "oxlint": "^1.55.0",
97
+ "prettier": "^3.8.1",
98
+ "prettier-plugin-svelte": "^3.5.1",
99
+ "prettier-plugin-tailwindcss": "^0.6.14",
100
+ "publint": "^0.1.16",
101
+ "rollup-plugin-visualizer": "^5.14.0",
102
+ "svelte": "^5.53.10",
103
+ "svelte-check": "^4.4.5",
104
+ "tslib": "^2.8.1",
105
+ "typescript": "^5.9.3",
106
+ "typescript-eslint": "^8.57.0",
107
+ "vite": "^5.4.21",
108
+ "takumi-js": "2.0.0-beta.14",
109
+ "vitest": "^1.6.1"
110
+ },
111
+ "main": "./dist/index.js",
112
+ "svelte": "./dist/index.js",
113
+ "types": "./dist/index.d.ts",
114
+ "type": "module",
115
+ "dependencies": {
116
+ "@resvg/resvg-wasm": "^2.6.2",
117
+ "satori": "^0.25.0",
118
+ "satori-html": "0.3.2",
119
+ "std-env": "^4.1.0",
120
+ "unwasm": "^0.5.3"
121
+ },
122
+ "peerDependencies": {
123
+ "@sveltejs/kit": ">=2.0.0",
124
+ "takumi-js": "^2.0.0-beta.14"
125
+ },
126
+ "peerDependenciesMeta": {
127
+ "takumi-js": {
128
+ "optional": true
129
+ }
130
+ }
131
+ }