@browserless/screenshot 13.1.6 → 13.1.8
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/package.json +5 -4
- package/src/index.js +32 -8
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": "13.1.
|
|
5
|
+
"version": "13.1.8",
|
|
6
6
|
"main": "src/index.js",
|
|
7
7
|
"author": {
|
|
8
8
|
"email": "hello@microlink.io",
|
|
@@ -32,7 +32,8 @@
|
|
|
32
32
|
"web-capture"
|
|
33
33
|
],
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@browserless/
|
|
35
|
+
"@browserless/errors": "13.1.7",
|
|
36
|
+
"@browserless/goto": "13.1.8",
|
|
36
37
|
"@kikobeats/content-type": "~1.0.4",
|
|
37
38
|
"@kikobeats/time-span": "~1.0.12",
|
|
38
39
|
"automad-prism-themes": "~0.3.7",
|
|
@@ -51,7 +52,7 @@
|
|
|
51
52
|
"svg-gradient": "~1.0.4"
|
|
52
53
|
},
|
|
53
54
|
"devDependencies": {
|
|
54
|
-
"@browserless/test": "13.1.
|
|
55
|
+
"@browserless/test": "13.1.8",
|
|
55
56
|
"ava": "5"
|
|
56
57
|
},
|
|
57
58
|
"engines": {
|
|
@@ -70,5 +71,5 @@
|
|
|
70
71
|
"timeout": "2m",
|
|
71
72
|
"workerThreads": false
|
|
72
73
|
},
|
|
73
|
-
"gitHead": "
|
|
74
|
+
"gitHead": "c47bf305151f14340462c59ae0f47aadeb993e16"
|
|
74
75
|
}
|
package/src/index.js
CHANGED
|
@@ -1,18 +1,34 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
const debug = require('debug-logfmt')('browserless:screenshot')
|
|
4
|
+
const { isContextDestroyed } = require('@browserless/errors')
|
|
4
5
|
const createGoto = require('@browserless/goto')
|
|
5
6
|
const pReflect = require('p-reflect')
|
|
6
7
|
|
|
7
8
|
const isWhiteScreenshot = require('./is-white-screenshot')
|
|
8
9
|
const waitForPrism = require('./pretty')
|
|
9
|
-
const
|
|
10
|
+
const prettyTimeSpan = require('./time-span')
|
|
10
11
|
const overlay = require('./overlay')
|
|
11
12
|
const { waitForDomStability, resolveWaitForDom, DEFAULT_WAIT_FOR_DOM } = require('./wait-for-dom')
|
|
12
13
|
|
|
13
|
-
const
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
const timeSpan = require('@kikobeats/time-span')()
|
|
15
|
+
|
|
16
|
+
// Retry a page capture (screenshot/pdf) that races with a client-side
|
|
17
|
+
// navigation. When the execution context is destroyed mid-capture, the page is
|
|
18
|
+
// navigating: wait for it to settle via `waitUntilAuto` and retry in-place,
|
|
19
|
+
// bounded by `timeout`, rather than failing the whole request. SPAs (e.g.
|
|
20
|
+
// scribd) navigate client-side after load, so the initial capture often races.
|
|
21
|
+
const captureWithNavigationRetry = async (capture, { page, goto, timeout }) => {
|
|
22
|
+
const elapsed = timeSpan()
|
|
23
|
+
while (true) {
|
|
24
|
+
try {
|
|
25
|
+
return await capture()
|
|
26
|
+
} catch (error) {
|
|
27
|
+
if (!isContextDestroyed(error) || elapsed() >= timeout) throw error
|
|
28
|
+
debug('captureWithNavigationRetry', { error: error.message })
|
|
29
|
+
await goto.waitUntilAuto(page, { timeout })
|
|
30
|
+
}
|
|
31
|
+
}
|
|
16
32
|
}
|
|
17
33
|
|
|
18
34
|
const getPageSnapshot = page =>
|
|
@@ -170,13 +186,17 @@ module.exports = ({ goto, ...gotoOpts }) => {
|
|
|
170
186
|
|
|
171
187
|
const takeScreenshot = async opts => {
|
|
172
188
|
const timeout = goto.timeouts.action(opts.timeout)
|
|
173
|
-
const elapsed =
|
|
189
|
+
const elapsed = timeSpan()
|
|
174
190
|
let retry = 0
|
|
175
191
|
let isWhite = false
|
|
176
192
|
let isReady = false
|
|
177
193
|
|
|
178
194
|
do {
|
|
179
|
-
screenshot = await page.screenshot(opts)
|
|
195
|
+
screenshot = await captureWithNavigationRetry(() => page.screenshot(opts), {
|
|
196
|
+
page,
|
|
197
|
+
goto,
|
|
198
|
+
timeout
|
|
199
|
+
})
|
|
180
200
|
isWhite = await isWhiteScreenshot(screenshot)
|
|
181
201
|
const snapshotResult = await pReflect(getPageSnapshot(page))
|
|
182
202
|
const pageSnapshot = snapshotResult.isRejected ? {} : snapshotResult.value
|
|
@@ -205,12 +225,15 @@ module.exports = ({ goto, ...gotoOpts }) => {
|
|
|
205
225
|
page.on('dialog', onDialog)
|
|
206
226
|
|
|
207
227
|
try {
|
|
208
|
-
const timeScreenshot =
|
|
228
|
+
const timeScreenshot = prettyTimeSpan()
|
|
209
229
|
|
|
210
230
|
if (waitUntil !== 'auto') {
|
|
211
231
|
;({ response } = await goto(page, { ...opts, url, waitUntil }))
|
|
212
232
|
const screenshotOpts = await beforeScreenshot(page, response, opts)
|
|
213
|
-
screenshot = await
|
|
233
|
+
screenshot = await captureWithNavigationRetry(
|
|
234
|
+
() => page.screenshot({ ...opts, ...screenshotOpts }),
|
|
235
|
+
{ page, goto, timeout: goto.timeouts.action(opts.timeout) }
|
|
236
|
+
)
|
|
214
237
|
debug('screenshot', { waitUntil, duration: timeScreenshot() })
|
|
215
238
|
} else {
|
|
216
239
|
;({ response } = await goto(page, { ...opts, url, waitUntil, waitUntilAuto }))
|
|
@@ -242,6 +265,7 @@ module.exports = ({ goto, ...gotoOpts }) => {
|
|
|
242
265
|
}
|
|
243
266
|
}
|
|
244
267
|
|
|
268
|
+
module.exports.captureWithNavigationRetry = captureWithNavigationRetry
|
|
245
269
|
module.exports.isWhiteScreenshot = isWhiteScreenshot
|
|
246
270
|
module.exports.waitForDomStability = waitForDomStability
|
|
247
271
|
module.exports.resolveWaitForDom = resolveWaitForDom
|