wasm-html-to-image 1.0.5 → 1.0.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.
package/README.md CHANGED
@@ -7,27 +7,36 @@
7
7
  [![Documentation](https://img.shields.io/badge/Docs-Docusaurus-blue)](https://sorakumo001.github.io/wasm-html-to-image/master/docs/)
8
8
  [![Samples](https://img.shields.io/badge/Examples-GitHub-green)](https://github.com/SoraKumo001/wasm-html-to-image-samples)
9
9
 
10
- A high-performance, WebAssembly-powered HTML-to-image renderer and image optimization engine. It consolidates HTML rendering (**Satoru** / **Skia** / **litehtml**) and native image encoding (**WebP / AVIF / JPEG**) into a single, unified WASM binary.
10
+ A high-performance HTML-to-image renderer and image processing engine powered by a single WebAssembly module.
11
11
 
12
- No headless browsers (Chromium, Puppeteer, or Playwright) required. Runs seamlessly across Node.js, Cloudflare Workers, Edge runtimes, browsers, and the CLI.
12
+ **No Chromium / Puppeteer.** **No native dependencies (Sharp / ImageMagick).**
13
+ Runs seamlessly across **Node.js**, **Cloudflare Workers**, **Edge runtimes**, **browsers**, and the **CLI**.
13
14
 
14
15
  ---
15
16
 
16
- ## ✨ Features
17
+ ## ⚡ What Can It Do?
17
18
 
18
- - ⚡ **Single Unified WASM Binary**: HTML parsing, CSS layout, vector painting, and image encoding execute entirely inside WebAssembly without copying intermediate framebuffers across JS boundaries.
19
- - 🎨 **Versatile Inputs**: Renders HTML strings, remote Web URLs, multi-page HTML arrays, or raw image buffers (PNG, JPEG, WebP, GIF, AVIF, BMP, Data URLs).
20
- - 📦 **Rich Output Formats**: Direct SVG vector streams, high-quality PNG, JPEG, WebP, AVIF, JXL, uncompressed RAW pixels, ThumbHash placeholders, and multi-page vector PDFs.
21
- - 🚀 **Zero-Config Single Bundle**: Use `wasm-html-to-image/single` to call `render()` immediately without manual WASM loading or build setup.
22
- - 🌐 **Edge & Serverless Native**: Dedicated subpaths (`/workerd` for Cloudflare Workers, `/edge-light` for Vercel Edge) tailored for strict serverless constraints.
23
- - 🧵 **Multi-Threaded Worker Pool**: Process thousands of images in parallel using `wasm-html-to-image/workers` (Node.js worker threads / Web Workers).
24
- - ⚛️ **Ecosystem Ready**: First-class support for React / Preact JSX components and Tailwind CSS inlined styling.
19
+ | Feature | Description | Formats |
20
+ | :--- | :--- | :--- |
21
+ | 🌐 **HTML / React to Image** | Render HTML/CSS strings or React components directly | PNG, JPEG, WebP, AVIF, JXL, SVG |
22
+ | 🔗 **URL to Screenshot** | Capture remote web pages without launching a browser | PNG, WebP, JPEG, AVIF |
23
+ | 📑 **Multi-Page Vector PDF** | Generate crisp, selectable vector PDFs from HTML or images | PDF |
24
+ | 🖼️ **Image Resizing & Optimization** | Fast format conversion, crop, and resize (Sharp alternative) | WebP, AVIF, JXL, PNG, JPEG |
25
+ | 🎬 **CSS Animation to WebP / GIF** | Record CSS `@keyframes` animations into animated images | Animated WebP, APNG, GIF |
26
+ | 🪶 **ThumbHash Blur Placeholder** | Generate compact blur placeholders for instant progressive loading | ThumbHash |
27
+
28
+
29
+ Supports vertical writing mode and CSS animations:
30
+
31
+ <p align="center">
32
+ <img src="./doc/image01.webp" alt="Vertical writing mode and animation preview" width="100%" />
33
+ </p>
25
34
 
26
35
  ---
27
36
 
28
37
  ## 📦 Installation
29
38
 
30
- ```bash npm2yarn
39
+ ```bash
31
40
  npm install wasm-html-to-image
32
41
  ```
33
42
 
@@ -35,151 +44,122 @@ npm install wasm-html-to-image
35
44
 
36
45
  ## 🚀 Quick Start
37
46
 
38
- ### Zero-Config Rendering (`wasm-html-to-image`)
39
-
40
- The easiest way to get started. WASM is embedded and loaded automatically (in Cloudflare Workers, the workerd-optimized module is automatically selected):
47
+ One single function — `render()` — handles all HTML rendering, URL capturing, and image processing:
41
48
 
42
49
  ```typescript
43
50
  import { render } from "wasm-html-to-image";
44
51
 
45
- // 1. Render HTML to PNG (returns RenderResult with .data and dimensions)
52
+ // 1. Render HTML to PNG / WebP / AVIF
46
53
  const result = await render({
47
- value: `<div style="background: linear-gradient(135deg, #667eea, #764ba2); padding: 40px; color: white; border-radius: 16px; font-family: sans-serif;">
48
- <h1 style="margin: 0; font-size: 32px;">Hello wasm-html-to-image</h1>
49
- <p style="margin-top: 8px; opacity: 0.9;">High-performance serverless rendering</p>
54
+ value: `<div style="padding: 40px; background: #6366f1; color: white; border-radius: 12px; font-family: sans-serif;">
55
+ <h1 style="margin: 0;">Hello wasm-html-to-image</h1>
56
+ <p>High-performance serverless rendering</p>
50
57
  </div>`,
51
58
  width: 800,
52
59
  format: "png",
53
60
  });
54
-
55
61
  console.log(result.data); // Uint8Array
56
62
  console.log(result.width, result.height); // 800, 600
57
63
 
58
- // 2. Convert and resize image with the same render() function
59
- const webp = await render({
60
- value: result.data, // Pass raw image buffer directly
61
- width: 400, // Target resized width
64
+ // 2. Capture a URL screenshot
65
+ const screenshot = await render({
66
+ url: "https://example.com",
67
+ width: 1200,
68
+ height: 630,
62
69
  format: "webp",
70
+ });
71
+
72
+ // 3. Convert & Resize an image (JPEG -> AVIF)
73
+ const avif = await render({
74
+ value: imageBuffer, // Pass raw Uint8Array / Buffer directly
75
+ width: 400,
76
+ format: "avif",
63
77
  quality: 80,
64
78
  });
65
79
 
66
- console.log(webp.originalWidth, webp.originalHeight); // Original image dimensions
67
- console.log(webp.width, webp.height); // Output image dimensions
80
+ // 4. Record CSS Animation -> Animated WebP / GIF / APNG
81
+ const animated = await render({
82
+ value: `<style>
83
+ @keyframes spin { to { transform: rotate(360deg); } }
84
+ .box { width: 100px; height: 100px; background: red; animation: spin 2s linear infinite; }
85
+ </style><div class="box"></div>`,
86
+ format: "webp",
87
+ animation: 2000, // duration in ms
88
+ animationFps: 20,
89
+ });
68
90
  ```
69
91
 
70
92
  ---
71
93
 
72
- ## 🖼️ Image-to-Image Conversion & Optimization
73
-
74
- `wasm-html-to-image` is not only an HTML renderer — it also serves as a high-speed, self-contained **image-to-image converter, resizer, and compressor** without requiring heavy native libraries like Sharp or ImageMagick.
75
-
76
- Simply pass raw image bytes (`Uint8Array` or `Buffer`) or a `data:image/...` URL to `render()`. It automatically identifies input magic bytes, skips the HTML layout pass, and routes straight into the native Skia image pipeline. Every call returns rich metadata (`width`, `height`, `originalWidth`, `originalHeight`, `format`, `isAnimated`) along with the output data in `.data`:
77
-
78
- ```typescript
79
- import fs from "node:fs/promises";
80
- import { render } from "wasm-html-to-image/single";
81
-
82
- const imageBuffer = await fs.readFile("photo.jpg");
94
+ ## 💻 CLI Usage
83
95
 
84
- // 1. Convert JPEG -> AVIF (highest compression)
85
- const avif = await render({
86
- value: imageBuffer,
87
- width: 800,
88
- format: "avif",
89
- quality: 75,
90
- speed: 6, // 0 (best quality) - 10 (fastest). AVIF default is 8; 6 trades time for ~15-20% smaller files
91
- });
92
- await fs.writeFile("photo.avif", Buffer.from(avif.data));
96
+ Render from your terminal without writing code:
93
97
 
94
- // 2. Crop & Resize -> PNG
95
- const cropped = await render({
96
- value: imageBuffer,
97
- crop: { x: 50, y: 50, width: 300, height: 300 },
98
- width: 150,
99
- height: 150,
100
- format: "png",
101
- });
102
- await fs.writeFile("cropped.png", Buffer.from(cropped.data));
98
+ ```bash
99
+ # Render HTML to WebP
100
+ npx wasm-html-to-image template.html -o banner.webp -w 1200 -h 630 -f webp -q 90
103
101
 
104
- // 3. Generate ThumbHash Blur Placeholder
105
- const thumbhash = await render({
106
- value: imageBuffer,
107
- width: 100,
108
- format: "thumbhash",
109
- });
110
- console.log("ThumbHash bytes:", thumbhash.data);
102
+ # Capture screenshot from URL
103
+ npx wasm-html-to-image https://example.com -o site.png -w 1280 -h 720
111
104
 
112
- // 4. Convert Image -> Single-Page Vector PDF
113
- const pdf = await render({
114
- value: imageBuffer,
115
- format: "pdf",
116
- });
117
- await fs.writeFile("photo.pdf", Buffer.from(pdf.data));
105
+ # Convert and resize an image (JPEG -> AVIF)
106
+ npx wasm-html-to-image photo.jpg -o photo.avif -w 800 -f avif -q 80
118
107
 
119
- // 5. Convert Animated GIF -> Animated WebP
120
- const animatedWebp = await render({
121
- value: await fs.readFile("animation.gif"),
122
- format: "webp",
123
- animation: true,
124
- });
125
- await fs.writeFile("animation.webp", Buffer.from(animatedWebp.data));
108
+ # Convert CSS animation into Animated WebP or GIF
109
+ npx wasm-html-to-image loader.html -o loader.webp -f webp --animation 2000 --animation-fps 20
110
+ npx wasm-html-to-image loader.html -o loader.gif -f gif --animation 2000
126
111
  ```
127
112
 
128
113
  ---
129
114
 
130
- ## 📊 Format Matrix
115
+ ## 📊 Supported Formats
131
116
 
132
117
  ### Inputs (`value` / `url`)
133
-
134
- | Input Type | Detection | Description |
135
- | --------------------------- | -------------------------------- | ---------------------------------------------------------- |
136
- | **HTML String** | Text starting with tags / markup | Standard HTML/CSS rendering |
137
- | **HTML Array (`string[]`)** | Array of HTML strings | Multi-page PDF generation (one page per item) |
138
- | **URL (`url`)** | `http://` or `https://` | Automatically fetches and renders remote web pages |
139
- | **Image Buffer** | `Uint8Array` / `Buffer` | Magic-byte recognition for PNG, JPEG, WebP, GIF, AVIF, BMP |
140
- | **Data URL** | `data:image/*;base64,...` | Inlined image data URL, routed straight to image pipeline |
118
+ - **HTML String**: Standard HTML & CSS (Flexbox, Grid, gradients, custom fonts, `@keyframes`).
119
+ - **HTML Array (`string[]`)**: Multi-page PDF generation (one page per array item).
120
+ - **URL (`url`)**: Automatically fetches and renders remote web pages.
121
+ - **Image Buffer / Data URL**: `PNG`, `JPEG`, `WebP`, `GIF`, `AVIF`, `JXL`, `BMP`.
141
122
 
142
123
  ### Outputs (`format`)
124
+ `png`, `jpeg`, `webp`, `avif`, `jxl`, `apng`, `gif`, `svg`, `pdf`, `thumbhash`, `raw` (uncompressed RGBA).
143
125
 
144
- All formats return a `RenderResult<T>` object containing `.data` (`Uint8Array` or `string` for SVG) and metadata (`width`, `height`, `originalWidth`, `originalHeight`, `format`, `isAnimated`):
145
-
146
- | Format | `result.data` Type | HTML Input | Image Input |
147
- | ----------- | ------------------ | ---------------------------------------------- | ----------------------------- |
148
- | `png` | `Uint8Array` | Skia render → PNG encode | Decodes and converts to PNG |
149
- | `jpeg` | `Uint8Array` | Skia render → JPEG encode (`quality`) | Decodes and compresses JPEG |
150
- | `webp` | `Uint8Array` | Skia render → WebP encode (`quality`) | Decodes and compresses WebP |
151
- | `avif` | `Uint8Array` | Skia render → AVIF encode (`quality`, `speed`) | Decodes and compresses AVIF |
152
- | `jxl` | `Uint8Array` | Skia render → JXL encode (`quality`, `speed`) | Decodes and compresses JXL |
153
- | `raw` | `Uint8Array` | Uncompressed RGBA pixel bytes | Uncompressed RGBA pixel bytes |
154
- | `thumbhash` | `Uint8Array` | Computes ThumbHash from render | Computes ThumbHash from image |
155
- | `svg` | `string` | Skia vector drawing stream | Single `<image>` wrapper SVG |
156
- | `pdf` | `Uint8Array` | SkPDFDocument vector PDF | Single-page centered PDF |
126
+ Every call returns a `RenderResult` object:
127
+ ```typescript
128
+ interface RenderResult {
129
+ data: Uint8Array | string; // Binary bytes (or string for SVG)
130
+ width: number;
131
+ height: number;
132
+ originalWidth: number;
133
+ originalHeight: number;
134
+ format: string;
135
+ isAnimated: boolean;
136
+ }
137
+ ```
157
138
 
158
139
  ---
159
140
 
160
- ## 🧩 Subpaths & Usage
141
+ ## 🌐 Environments & Subpaths
161
142
 
162
- Choose the optimal entry point for your application and environment:
163
-
164
- | Subpath | Target Environment | Highlights |
165
- | ------------------------------- | ---------------------------------------- | ---------------------------------------------------------------------- |
166
- | `wasm-html-to-image` | Universal (Node, Edge, Cloudflare, Deno) | Zero-config default: auto routes to single/workerd, instant `render()` |
167
- | `wasm-html-to-image/single` | Node.js, Bundlers | Single bundled WASM entry point |
168
- | `wasm-html-to-image/index` | High-throughput servers | Explicit `loadHtmlToImageModule()` & manual instance reuse |
169
- | `wasm-html-to-image/workerd` | Cloudflare Workers | WebAssembly.Module compilation compatible |
170
- | `wasm-html-to-image/edge-light` | Vercel Edge Runtime | Optimized for Edge Runtime constraints |
171
- | `wasm-html-to-image/workers` | Node.js, Browsers | Multi-threaded worker pool for high concurrency |
172
- | `wasm-html-to-image/react` | React integration | Directly render React JSX element trees |
173
- | `wasm-html-to-image/preact` | Preact integration | Directly render Preact JSX element trees |
174
- | `wasm-html-to-image/tailwind` | Utility styling | Inlines UnoCSS / Tailwind classes |
143
+ | Subpath | Target Environment | Highlights |
144
+ | :--- | :--- | :--- |
145
+ | `wasm-html-to-image` | Universal (Node, Edge, Cloudflare, Deno) | **Zero-config default**: auto-routes to single or workerd |
146
+ | `wasm-html-to-image/single` | Node.js, Bundlers | Single bundled WASM binary |
147
+ | `wasm-html-to-image/index` | High-throughput servers | Explicit `loadHtmlToImageModule()` & instance reuse |
148
+ | `wasm-html-to-image/workerd` | Cloudflare Workers | Optimized for `WebAssembly.Module` compilation |
149
+ | `wasm-html-to-image/edge-light` | Vercel Edge Runtime | Tailored for strict Edge constraints |
150
+ | `wasm-html-to-image/workers` | Node.js, Web Workers | Multi-threaded worker pool for high concurrency |
151
+ | `wasm-html-to-image/react` | React integration | Directly render React JSX element trees |
152
+ | `wasm-html-to-image/preact` | Preact integration | Directly render Preact JSX element trees |
153
+ | `wasm-html-to-image/tailwind` | Utility styling | UnoCSS / Tailwind v4 utilities (`createCSS`, `tailwind()`) |
175
154
 
176
155
  ---
177
156
 
178
- ## 💡 Practical Examples
157
+ ## 💡 Advanced Examples
179
158
 
180
- ### 1. High-Throughput Node.js Server (Instance Reuse)
159
+ <details>
160
+ <summary><b>1. High-Throughput Node.js Server (Module Instance Reuse)</b></summary>
181
161
 
182
- Reuse the WASM module across incoming HTTP requests for maximum performance:
162
+ Reuse the compiled WASM module across incoming HTTP requests for maximum performance:
183
163
 
184
164
  ```typescript
185
165
  import { loadHtmlToImageModule, htmlToImage } from "wasm-html-to-image";
@@ -202,19 +182,13 @@ app.get("/ogp", async (req, res) => {
202
182
 
203
183
  app.listen(3000);
204
184
  ```
185
+ </details>
205
186
 
206
- ### 2. Cloudflare Workers (`workerd`)
207
-
208
- Generate dynamic social preview images at the edge:
187
+ <details>
188
+ <summary><b>2. Cloudflare Workers (Edge OGP Generator)</b></summary>
209
189
 
210
190
  ```typescript
211
- // wrangler.jsonc: no "rules" needed on current Wrangler (v3/v4) —
212
- // `import ... from "*.wasm"` is bundled as WebAssembly.Module by default.
213
- // Minimal wrangler.jsonc: { "main": "src/index.ts", "compatibility_date": "2026-09-01" }
214
- // (Only configure "rules" yourself if you customize bundling rules or use a very old Wrangler.
215
- // Note: @cloudflare/vite-plugin ignores "rules".)
216
-
217
- import { render } from "wasm-html-to-image"; // auto-selects the workerd build on Cloudflare ("wasm-html-to-image/workerd" also works)
191
+ import { render } from "wasm-html-to-image"; // auto-selects the workerd build
218
192
 
219
193
  export default {
220
194
  async fetch(request: Request): Promise<Response> {
@@ -236,10 +210,12 @@ export default {
236
210
  },
237
211
  };
238
212
  ```
213
+ </details>
239
214
 
240
- ### 3. Multi-Threaded Batch Generation (`workers`)
215
+ <details>
216
+ <summary><b>3. Multi-Threaded Batch Generation (`workers`)</b></summary>
241
217
 
242
- Leverage multi-core CPUs to process large batches of images in parallel:
218
+ Leverage multi-core CPUs with worker threads to render hundreds of images in parallel:
243
219
 
244
220
  ```typescript
245
221
  import { render } from "wasm-html-to-image/workers";
@@ -255,38 +231,36 @@ const tasks = items.map((item) =>
255
231
 
256
232
  const images = await Promise.all(tasks);
257
233
  ```
234
+ </details>
258
235
 
259
- ### 4. Command Line Interface (CLI)
260
-
261
- Render directly from your shell without writing code:
262
-
263
- ```bash
264
- # Render HTML to WebP
265
- npx wasm-html-to-image template.html -o banner.webp -w 1200 -h 630 -f webp -q 90
266
-
267
- # Capture screenshot from URL
268
- npx wasm-html-to-image https://example.com -o site.png -w 1280 -h 720
269
-
270
- # Pin the base for relative resources (default: URL input follows redirects,
271
- # file input uses the file's own directory)
272
- npx wasm-html-to-image https://example.com/news -o news.png --base-url https://example.com/
236
+ <details>
237
+ <summary><b>4. Image Cropping & ThumbHash</b></summary>
273
238
 
274
- # Convert and resize an image
275
- npx wasm-html-to-image photo.jpg -o photo.avif -w 800 -f avif -q 80
239
+ ```typescript
240
+ import { render } from "wasm-html-to-image";
276
241
 
277
- # Sample an opacity / transform / color @keyframes animation into an animated WebP
278
- npx wasm-html-to-image loader.html -o loader.webp -f webp --animation 2000 --animation-fps 20
242
+ // Crop and resize
243
+ const cropped = await render({
244
+ value: imageBuffer,
245
+ crop: { x: 50, y: 50, width: 300, height: 300 },
246
+ width: 150,
247
+ height: 150,
248
+ format: "png",
249
+ });
279
250
 
280
- # Play the animated WebP once instead of looping forever
281
- npx wasm-html-to-image loader.html -o loader.webp -f webp --animation 2000 --animation-loop 1
251
+ // Generate ThumbHash blur placeholder
252
+ const thumbhash = await render({
253
+ value: imageBuffer,
254
+ width: 100,
255
+ format: "thumbhash",
256
+ });
282
257
  ```
258
+ </details>
283
259
 
284
260
  ---
285
261
 
286
262
  ## 📖 Documentation & Examples
287
263
 
288
- For full guides, architecture deep-dives, font management, and advanced recipes:
289
-
290
264
  👉 **[Read the Official Documentation](https://sorakumo001.github.io/wasm-html-to-image/master/docs/)**
291
265
  👉 **[Sample Code & Projects (GitHub)](https://github.com/SoraKumo001/wasm-html-to-image-samples)**
292
266
 
@@ -14,7 +14,7 @@ import { pdfFirstPageSize, svgRootHeight } from "./output-size.js";
14
14
  import { FIT_INT, FORMAT_INT } from "./encode-args.js";
15
15
  import { imageBytesFromUnknown, toBytes, } from "./input.js";
16
16
  import { DIAGNOSTIC_CODES, LogLevel, } from "./diagnostics.js";
17
- import { now, resolveHtmlResources, } from "./core-resources.js";
17
+ import { isNodeRuntime, now, resolveHtmlResources, } from "./core-resources.js";
18
18
  const DEFAULT_USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36";
19
19
  export { DEFAULT_USER_AGENT };
20
20
  export function requireBindingError(name) {
@@ -193,7 +193,11 @@ export async function resolveHtmlSource(orch) {
193
193
  return value;
194
194
  }
195
195
  if (typeof url === "string") {
196
- const headers = { "User-Agent": userAgent ?? DEFAULT_USER_AGENT };
196
+ // Same as resource fetch: User-Agent override is Node-only. In browsers
197
+ // it is forbidden and triggers a Firefox preflight that breaks CORS.
198
+ const headers = isNodeRuntime()
199
+ ? { "User-Agent": userAgent ?? DEFAULT_USER_AGENT }
200
+ : undefined;
197
201
  const fetchStart = now();
198
202
  // Post-redirect document URL (`Response.url`). Relative resources must
199
203
  // resolve against the final URL, not the stale request URL: a 301 to a new
@@ -10,6 +10,7 @@ import { type HtmlToImageModule } from "./loader.js";
10
10
  import { LogLevel, type DiagnosticMessage, type FontDiagnostic, type RenderLimits, type ResolveResourceHook, type ResourceDiagnostic } from "./diagnostics.js";
11
11
  /** Drop every cached resource (e.g. after the source assets changed). */
12
12
  export declare function clearResourceCache(): void;
13
+ export declare function isNodeRuntime(): boolean;
13
14
  /**
14
15
  * Fetch external resource bytes. `data:` URLs resolve inline in C++
15
16
  * (`request()`), so they are skipped here. Relative URLs resolve against
@@ -56,7 +56,7 @@ const resourceCache = new ResourceCache();
56
56
  export function clearResourceCache() {
57
57
  resourceCache.clear();
58
58
  }
59
- function isNodeRuntime() {
59
+ export function isNodeRuntime() {
60
60
  const proc = globalThis
61
61
  .process;
62
62
  return typeof proc?.versions?.node === "string";
@@ -102,7 +102,10 @@ async function isInsideDir(fs, path, root, target) {
102
102
  }
103
103
  /** Built-in resolution behind the `resolveResource` hook (see above). */
104
104
  async function fetchResourceBytesInner(url, baseUrl, userAgent, timeoutMs, confineFiles) {
105
- const headers = userAgent ? { "User-Agent": userAgent } : undefined;
105
+ // Browser fetch forbids overriding User-Agent (and Firefox preflights it,
106
+ // breaking Google Fonts/jsDelivr CORS). Spoof only in Node where we
107
+ // control the UA to get woff2 CSS.
108
+ const headers = userAgent && isNodeRuntime() ? { "User-Agent": userAgent } : undefined;
106
109
  // Abort hung connections so one stalled server cannot outlive `timeoutMs`.
107
110
  const signal = timeoutMs !== undefined
108
111
  ? AbortSignal.timeout(Math.max(1, timeoutMs))
package/dist/core.d.ts CHANGED
@@ -63,7 +63,7 @@ export interface RenderOptions {
63
63
  export interface HtmlToImageOptions extends RenderOptions {
64
64
  /** Encode quality 0-100 (encode stage only, default 85; ignored for svg/pdf). */
65
65
  quality?: number;
66
- /** Encode speed 0-10, mainly for AVIF (encode stage only; default 8 for AVIF, 6 otherwise). */
66
+ /** Encode speed 0-10 for AVIF, JXL and animated (lossy) WebP (encode stage only; default 8 for AVIF, 6 otherwise). Animated WebP uses libwebp method `8 - speed`: the default 6 is method 2, 5 is method 3 (Skia's, smaller by ~4%), 9 is method 0 (fastest, ~30% larger). */
67
67
  speed?: number;
68
68
  /**
69
69
  * Animation handling.
package/dist/core.js CHANGED
@@ -15,8 +15,8 @@ const EMOJI_URL = "https://cdn.jsdelivr.net/npm/@fontsource/noto-color-emoji/fil
15
15
  * UA so woff2 is served); fetched at render time, nothing bundled.
16
16
  */
17
17
  export const DEFAULT_FONT_MAP = {
18
- "sans-serif": "https://fonts.googleapis.com/css2?family=Noto+Sans+JP",
19
- serif: "https://fonts.googleapis.com/css2?family=Noto+Serif+JP",
18
+ "sans-serif": "https://fonts.googleapis.com/css2?family=Noto+Sans+JP:wght@100..900",
19
+ serif: "https://fonts.googleapis.com/css2?family=Noto+Serif+JP:wght@200..900",
20
20
  monospace: "https://fonts.googleapis.com/css2?family=M+PLUS+1+Code",
21
21
  cursive: "https://fonts.googleapis.com/css2?family=Yuji+Syuku",
22
22
  fantasy: "https://fonts.googleapis.com/css2?family=Reggae+One",