@browserless/screenshot 10.11.4 → 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.11.4",
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": "9ff2a0f0dad20d64a5c47a04a989ee77d1ee5ae8"
74
+ "gitHead": "13b7b3d5e3e27a3e109936b5ae5b7fd0e6f17c44"
74
75
  }
@@ -1,11 +1,11 @@
1
- /* PrismJS 1.29.0
1
+ /* PrismJS 1.30.0
2
2
  https://prismjs.com/download.html#themes=prism&languages=clike+javascript */
3
3
  var _self =
4
4
  'undefined' != typeof window
5
5
  ? window
6
6
  : 'undefined' != typeof WorkerGlobalScope && self instanceof WorkerGlobalScope
7
- ? self
8
- : {},
7
+ ? self
8
+ : {},
9
9
  Prism = (function (e) {
10
10
  var n = /(?:^|\s)lang(?:uage)?-([\w-]+)(?=\s|$)/i,
11
11
  t = 0,
@@ -18,8 +18,8 @@ var _self =
18
18
  return n instanceof i
19
19
  ? new i(n.type, e(n.content), n.alias)
20
20
  : Array.isArray(n)
21
- ? n.map(e)
22
- : n
21
+ ? n.map(e)
22
+ : n
23
23
  .replace(/&/g, '&')
24
24
  .replace(/</g, '&lt;')
25
25
  .replace(/\u00a0/g, ' ')
@@ -43,11 +43,11 @@ var _self =
43
43
  t[i]
44
44
  ? t[i]
45
45
  : ((r = []),
46
- (t[i] = r),
47
- n.forEach(function (n, a) {
48
- r[a] = e(n, t)
49
- }),
50
- r)
46
+ (t[i] = r),
47
+ n.forEach(function (n, a) {
48
+ r[a] = e(n, t)
49
+ }),
50
+ r)
51
51
  )
52
52
  default:
53
53
  return n
@@ -67,7 +67,8 @@ var _self =
67
67
  },
68
68
  currentScript: function () {
69
69
  if ('undefined' == typeof document) return null
70
- if ('currentScript' in document) return document.currentScript
70
+ if (document.currentScript && 'SCRIPT' === document.currentScript.tagName)
71
+ return document.currentScript
71
72
  try {
72
73
  throw new Error()
73
74
  } catch (r) {
@@ -254,38 +255,38 @@ var _self =
254
255
  w !== n.tail && !(g && A >= g.reach);
255
256
  A += w.value.length, w = w.next
256
257
  ) {
257
- var E = w.value
258
+ var P = w.value
258
259
  if (n.length > e.length) return
259
- if (!(E instanceof i)) {
260
- var P,
261
- L = 1
260
+ if (!(P instanceof i)) {
261
+ var E,
262
+ S = 1
262
263
  if (y) {
263
- if (!(P = l(b, A, e, m)) || P.index >= e.length) break
264
- var S = P.index,
265
- O = P.index + P[0].length,
266
- j = A
267
- for (j += w.value.length; S >= j; ) j += (w = w.next).value.length
268
- if (((A = j -= w.value.length), w.value instanceof i)) continue
269
- for (var C = w; C !== n.tail && (j < O || 'string' == typeof C.value); C = C.next)
270
- L++, (j += C.value.length)
271
- L--, (E = e.slice(A, j)), (P.index -= A)
272
- } else if (!(P = l(b, 0, E, m))) continue
273
- S = P.index
274
- var N = P[0],
275
- _ = E.slice(0, S),
276
- M = E.slice(S + N.length),
277
- W = A + E.length
264
+ if (!(E = l(b, A, e, m)) || E.index >= e.length) break
265
+ var L = E.index,
266
+ O = E.index + E[0].length,
267
+ C = A
268
+ for (C += w.value.length; L >= C; ) C += (w = w.next).value.length
269
+ if (((A = C -= w.value.length), w.value instanceof i)) continue
270
+ for (var j = w; j !== n.tail && (C < O || 'string' == typeof j.value); j = j.next)
271
+ S++, (C += j.value.length)
272
+ S--, (P = e.slice(A, C)), (E.index -= A)
273
+ } else if (!(E = l(b, 0, P, m))) continue
274
+ L = E.index
275
+ var N = E[0],
276
+ _ = P.slice(0, L),
277
+ M = P.slice(L + N.length),
278
+ W = A + P.length
278
279
  g && W > g.reach && (g.reach = W)
279
- var z = w.prev
280
+ var I = w.prev
280
281
  if (
281
- (_ && ((z = u(n, z, _)), (A += _.length)),
282
- c(n, z, L),
283
- (w = u(n, z, new i(f, p ? a.tokenize(N, p) : N, k, N))),
282
+ (_ && ((I = u(n, I, _)), (A += _.length)),
283
+ c(n, I, S),
284
+ (w = u(n, I, new i(f, p ? a.tokenize(N, p) : N, k, N))),
284
285
  M && u(n, w, M),
285
- L > 1)
286
+ S > 1)
286
287
  ) {
287
- var I = { cause: f + ',' + d, reach: W }
288
- o(e, n, t, w.prev, A, I), g && I.reach > g.reach && (g.reach = I.reach)
288
+ var T = { cause: f + ',' + d, reach: W }
289
+ o(e, n, t, w.prev, A, T), g && T.reach > g.reach && (g.reach = T.reach)
289
290
  }
290
291
  }
291
292
  }
@@ -351,18 +352,18 @@ var _self =
351
352
  )
352
353
  return e.addEventListener
353
354
  ? (a.disableWorkerMessageHandler ||
354
- e.addEventListener(
355
- 'message',
356
- function (n) {
357
- var t = JSON.parse(n.data),
358
- r = t.language,
359
- i = t.code,
360
- l = t.immediateClose
361
- e.postMessage(a.highlight(i, a.languages[r], r)), l && e.close()
362
- },
363
- !1
364
- ),
365
- a)
355
+ e.addEventListener(
356
+ 'message',
357
+ function (n) {
358
+ var t = JSON.parse(n.data),
359
+ r = t.language,
360
+ i = t.code,
361
+ l = t.immediateClose
362
+ e.postMessage(a.highlight(i, a.languages[r], r)), l && e.close()
363
+ },
364
+ !1
365
+ ),
366
+ a)
366
367
  : a
367
368
  var g = a.util.currentScript()
368
369
  function f () {
@@ -375,8 +376,8 @@ var _self =
375
376
  'loading' === h || ('interactive' === h && g && g.defer)
376
377
  ? document.addEventListener('DOMContentLoaded', f)
377
378
  : window.requestAnimationFrame
378
- ? window.requestAnimationFrame(f)
379
- : window.setTimeout(f, 16)
379
+ ? window.requestAnimationFrame(f)
380
+ : window.setTimeout(f, 16)
380
381
  }
381
382
  return a
382
383
  })(_self)
@@ -389,11 +390,13 @@ Prism.languages.clike = {
389
390
  ],
390
391
  string: { pattern: /(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/, greedy: !0 },
391
392
  'class-name': {
392
- pattern: /(\b(?:class|extends|implements|instanceof|interface|new|trait)\s+|\bcatch\s+\()[\w.\\]+/i,
393
+ pattern:
394
+ /(\b(?:class|extends|implements|instanceof|interface|new|trait)\s+|\bcatch\s+\()[\w.\\]+/i,
393
395
  lookbehind: !0,
394
396
  inside: { punctuation: /[.\\]/ }
395
397
  },
396
- keyword: /\b(?:break|catch|continue|do|else|finally|for|function|if|in|instanceof|new|null|return|throw|try|while)\b/,
398
+ keyword:
399
+ /\b(?:break|catch|continue|do|else|finally|for|function|if|in|instanceof|new|null|return|throw|try|while)\b/,
397
400
  boolean: /\b(?:false|true)\b/,
398
401
  function: /\b\w+(?=\()/,
399
402
  number: /\b0x[\da-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?/i,
@@ -404,29 +407,32 @@ Prism.languages.clike = {
404
407
  'class-name': [
405
408
  Prism.languages.clike['class-name'],
406
409
  {
407
- pattern: /(^|[^$\w\xA0-\uFFFF])(?!\s)[_$A-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\.(?:constructor|prototype))/,
410
+ pattern:
411
+ /(^|[^$\w\xA0-\uFFFF])(?!\s)[_$A-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\.(?:constructor|prototype))/,
408
412
  lookbehind: !0
409
413
  }
410
414
  ],
411
415
  keyword: [
412
416
  { pattern: /((?:^|\})\s*)catch\b/, lookbehind: !0 },
413
417
  {
414
- pattern: /(^|[^.]|\.\.\.\s*)\b(?:as|assert(?=\s*\{)|async(?=\s*(?:function\b|\(|[$\w\xA0-\uFFFF]|$))|await|break|case|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally(?=\s*(?:\{|$))|for|from(?=\s*(?:['"]|$))|function|(?:get|set)(?=\s*(?:[#\[$\w\xA0-\uFFFF]|$))|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)\b/,
418
+ pattern:
419
+ /(^|[^.]|\.\.\.\s*)\b(?:as|assert(?=\s*\{)|async(?=\s*(?:function\b|\(|[$\w\xA0-\uFFFF]|$))|await|break|case|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally(?=\s*(?:\{|$))|for|from(?=\s*(?:['"]|$))|function|(?:get|set)(?=\s*(?:[#\[$\w\xA0-\uFFFF]|$))|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)\b/,
415
420
  lookbehind: !0
416
421
  }
417
422
  ],
418
- function: /#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*(?:\.\s*(?:apply|bind|call)\s*)?\()/,
423
+ function:
424
+ /#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*(?:\.\s*(?:apply|bind|call)\s*)?\()/,
419
425
  number: {
420
426
  pattern: RegExp(
421
427
  '(^|[^\\w$])(?:NaN|Infinity|0[bB][01]+(?:_[01]+)*n?|0[oO][0-7]+(?:_[0-7]+)*n?|0[xX][\\dA-Fa-f]+(?:_[\\dA-Fa-f]+)*n?|\\d+(?:_\\d+)*n|(?:\\d+(?:_\\d+)*(?:\\.(?:\\d+(?:_\\d+)*)?)?|\\.\\d+(?:_\\d+)*)(?:[Ee][+-]?\\d+(?:_\\d+)*)?)(?![\\w$])'
422
428
  ),
423
429
  lookbehind: !0
424
430
  },
425
- operator: /--|\+\+|\*\*=?|=>|&&=?|\|\|=?|[!=]==|<<=?|>>>?=?|[-+*/%&|^!=<>]=?|\.{3}|\?\?=?|\?\.?|[~:]/
431
+ operator:
432
+ /--|\+\+|\*\*=?|=>|&&=?|\|\|=?|[!=]==|<<=?|>>>?=?|[-+*/%&|^!=<>]=?|\.{3}|\?\?=?|\?\.?|[~:]/
426
433
  })),
427
- (Prism.languages.javascript[
428
- 'class-name'
429
- ][0].pattern = /(\b(?:class|extends|implements|instanceof|interface|new)\s+)[\w.\\]+/),
434
+ (Prism.languages.javascript['class-name'][0].pattern =
435
+ /(\b(?:class|extends|implements|instanceof|interface|new)\s+)[\w.\\]+/),
430
436
  Prism.languages.insertBefore('javascript', 'keyword', {
431
437
  regex: {
432
438
  pattern: RegExp(
@@ -446,17 +452,20 @@ Prism.languages.clike = {
446
452
  }
447
453
  },
448
454
  'function-variable': {
449
- pattern: /#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*[=:]\s*(?:async\s*)?(?:\bfunction\b|(?:\((?:[^()]|\([^()]*\))*\)|(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)\s*=>))/,
455
+ pattern:
456
+ /#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*[=:]\s*(?:async\s*)?(?:\bfunction\b|(?:\((?:[^()]|\([^()]*\))*\)|(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)\s*=>))/,
450
457
  alias: 'function'
451
458
  },
452
459
  parameter: [
453
460
  {
454
- pattern: /(function(?:\s+(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)?\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\))/,
461
+ pattern:
462
+ /(function(?:\s+(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)?\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\))/,
455
463
  lookbehind: !0,
456
464
  inside: Prism.languages.javascript
457
465
  },
458
466
  {
459
- pattern: /(^|[^$\w\xA0-\uFFFF])(?!\s)[_$a-z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*=>)/i,
467
+ pattern:
468
+ /(^|[^$\w\xA0-\uFFFF])(?!\s)[_$a-z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*=>)/i,
460
469
  lookbehind: !0,
461
470
  inside: Prism.languages.javascript
462
471
  },
@@ -466,7 +475,8 @@ Prism.languages.clike = {
466
475
  inside: Prism.languages.javascript
467
476
  },
468
477
  {
469
- pattern: /((?:\b|\s|^)(?!(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)(?![$\w\xA0-\uFFFF]))(?:(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*)\(\s*|\]\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*\{)/,
478
+ pattern:
479
+ /((?:\b|\s|^)(?!(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)(?![$\w\xA0-\uFFFF]))(?:(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*)\(\s*|\]\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*\{)/,
470
480
  lookbehind: !0,
471
481
  inside: Prism.languages.javascript
472
482
  }
@@ -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
  }