Skip to content

Commit f0982ea

Browse files
committed
chore(screenshot): use automad-prism-themes
1 parent 057ad61 commit f0982ea

File tree

7 files changed

+247
-405
lines changed

7 files changed

+247
-405
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -419,7 +419,7 @@ The color schemes is based on the [Prism library](https://prismjs.com).
419419

420420
![](https://i.imgur.com/uFfviX7.png)
421421

422-
The [Prism repository](https://github.com/PrismJS/prism-themes/tree/master?tab=readme-ov-file#available-themes) offers a wide range of themes to choose from as well as a [CDN option](https://unpkg.com/browse/[email protected]/themes).
422+
The [automad-prism-themes repository](https://github.com/automadcms/automad-prism-themes) offers a wide range of themes to choose from as well as a [CDN option](https://unpkg.com/browse/automad-prism-themes@latest/dist/).
423423

424424
##### element
425425

packages/screenshot/README.md

Lines changed: 57 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -61,17 +61,17 @@ const buffer = await browserless.screenshot('https://example.com', {
6161

6262
### Options
6363

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 |
7575

7676
All [Puppeteer page.screenshot() options](https://pptr.dev/api/puppeteer.screenshotoptions) are supported.
7777

@@ -84,10 +84,10 @@ const buffer = await browserless.screenshot(url, {
8484
overlay: {
8585
// Browser frame theme: 'dark' or 'light'
8686
browser: 'dark',
87-
87+
8888
// Background: color, gradient, or image URL
8989
background: 'linear-gradient(225deg, #FF057C 0%, #8D0B93 50%, #321575 100%)',
90-
90+
9191
// Margin around the screenshot (default: 0.2 = 20%)
9292
margin: 0.2
9393
}
@@ -149,8 +149,37 @@ const buffer = await browserless.screenshot('https://api.example.com/data', {
149149
})
150150
```
151151

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):
153+
- `atom-dark`, `github-light`, `github-dark`, `dracula`, `duotone-dark`, `duotone-light`, `nord`, `synthwave84`, `catppuccin-mocha`, `catppuccin-latte`, and [many more](https://github.com/automadcms/automad-prism-themes#available-themes)
154+
155+
Legacy [prism-themes](https://github.com/PrismJS/prism-themes) names are supported via aliases (e.g., `ghcolors``github-light`, `one-dark``atom-one-dark`, `material-dark``nightfall`).
156+
157+
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.
158+
159+
Available combo themes:
160+
161+
| Combo theme | Light | Dark |
162+
| ---------------------------------- | --------------------- | ----------------------- |
163+
| `atom-one.light-dark` | `atom-one-light` | `atom-one-dark` |
164+
| `automad.light-dark` | `automad-light` | `automad-dark` |
165+
| `ayu.light-dark` | `ayu-light` | `ayu-dark` |
166+
| `ayu-mirage.light-dark` | `ayu-light` | `ayu-mirage` |
167+
| `bearded-arc-blueberry.light-dark` | `bearded-vivid-light` | `bearded-arc-blueberry` |
168+
| `boola.light-dark` | `boola-light` | `boola-dark` |
169+
| `catppuccin-frappe.light-dark` | `catppuccin-latte` | `catppuccin-frappe` |
170+
| `catppuccin-macchiato.light-dark` | `catppuccin-latte` | `catppuccin-macchiato` |
171+
| `catppuccin-mocha.light-dark` | `catppuccin-latte` | `catppuccin-mocha` |
172+
| `coldark.light-dark` | `coldark-cold` | `coldark-dark` |
173+
| `github.light-dark` | `github-light` | `github-dark` |
174+
| `gruvbox.light-dark` | `gruvbox-light` | `gruvbox-dark` |
175+
| `night-owl.light-dark` | `night-owl-light` | `night-owl` |
176+
| `rose-pine.light-dark` | `rose-pine-dawn` | `rose-pine` |
177+
| `serendipity-midnight.light-dark` | `serendipity-morning` | `serendipity-midnight` |
178+
| `serendipity-sunset.light-dark` | `serendipity-morning` | `serendipity-sunset` |
179+
| `tailwind-moon-blue.light-dark` | `tailwind-ice` | `tailwind-moon-blue` |
180+
| `tokyo-night-storm.light-dark` | `tokyo-night-light` | `tokyo-night-storm` |
181+
| `tokyo-night.light-dark` | `tokyo-night-light` | `tokyo-night` |
182+
| `verdandi.light-dark` | `verdandi` | `verdandi-alter` |
154183

155184
### Smart Content Detection
156185

@@ -222,22 +251,22 @@ const buffer = await browserless.screenshot('https://example.com', {
222251

223252
This is a **core functionality package** for screenshot capture:
224253

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 |
254+
| Consumer | Purpose |
255+
| -------------------- | ---------------------------------------------- |
256+
| `browserless` (core) | Provides the `.screenshot()` method |
257+
| `@browserless/cli` | Powers the `browserless screenshot` command |
258+
| `@browserless/pdf` | Uses `isWhiteScreenshot` for content detection |
230259

231260
### Dependencies
232261

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 |
262+
| Package | Purpose |
263+
| ---------------------- | ---------------------------------------------------------------- |
264+
| `@browserless/goto` | Page navigation with ad blocking |
265+
| `sharp` | Image composition for overlays; White/blank screenshot detection |
266+
| `automad-prism-themes` | Syntax highlighting themes |
267+
| `svg-gradient` | Generate gradient backgrounds |
268+
| `got` | Fetch remote background images |
269+
| `is-html-content` | Detect if content is HTML vs code |
241270

242271
## License
243272

packages/screenshot/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545
"null-prototype-object": "~1.2.5",
4646
"p-reflect": "~2.1.0",
4747
"pretty-ms": "~7.0.1",
48-
"prism-themes": "~1.9.0",
48+
"automad-prism-themes": "~0.3.7",
4949
"sharp": "~0.34.5",
5050
"svg-gradient": "~1.0.4"
5151
},

packages/screenshot/src/pretty/theme.js

Lines changed: 57 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,67 @@ const path = require('path')
77

88
const CACHE = new NullProtoObj()
99

10-
const GET_THEME_PATH = () => require('prism-themes').themesDirectory
10+
const DEFAULT_THEME_ID = 'atom-dark'
1111

12-
const THEME_PATH = () => CACHE.root || (CACHE.root = GET_THEME_PATH())
12+
const THEME_ALIASES = {
13+
ghcolors: 'github-light',
14+
'one-dark': 'atom-one-dark',
15+
'one-light': 'atom-one-light',
16+
darcula: 'atom-one-dark',
17+
'a11y-dark': 'github-dark',
18+
cb: 'gruvbox-dark',
19+
'coy-without-shadows': 'github-light',
20+
'holi-theme': 'aura-dark',
21+
hopscotch: 'dracula',
22+
lucario: 'dark-space',
23+
'material-dark': 'nightfall',
24+
'material-light': 'catppuccin-latte',
25+
'material-oceanic': 'nightfall',
26+
pojoaque: 'gruvbox-dark',
27+
vs: 'github-light',
28+
xonokai: 'dracula',
29+
'z-touch': 'poimandres'
30+
}
31+
32+
const GET_THEME_PATHS = () => {
33+
const packageRoot = path.dirname(require.resolve('automad-prism-themes/package.json'))
34+
const { themesDirectory } = require('automad-prism-themes')
35+
36+
return [themesDirectory, path.resolve(packageRoot, 'dist'), packageRoot].filter(Boolean)
37+
}
38+
39+
const THEME_PATHS = () => CACHE.root || (CACHE.root = GET_THEME_PATHS())
40+
41+
const readTheme = async themeId => {
42+
const ids = [themeId]
43+
const alias = THEME_ALIASES[themeId]
44+
if (alias) ids.push(alias)
45+
46+
for (const id of ids) {
47+
for (const dirPath of THEME_PATHS()) {
48+
try {
49+
return await readFile(path.resolve(dirPath, `prism-${id}.css`))
50+
} catch (error) {
51+
if (error.code !== 'ENOENT') throw error
52+
}
53+
}
54+
}
55+
56+
throw new Error(`Unable to resolve Prism theme: ${themeId}`)
57+
}
1358

1459
module.exports = async themeId => {
1560
if (isHttpUrl(themeId)) return `<link rel="stylesheet" type="text/css" href="${themeId}">`
1661

17-
const stylesheet =
18-
CACHE[themeId] ||
19-
(CACHE[themeId] = await readFile(path.resolve(THEME_PATH(), `prism-${themeId}.css`)))
62+
try {
63+
CACHE[themeId] = CACHE[themeId] || (await readTheme(themeId))
64+
} catch (error) {
65+
if (themeId !== DEFAULT_THEME_ID) {
66+
CACHE[themeId] = CACHE[themeId] || (await readTheme(DEFAULT_THEME_ID))
67+
} else {
68+
throw error
69+
}
70+
}
2071

21-
return `<style>${stylesheet}</style>`
72+
return `<style>${CACHE[themeId]}</style>`
2273
}
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
/**
2+
* GHColors theme by Avi Aryan (http://aviaryan.in)
3+
* Inspired by Github syntax coloring
4+
*/
5+
6+
code[class*="language-"],
7+
pre[class*="language-"] {
8+
color: #393A34;
9+
font-family: "Consolas", "Bitstream Vera Sans Mono", "Courier New", Courier, monospace;
10+
direction: ltr;
11+
text-align: left;
12+
white-space: pre;
13+
word-spacing: normal;
14+
word-break: normal;
15+
font-size: .9em;
16+
line-height: 1.2em;
17+
18+
-moz-tab-size: 4;
19+
-o-tab-size: 4;
20+
tab-size: 4;
21+
22+
-webkit-hyphens: none;
23+
-moz-hyphens: none;
24+
-ms-hyphens: none;
25+
hyphens: none;
26+
}
27+
28+
pre > code[class*="language-"] {
29+
font-size: 1em;
30+
}
31+
32+
pre[class*="language-"]::-moz-selection, pre[class*="language-"] ::-moz-selection,
33+
code[class*="language-"]::-moz-selection, code[class*="language-"] ::-moz-selection {
34+
background: #b3d4fc;
35+
}
36+
37+
pre[class*="language-"]::selection, pre[class*="language-"] ::selection,
38+
code[class*="language-"]::selection, code[class*="language-"] ::selection {
39+
background: #b3d4fc;
40+
}
41+
42+
/* Code blocks */
43+
pre[class*="language-"] {
44+
padding: 1em;
45+
margin: .5em 0;
46+
overflow: auto;
47+
border: 1px solid #dddddd;
48+
background-color: white;
49+
}
50+
51+
/* Inline code */
52+
:not(pre) > code[class*="language-"] {
53+
padding: .2em;
54+
padding-top: 1px;
55+
padding-bottom: 1px;
56+
background: #f8f8f8;
57+
border: 1px solid #dddddd;
58+
}
59+
60+
.token.comment,
61+
.token.prolog,
62+
.token.doctype,
63+
.token.cdata {
64+
color: #999988;
65+
font-style: italic;
66+
}
67+
68+
.token.namespace {
69+
opacity: .7;
70+
}
71+
72+
.token.string,
73+
.token.attr-value {
74+
color: #e3116c;
75+
}
76+
77+
.token.punctuation,
78+
.token.operator {
79+
color: #393A34; /* no highlight */
80+
}
81+
82+
.token.entity,
83+
.token.url,
84+
.token.symbol,
85+
.token.number,
86+
.token.boolean,
87+
.token.variable,
88+
.token.constant,
89+
.token.property,
90+
.token.regex,
91+
.token.inserted {
92+
color: #36acaa;
93+
}
94+
95+
.token.atrule,
96+
.token.keyword,
97+
.token.attr-name,
98+
.language-autohotkey .token.selector {
99+
color: #00a4db;
100+
}
101+
102+
.token.function,
103+
.token.deleted,
104+
.language-autohotkey .token.tag {
105+
color: #9a050f;
106+
}
107+
108+
.token.tag,
109+
.token.selector,
110+
.language-autohotkey .token.keyword {
111+
color: #00009f;
112+
}
113+
114+
.token.important,
115+
.token.function,
116+
.token.bold {
117+
font-weight: bold;
118+
}
119+
120+
.token.italic {
121+
font-style: italic;
122+
}

0 commit comments

Comments
 (0)