@browserless/screenshot 10.12.3 → 10.12.4

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
@@ -61,17 +61,17 @@ const buffer = await browserless.screenshot('https://example.com', {
61
61
 
62
62
  ### Options
63
63
 
64
- | Option | Type | Default | Description |
65
- |--------|------|---------|-------------|
66
- | `type` | `string` | `'png'` | Image format: `'png'`, `'jpeg'`, `'webp'` |
67
- | `quality` | `number` | — | Quality (0-100) for JPEG/WebP |
68
- | `fullPage` | `boolean` | `false` | Capture full scrollable page |
69
- | `element` | `string` | — | CSS selector for element screenshot |
70
- | `codeScheme` | `string` | `'atom-dark'` | Prism.js theme for code highlighting |
71
- | `waitUntil` | `string` | `'auto'` | When to consider navigation done |
72
- | `waitForDom` | `number` | `0` | DOM stability window in ms (idle is `waitForDom / 10`, `0` disables DOM wait) |
73
- | `isPageReady` | `function` | `({ isWhite }) => !isWhite` | Custom readiness predicate for retry loop |
74
- | `overlay` | `object` | `{}` | Browser overlay options |
64
+ | Option | Type | Default | Description |
65
+ | ------------- | ---------- | --------------------------- | ----------------------------------------------------------------------------- |
66
+ | `type` | `string` | `'png'` | Image format: `'png'`, `'jpeg'`, `'webp'` |
67
+ | `quality` | `number` | — | Quality (0-100) for JPEG/WebP |
68
+ | `fullPage` | `boolean` | `false` | Capture full scrollable page |
69
+ | `element` | `string` | — | CSS selector for element screenshot |
70
+ | `codeScheme` | `string` | `'atom-dark'` | Prism.js theme for code highlighting |
71
+ | `waitUntil` | `string` | `'auto'` | When to consider navigation done |
72
+ | `waitForDom` | `number` | `0` | DOM stability window in ms (idle is `waitForDom / 10`, `0` disables DOM wait) |
73
+ | `isPageReady` | `function` | `({ isWhite }) => !isWhite` | Custom readiness predicate for retry loop |
74
+ | `overlay` | `object` | `{}` | Browser overlay options |
75
75
 
76
76
  All [Puppeteer page.screenshot() options](https://pptr.dev/api/puppeteer.screenshotoptions) are supported.
77
77
 
@@ -84,10 +84,10 @@ const buffer = await browserless.screenshot(url, {
84
84
  overlay: {
85
85
  // Browser frame theme: 'dark' or 'light'
86
86
  browser: 'dark',
87
-
87
+
88
88
  // Background: color, gradient, or image URL
89
89
  background: 'linear-gradient(225deg, #FF057C 0%, #8D0B93 50%, #321575 100%)',
90
-
90
+
91
91
  // Margin around the screenshot (default: 0.2 = 20%)
92
92
  margin: 0.2
93
93
  }
@@ -149,8 +149,114 @@ const buffer = await browserless.screenshot('https://api.example.com/data', {
149
149
  })
150
150
  ```
151
151
 
152
- Available themes from [prism-themes](https://github.com/PrismJS/prism-themes):
153
- - `atom-dark`, `ghcolors`, `dracula`, `duotone-dark`, `duotone-light`, `material-dark`, `material-light`, `nord`, `synthwave84`, and more
152
+ Available themes from [automad-prism-themes](https://github.com/automadcms/automad-prism-themes) and [prism-themes](https://github.com/PrismJS/prism-themes). When a theme exists in both, the automad version is used.
153
+
154
+ | Theme | Source |
155
+ | --------------------------------- | ------------ |
156
+ | `a11y-dark` | prism-themes |
157
+ | `atom-dark` | automad |
158
+ | `atom-one-dark` | automad |
159
+ | `atom-one-light` | automad |
160
+ | `aura-dark` | automad |
161
+ | `automad-dark` | automad |
162
+ | `automad-light` | automad |
163
+ | `ayu-dark` | automad |
164
+ | `ayu-light` | automad |
165
+ | `ayu-mirage` | automad |
166
+ | `base` | automad |
167
+ | `base16-ateliersulphurpool.light` | prism-themes |
168
+ | `bearded-arc-blueberry` | automad |
169
+ | `bearded-vivid-light` | automad |
170
+ | `boola-dark` | automad |
171
+ | `boola-light` | automad |
172
+ | `catppuccin-frappe` | automad |
173
+ | `catppuccin-latte` | automad |
174
+ | `catppuccin-macchiato` | automad |
175
+ | `catppuccin-mocha` | automad |
176
+ | `cb` | prism-themes |
177
+ | `coldark-cold` | automad |
178
+ | `coldark-dark` | automad |
179
+ | `coy-without-shadows` | prism-themes |
180
+ | `darcula` | prism-themes |
181
+ | `dark-frost` | automad |
182
+ | `dark-space` | automad |
183
+ | `dracula` | automad |
184
+ | `duotone-dark` | automad |
185
+ | `duotone-earth` | automad |
186
+ | `duotone-forest` | automad |
187
+ | `duotone-light` | automad |
188
+ | `duotone-sea` | automad |
189
+ | `duotone-space` | automad |
190
+ | `ghcolors` | prism-themes |
191
+ | `github-dark` | automad |
192
+ | `github-light` | automad |
193
+ | `gruvbox-dark` | automad |
194
+ | `gruvbox-light` | automad |
195
+ | `holi-theme` | prism-themes |
196
+ | `hopscotch` | prism-themes |
197
+ | `laserwave` | automad |
198
+ | `lucario` | prism-themes |
199
+ | `material-dark` | prism-themes |
200
+ | `material-light` | prism-themes |
201
+ | `material-oceanic` | prism-themes |
202
+ | `night-owl` | automad |
203
+ | `night-owl-light` | automad |
204
+ | `nightfall` | automad |
205
+ | `nord` | automad |
206
+ | `one-dark` | prism-themes |
207
+ | `one-light` | prism-themes |
208
+ | `panda` | automad |
209
+ | `poimandres` | automad |
210
+ | `pojoaque` | prism-themes |
211
+ | `rose-pine` | automad |
212
+ | `rose-pine-dawn` | automad |
213
+ | `sakura-sun` | automad |
214
+ | `sea-shells-dark` | automad |
215
+ | `serendipity-midnight` | automad |
216
+ | `serendipity-morning` | automad |
217
+ | `serendipity-sunset` | automad |
218
+ | `shades-of-purple` | automad |
219
+ | `solarized-dark-atom` | automad |
220
+ | `synthwave84` | automad |
221
+ | `tailwind-ice` | automad |
222
+ | `tailwind-moon-blue` | automad |
223
+ | `tokyo-night` | automad |
224
+ | `tokyo-night-light` | automad |
225
+ | `tokyo-night-storm` | automad |
226
+ | `verdandi` | automad |
227
+ | `verdandi-alter` | automad |
228
+ | `violet-dream` | automad |
229
+ | `vs` | prism-themes |
230
+ | `vsc-dark-plus` | automad |
231
+ | `xonokai` | prism-themes |
232
+ | `z-touch` | prism-themes |
233
+
234
+ Some themes also offer light/dark combo variants that bundle both modes in a single CSS file, switching automatically based on the page's dark mode class. Since screenshots render without a dark mode context, the light variant will always be used — prefer explicit themes like `github-light` or `github-dark` instead.
235
+
236
+ Available combo themes:
237
+
238
+ | Combo theme | Light | Dark |
239
+ | ---------------------------------- | --------------------- | ----------------------- |
240
+ | `atom-one.light-dark` | `atom-one-light` | `atom-one-dark` |
241
+ | `automad.light-dark` | `automad-light` | `automad-dark` |
242
+ | `ayu.light-dark` | `ayu-light` | `ayu-dark` |
243
+ | `ayu-mirage.light-dark` | `ayu-light` | `ayu-mirage` |
244
+ | `bearded-arc-blueberry.light-dark` | `bearded-vivid-light` | `bearded-arc-blueberry` |
245
+ | `boola.light-dark` | `boola-light` | `boola-dark` |
246
+ | `catppuccin-frappe.light-dark` | `catppuccin-latte` | `catppuccin-frappe` |
247
+ | `catppuccin-macchiato.light-dark` | `catppuccin-latte` | `catppuccin-macchiato` |
248
+ | `catppuccin-mocha.light-dark` | `catppuccin-latte` | `catppuccin-mocha` |
249
+ | `coldark.light-dark` | `coldark-cold` | `coldark-dark` |
250
+ | `github.light-dark` | `github-light` | `github-dark` |
251
+ | `gruvbox.light-dark` | `gruvbox-light` | `gruvbox-dark` |
252
+ | `night-owl.light-dark` | `night-owl-light` | `night-owl` |
253
+ | `rose-pine.light-dark` | `rose-pine-dawn` | `rose-pine` |
254
+ | `serendipity-midnight.light-dark` | `serendipity-morning` | `serendipity-midnight` |
255
+ | `serendipity-sunset.light-dark` | `serendipity-morning` | `serendipity-sunset` |
256
+ | `tailwind-moon-blue.light-dark` | `tailwind-ice` | `tailwind-moon-blue` |
257
+ | `tokyo-night-storm.light-dark` | `tokyo-night-light` | `tokyo-night-storm` |
258
+ | `tokyo-night.light-dark` | `tokyo-night-light` | `tokyo-night` |
259
+ | `verdandi.light-dark` | `verdandi` | `verdandi-alter` |
154
260
 
155
261
  ### Smart Content Detection
156
262
 
@@ -222,22 +328,22 @@ const buffer = await browserless.screenshot('https://example.com', {
222
328
 
223
329
  This is a **core functionality package** for screenshot capture:
224
330
 
225
- | Consumer | Purpose |
226
- |----------|---------|
227
- | `browserless` (core) | Provides the `.screenshot()` method |
228
- | `@browserless/cli` | Powers the `browserless screenshot` command |
229
- | `@browserless/pdf` | Uses `isWhiteScreenshot` for content detection |
331
+ | Consumer | Purpose |
332
+ | -------------------- | ---------------------------------------------- |
333
+ | `browserless` (core) | Provides the `.screenshot()` method |
334
+ | `@browserless/cli` | Powers the `browserless screenshot` command |
335
+ | `@browserless/pdf` | Uses `isWhiteScreenshot` for content detection |
230
336
 
231
337
  ### Dependencies
232
338
 
233
- | Package | Purpose |
234
- |---------|---------|
235
- | `@browserless/goto` | Page navigation with ad blocking |
236
- | `sharp` | Image composition for overlays; White/blank screenshot detection |
237
- | `prism-themes` | Syntax highlighting themes |
238
- | `svg-gradient` | Generate gradient backgrounds |
239
- | `got` | Fetch remote background images |
240
- | `is-html-content` | Detect if content is HTML vs code |
339
+ | Package | Purpose |
340
+ | ---------------------- | ---------------------------------------------------------------- |
341
+ | `@browserless/goto` | Page navigation with ad blocking |
342
+ | `sharp` | Image composition for overlays; White/blank screenshot detection |
343
+ | `automad-prism-themes` | Syntax highlighting themes |
344
+ | `svg-gradient` | Generate gradient backgrounds |
345
+ | `got` | Fetch remote background images |
346
+ | `is-html-content` | Detect if content is HTML vs code |
241
347
 
242
348
  ## License
243
349
 
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@browserless/screenshot",
3
3
  "description": "Capture high-quality screenshots of websites with overlay support, device emulation, and automated image optimization.",
4
4
  "homepage": "https://browserless.js.org/#/?id=screenshoturl-options",
5
- "version": "10.12.3",
5
+ "version": "10.12.4",
6
6
  "main": "src/index.js",
7
7
  "author": {
8
8
  "email": "hello@microlink.io",
@@ -35,6 +35,7 @@
35
35
  "@browserless/goto": "^10.11.4",
36
36
  "@kikobeats/content-type": "~1.0.3",
37
37
  "@kikobeats/time-span": "~1.0.11",
38
+ "automad-prism-themes": "~0.3.7",
38
39
  "debug-logfmt": "~1.4.8",
39
40
  "got": "~11.8.6",
40
41
  "is-html-content": "~1.0.0",
@@ -70,5 +71,5 @@
70
71
  "timeout": "2m",
71
72
  "workerThreads": false
72
73
  },
73
- "gitHead": "057ad616cae720a908af469a8e2c702fb826c88b"
74
+ "gitHead": "13b7b3d5e3e27a3e109936b5ae5b7fd0e6f17c44"
74
75
  }
@@ -5,18 +5,46 @@ const { readFile } = require('fs/promises')
5
5
  const isHttpUrl = require('is-url-http')
6
6
  const path = require('path')
7
7
 
8
+ const { existsSync, readdirSync } = require('fs')
9
+
8
10
  const CACHE = new NullProtoObj()
11
+ let themeIndex
9
12
 
10
- const GET_THEME_PATH = () => require('prism-themes').themesDirectory
13
+ const GET_THEME_INDEX = () => {
14
+ const automadRoot = path.dirname(require.resolve('automad-prism-themes/package.json'))
15
+ const { themesDirectory } = require('automad-prism-themes')
16
+ const prismRoot = path.dirname(require.resolve('prism-themes/package.json'))
17
+ const { themesDirectory: prismThemesDirectory } = require('prism-themes')
11
18
 
12
- const THEME_PATH = () => CACHE.root || (CACHE.root = GET_THEME_PATH())
19
+ const dirs = [
20
+ themesDirectory,
21
+ path.resolve(automadRoot, 'dist'),
22
+ prismThemesDirectory,
23
+ path.resolve(prismRoot, 'themes')
24
+ ].filter(dir => dir && existsSync(dir))
13
25
 
14
- module.exports = async themeId => {
15
- if (isHttpUrl(themeId)) return `<link rel="stylesheet" type="text/css" href="${themeId}">`
26
+ const index = new NullProtoObj()
27
+ for (const dir of dirs) {
28
+ for (const file of readdirSync(dir)) {
29
+ const match = file.match(/^prism-(.+)\.css$/)
30
+ if (match && !match[1].endsWith('.min') && !(match[1] in index)) {
31
+ index[match[1]] = path.resolve(dir, file)
32
+ }
33
+ }
34
+ }
35
+ return index
36
+ }
16
37
 
17
- const stylesheet =
18
- CACHE[themeId] ||
19
- (CACHE[themeId] = await readFile(path.resolve(THEME_PATH(), `prism-${themeId}.css`)))
38
+ const THEME_INDEX = () => themeIndex || (themeIndex = GET_THEME_INDEX())
20
39
 
21
- return `<style>${stylesheet}</style>`
40
+ const readTheme = async themeId => {
41
+ const filePath = THEME_INDEX()[themeId]
42
+ if (!filePath) throw new Error(`Unable to resolve Prism theme: ${themeId}`)
43
+ return readFile(filePath)
44
+ }
45
+
46
+ module.exports = async themeId => {
47
+ if (isHttpUrl(themeId)) return `<link rel="stylesheet" type="text/css" href="${themeId}">`
48
+ CACHE[themeId] = CACHE[themeId] || (await readTheme(themeId))
49
+ return `<style>${CACHE[themeId]}</style>`
22
50
  }