satori-cf 0.0.1
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.
- package/README.md +37 -0
- package/dist/assets/emoji.d.ts +15 -0
- package/dist/assets/emoji.d.ts.map +1 -0
- package/dist/assets/font.d.ts +10 -0
- package/dist/assets/font.d.ts.map +1 -0
- package/dist/core/yoga.d.ts +12 -0
- package/dist/core/yoga.d.ts.map +1 -0
- package/dist/errors.d.ts +31 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/generators/batch.d.ts +26 -0
- package/dist/generators/batch.d.ts.map +1 -0
- package/dist/generators/single.d.ts +23 -0
- package/dist/generators/single.d.ts.map +1 -0
- package/dist/generators/stream.d.ts +21 -0
- package/dist/generators/stream.d.ts.map +1 -0
- package/dist/html/parser.d.ts +13 -0
- package/dist/html/parser.d.ts.map +1 -0
- package/dist/html/utils.d.ts +13 -0
- package/dist/html/utils.d.ts.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +80 -0
- package/dist/types.d.ts +169 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/utils/response.d.ts +18 -0
- package/dist/utils/response.d.ts.map +1 -0
- package/dist/yoga-ZMNYPE6Z.wasm +0 -0
- package/package.json +51 -0
package/README.md
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# satori-cf
|
|
2
|
+
|
|
3
|
+
> SVG-only, batch-optimized Open Graph image generation for Cloudflare Workers
|
|
4
|
+
|
|
5
|
+
See the [main README](../../README.md) for full documentation.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install satori-cf
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Quick Start
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
import { generateOG, createSVGResponse } from "satori-cf";
|
|
17
|
+
|
|
18
|
+
export default {
|
|
19
|
+
async fetch(request: Request): Promise<Response> {
|
|
20
|
+
const result = await generateOG(
|
|
21
|
+
`<div style="display: flex; align-items: center; justify-content: center; width: 100%; height: 100%; background: #667eea; color: white; font-size: 60px;">
|
|
22
|
+
Hello World
|
|
23
|
+
</div>`
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
if (result.ok) {
|
|
27
|
+
return createSVGResponse(result.value);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return new Response(result.error.message, { status: 500 });
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## License
|
|
36
|
+
|
|
37
|
+
MIT
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { EmojiType } from "../types";
|
|
2
|
+
import type { Font } from "satori";
|
|
3
|
+
type AssetLoaderResult = string | Font[];
|
|
4
|
+
/**
|
|
5
|
+
* Creates a dynamic asset loader for emojis.
|
|
6
|
+
* Returns a function compatible with Satori's loadAdditionalAsset option.
|
|
7
|
+
*
|
|
8
|
+
* @param options - Options including the emoji provider to use
|
|
9
|
+
* @returns Asset loader function
|
|
10
|
+
*/
|
|
11
|
+
export declare const loadDynamicAsset: ({ emoji }: {
|
|
12
|
+
emoji: EmojiType;
|
|
13
|
+
}) => (languageCode: string, segment: string) => Promise<AssetLoaderResult>;
|
|
14
|
+
export {};
|
|
15
|
+
//# sourceMappingURL=emoji.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"emoji.d.ts","sourceRoot":"","sources":["../../src/assets/emoji.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAC1C,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAEnC,KAAK,iBAAiB,GAAG,MAAM,GAAG,IAAI,EAAE,CAAC;AA2DzC;;;;;;GAMG;AACH,eAAO,MAAM,gBAAgB,GAAI,WAAW;IAAE,KAAK,EAAE,SAAS,CAAA;CAAE,MAe5D,cAAc,MAAM,EACpB,SAAS,MAAM,KACd,OAAO,CAAC,iBAAiB,CAW7B,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { GoogleFontOptions } from "../types";
|
|
2
|
+
/**
|
|
3
|
+
* Loads a font from Google Fonts API.
|
|
4
|
+
* Uses Cloudflare's cache API for efficient caching.
|
|
5
|
+
*
|
|
6
|
+
* @param options - Font loading options
|
|
7
|
+
* @returns ArrayBuffer containing the font data
|
|
8
|
+
*/
|
|
9
|
+
export declare function loadGoogleFont({ family, weight, text, }: GoogleFontOptions): Promise<ArrayBuffer>;
|
|
10
|
+
//# sourceMappingURL=font.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"font.d.ts","sourceRoot":"","sources":["../../src/assets/font.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAGlD;;;;;;GAMG;AACH,wBAAsB,cAAc,CAAC,EACnC,MAAM,EACN,MAAM,EACN,IAAI,GACL,EAAE,iBAAiB,GAAG,OAAO,CAAC,WAAW,CAAC,CA6C1C"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ensures Yoga WASM is initialized exactly once.
|
|
3
|
+
* Uses promise coalescing to prevent concurrent initialization race conditions.
|
|
4
|
+
*
|
|
5
|
+
* @returns Promise that resolves when Yoga is ready
|
|
6
|
+
*/
|
|
7
|
+
export declare function ensureYogaInitialized(): Promise<void>;
|
|
8
|
+
/**
|
|
9
|
+
* Check if Yoga has been initialized
|
|
10
|
+
*/
|
|
11
|
+
export declare function isInitialized(): boolean;
|
|
12
|
+
//# sourceMappingURL=yoga.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"yoga.d.ts","sourceRoot":"","sources":["../../src/core/yoga.ts"],"names":[],"mappings":"AAmBA;;;;;GAKG;AACH,wBAAsB,qBAAqB,IAAI,OAAO,CAAC,IAAI,CAAC,CA+B3D;AAED;;GAEG;AACH,wBAAgB,aAAa,IAAI,OAAO,CAEvC"}
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base error class for satori-cf errors
|
|
3
|
+
*/
|
|
4
|
+
export declare class SatoriCFError extends Error {
|
|
5
|
+
constructor(message: string);
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Error thrown when WASM initialization fails
|
|
9
|
+
*/
|
|
10
|
+
export declare class WASMInitError extends SatoriCFError {
|
|
11
|
+
constructor(message: string);
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Error thrown when font loading fails
|
|
15
|
+
*/
|
|
16
|
+
export declare class FontLoadError extends SatoriCFError {
|
|
17
|
+
constructor(message: string);
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Error thrown when HTML parsing fails
|
|
21
|
+
*/
|
|
22
|
+
export declare class HTMLParseError extends SatoriCFError {
|
|
23
|
+
constructor(message: string);
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Error thrown when SVG generation fails
|
|
27
|
+
*/
|
|
28
|
+
export declare class SVGGenerationError extends SatoriCFError {
|
|
29
|
+
constructor(message: string);
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,qBAAa,aAAc,SAAQ,KAAK;gBAC1B,OAAO,EAAE,MAAM;CAI5B;AAED;;GAEG;AACH,qBAAa,aAAc,SAAQ,aAAa;gBAClC,OAAO,EAAE,MAAM;CAI5B;AAED;;GAEG;AACH,qBAAa,aAAc,SAAQ,aAAa;gBAClC,OAAO,EAAE,MAAM;CAI5B;AAED;;GAEG;AACH,qBAAa,cAAe,SAAQ,aAAa;gBACnC,OAAO,EAAE,MAAM;CAI5B;AAED;;GAEG;AACH,qBAAa,kBAAmB,SAAQ,aAAa;gBACvC,OAAO,EAAE,MAAM;CAI5B"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { BatchItem, BatchOptions, BatchResult } from "../types";
|
|
2
|
+
/**
|
|
3
|
+
* Generates multiple OG images as SVG with amortized WASM initialization.
|
|
4
|
+
* The WASM module is initialized once at the start, and fonts are pre-loaded
|
|
5
|
+
* for the entire batch.
|
|
6
|
+
*
|
|
7
|
+
* @param items - Array of items to generate
|
|
8
|
+
* @param options - Batch generation options
|
|
9
|
+
* @returns Array of results with preserved indices
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```ts
|
|
13
|
+
* const results = await generateOGBatch([
|
|
14
|
+
* { element: <Card title="One" /> },
|
|
15
|
+
* { element: <Card title="Two" /> },
|
|
16
|
+
* ], { concurrency: 5 });
|
|
17
|
+
*
|
|
18
|
+
* for (const { index, result } of results) {
|
|
19
|
+
* if (result.ok) {
|
|
20
|
+
* console.log(`Item ${index}: ${result.value.length} bytes`);
|
|
21
|
+
* }
|
|
22
|
+
* }
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
export declare function generateOGBatch(items: BatchItem[], options?: BatchOptions): Promise<BatchResult[]>;
|
|
26
|
+
//# sourceMappingURL=batch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"batch.d.ts","sourceRoot":"","sources":["../../src/generators/batch.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAGrE;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAsB,eAAe,CACnC,KAAK,EAAE,SAAS,EAAE,EAClB,OAAO,GAAE,YAAiB,GACzB,OAAO,CAAC,WAAW,EAAE,CAAC,CAyFxB"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { OGOptions, OGResult } from "../types";
|
|
2
|
+
/**
|
|
3
|
+
* Generates a single OG image as SVG.
|
|
4
|
+
*
|
|
5
|
+
* @param element - React element or HTML string to render
|
|
6
|
+
* @param options - Generation options
|
|
7
|
+
* @returns Result containing the SVG string or an error
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```ts
|
|
11
|
+
* const result = await generateOG(<Card title="Hello" />);
|
|
12
|
+
* if (result.ok) {
|
|
13
|
+
* console.log(result.value); // "<svg..."
|
|
14
|
+
* }
|
|
15
|
+
* ```
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```ts
|
|
19
|
+
* const result = await generateOG('<div style="color: red">Hello</div>');
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
export declare function generateOG(element: React.ReactNode | string, options?: OGOptions): Promise<OGResult<string>>;
|
|
23
|
+
//# sourceMappingURL=single.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"single.d.ts","sourceRoot":"","sources":["../../src/generators/single.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAEpD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,UAAU,CAC9B,OAAO,EAAE,KAAK,CAAC,SAAS,GAAG,MAAM,EACjC,OAAO,GAAE,SAAc,GACtB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAoD3B"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { StreamItem, StreamOptions, StreamResult } from "../types";
|
|
2
|
+
/**
|
|
3
|
+
* Generates OG images as an async generator for streaming large batches.
|
|
4
|
+
* Uses a prefetch pipeline for optimal throughput while maintaining
|
|
5
|
+
* memory efficiency.
|
|
6
|
+
*
|
|
7
|
+
* @param items - Iterable or AsyncIterable of items to generate
|
|
8
|
+
* @param options - Stream generation options
|
|
9
|
+
* @yields Results in order as they complete
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```ts
|
|
13
|
+
* for await (const { index, result } of OGStream(items, { prefetch: 3 })) {
|
|
14
|
+
* if (result.ok) {
|
|
15
|
+
* console.log(`Generated ${index}: ${result.value.length} bytes`);
|
|
16
|
+
* }
|
|
17
|
+
* }
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export declare function OGStream(items: Iterable<StreamItem> | AsyncIterable<StreamItem>, options?: StreamOptions): AsyncGenerator<StreamResult, void, unknown>;
|
|
21
|
+
//# sourceMappingURL=stream.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stream.d.ts","sourceRoot":"","sources":["../../src/generators/stream.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAGxE;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAuB,QAAQ,CAC7B,KAAK,EAAE,QAAQ,CAAC,UAAU,CAAC,GAAG,aAAa,CAAC,UAAU,CAAC,EACvD,OAAO,GAAE,aAAkB,GAC1B,cAAc,CAAC,YAAY,EAAE,IAAI,EAAE,OAAO,CAAC,CA4F7C"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parses HTML into a ReactElementLike object
|
|
3
|
+
* using Cloudflare Worker's own HTMLRewriter.
|
|
4
|
+
*
|
|
5
|
+
* This approach leverages the HTMLRewriter API which is part of
|
|
6
|
+
* Cloudflare Worker's runtime, making it the fastest way to
|
|
7
|
+
* transform HTML in this environment.
|
|
8
|
+
*
|
|
9
|
+
* @param html - HTML string to parse
|
|
10
|
+
* @returns Promise resolving to a React-like node or null on error
|
|
11
|
+
*/
|
|
12
|
+
export declare function parseHtml(html: string): Promise<React.ReactNode | null>;
|
|
13
|
+
//# sourceMappingURL=parser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../../src/html/parser.ts"],"names":[],"mappings":"AAMA;;;;;;;;;;GAUG;AACH,wBAAsB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC,CA6C7E"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sanitizes a string for use in JSON
|
|
3
|
+
*/
|
|
4
|
+
export declare const sanitizeJSON: (unsanitized: string) => string;
|
|
5
|
+
/**
|
|
6
|
+
* Extracts and formats attributes from an HTML element for JSON VDOM
|
|
7
|
+
*/
|
|
8
|
+
export declare const getAttributes: (element: Element) => string;
|
|
9
|
+
/**
|
|
10
|
+
* Removes trailing comma from a string if present
|
|
11
|
+
*/
|
|
12
|
+
export declare const maybeRemoveTrailingComma: (str: string) => string;
|
|
13
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/html/utils.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,eAAO,MAAM,YAAY,GAAI,aAAa,MAAM,KAAG,MAQlD,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,aAAa,GAAI,SAAS,OAAO,KAAG,MAgDhD,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,wBAAwB,GAAI,KAAK,MAAM,KAAG,MAKtD,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export { generateOG } from "./generators/single";
|
|
2
|
+
export { generateOGBatch } from "./generators/batch";
|
|
3
|
+
export { OGStream } from "./generators/stream";
|
|
4
|
+
export { loadGoogleFont } from "./assets/font";
|
|
5
|
+
export { loadDynamicAsset } from "./assets/emoji";
|
|
6
|
+
export { parseHtml } from "./html/parser";
|
|
7
|
+
export { createSVGResponse } from "./utils/response";
|
|
8
|
+
export { ensureYogaInitialized, isInitialized } from "./core/yoga";
|
|
9
|
+
export type { OGOptions, OGResult, OGSuccess, OGError, BatchItem, BatchResult, BatchOptions, StreamItem, StreamResult, StreamOptions, GoogleFontOptions, SVGResponseOptions, EmojiType, } from "./types";
|
|
10
|
+
export { SatoriCFError, WASMInitError, FontLoadError, HTMLParseError, SVGGenerationError, } from "./errors";
|
|
11
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAG/C,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAGrD,OAAO,EAAE,qBAAqB,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAGnE,YAAY,EACV,SAAS,EACT,QAAQ,EACR,SAAS,EACT,OAAO,EACP,SAAS,EACT,WAAW,EACX,YAAY,EACZ,UAAU,EACV,YAAY,EACZ,aAAa,EACb,iBAAiB,EACjB,kBAAkB,EAClB,SAAS,GACV,MAAM,SAAS,CAAC;AAGjB,OAAO,EACL,aAAa,EACb,aAAa,EACb,aAAa,EACb,cAAc,EACd,kBAAkB,GACnB,MAAM,UAAU,CAAC"}
|