@browserless/pdf 10.10.0 → 10.10.2

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.
Files changed (3) hide show
  1. package/README.md +5 -3
  2. package/package.json +4 -4
  3. package/src/index.js +37 -14
package/README.md CHANGED
@@ -73,6 +73,7 @@ The package applies these optimized defaults:
73
73
  | `scale` | `number` | `0.65` | Scale of the webpage rendering (0.1 - 2) |
74
74
  | `printBackground` | `boolean` | `true` | Print background graphics |
75
75
  | `waitUntil` | `string` | `'auto'` | When to consider navigation done |
76
+ | `waitForDom` | `number` | `1000` | DOM stability window in ms (idle is `waitForDom / 10`) |
76
77
  | `format` | `string` | `'Letter'` | Paper format (A4, Letter, etc.) |
77
78
  | `landscape` | `boolean` | `false` | Paper orientation |
78
79
  | `width` | `string \| number` | — | Paper width (overrides format) |
@@ -111,9 +112,10 @@ Supported units: `px`, `in`, `cm`, `mm`
111
112
  When `waitUntil: 'auto'` (the default), the package:
112
113
 
113
114
  1. Navigates to the page
114
- 2. Takes a low-quality screenshot to check for white/blank content
115
- 3. If the page appears blank, retries until content is detected
116
- 4. Generates the PDF once content is confirmed
115
+ 2. Waits for DOM stability (`waitForDom`, default `1000ms`)
116
+ 3. Takes a low-quality screenshot to check for white/blank content
117
+ 4. If the page appears blank, retries until content is detected
118
+ 5. Generates the PDF once content is confirmed
117
119
 
118
120
  This ensures dynamic content (JavaScript-rendered pages) is fully loaded before PDF generation.
119
121
 
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@browserless/pdf",
3
3
  "description": "Convert websites to high-quality PDFs with customizable margins, background printing, and optimized scaling.",
4
4
  "homepage": "https://browserless.js.org/#/?id=pdfurl-options",
5
- "version": "10.10.0",
5
+ "version": "10.10.2",
6
6
  "main": "src",
7
7
  "author": {
8
8
  "email": "hello@microlink.io",
@@ -30,8 +30,8 @@
30
30
  "conversion"
31
31
  ],
32
32
  "dependencies": {
33
- "@browserless/goto": "^10.10.0",
34
- "@browserless/screenshot": "^10.10.0",
33
+ "@browserless/goto": "^10.10.2",
34
+ "@browserless/screenshot": "^10.10.2",
35
35
  "@kikobeats/time-span": "~1.0.11",
36
36
  "debug-logfmt": "~1.4.7",
37
37
  "pretty-ms": "~7.0.1"
@@ -47,5 +47,5 @@
47
47
  "test": "exit 0"
48
48
  },
49
49
  "license": "MIT",
50
- "gitHead": "9b80e677418f2defb804d39043680fe65e3e277b"
50
+ "gitHead": "ec6a614923a1a692bd717ecc8e6f1b09417801d9"
51
51
  }
package/src/index.js CHANGED
@@ -1,7 +1,13 @@
1
1
  'use strict'
2
2
 
3
3
  const timeSpan = require('@kikobeats/time-span')({ format: n => Math.round(n) })
4
- const { isWhiteScreenshot } = require('@browserless/screenshot')
4
+ const pReflect = require('p-reflect')
5
+ const {
6
+ isWhiteScreenshot,
7
+ waitForDomStability,
8
+ resolveWaitForDom,
9
+ DEFAULT_WAIT_FOR_DOM
10
+ } = require('@browserless/screenshot')
5
11
  const debug = require('debug-logfmt')('browserless:pdf')
6
12
  const createGoto = require('@browserless/goto')
7
13
 
@@ -22,9 +28,17 @@ module.exports = ({ goto, ...gotoOpts } = {}) => {
22
28
  return function pdf (page) {
23
29
  return async (
24
30
  url,
25
- { margin = '0.35cm', scale = 0.65, printBackground = true, waitUntil = 'auto', ...opts } = {}
31
+ {
32
+ margin = '0.35cm',
33
+ scale = 0.65,
34
+ printBackground = true,
35
+ waitUntil = 'auto',
36
+ waitForDom = DEFAULT_WAIT_FOR_DOM,
37
+ ...opts
38
+ } = {}
26
39
  ) => {
27
40
  let pdfBuffer
41
+ const waitForDomOpts = resolveWaitForDom(waitForDom)
28
42
 
29
43
  const generatePdf = page =>
30
44
  page.pdf({
@@ -34,12 +48,24 @@ module.exports = ({ goto, ...gotoOpts } = {}) => {
34
48
  scale
35
49
  })
36
50
 
51
+ const waitForDomStabilityResult = async page => {
52
+ const result = await pReflect(page.evaluate(waitForDomStability, waitForDomOpts))
53
+ debug(
54
+ 'waitForDomStability',
55
+ result.isRejected
56
+ ? { ...waitForDomOpts, error: result.reason.message || result.reason }
57
+ : { ...waitForDomOpts, ...result.value }
58
+ )
59
+ }
60
+
37
61
  if (waitUntil !== 'auto') {
38
62
  await goto(page, { ...opts, url, waitUntil })
63
+ await waitForDomStabilityResult(page)
39
64
  pdfBuffer = await generatePdf(page)
40
65
  } else {
41
66
  await goto(page, { ...opts, url, waitUntil, waitUntilAuto })
42
67
  async function waitUntilAuto (page) {
68
+ await waitForDomStabilityResult(page)
43
69
  const timeout = goto.timeouts.action(opts.timeout)
44
70
  let isWhite = false
45
71
  let retry = -1
@@ -49,23 +75,20 @@ module.exports = ({ goto, ...gotoOpts } = {}) => {
49
75
  do {
50
76
  ++retry
51
77
  const screenshotTime = timeSpan()
52
- ;[isWhite, pdfBuffer] = await Promise.all([
53
- isWhiteScreenshot(
54
- await page.screenshot({
55
- ...opts,
56
- optimizeForSpeed: true,
57
- type: 'jpeg',
58
- quality: 30
59
- })
60
- ),
61
- generatePdf(page),
62
- retry === 1 ? goto.waitUntilAuto(page, { timeout: opts.timeout }) : Promise.resolve()
63
- ])
78
+ const screenshot = await page.screenshot({
79
+ ...opts,
80
+ optimizeForSpeed: true,
81
+ type: 'jpeg',
82
+ quality: 30
83
+ })
84
+ isWhite = await isWhiteScreenshot(screenshot)
85
+ if (retry === 1) await goto.waitUntilAuto(page, { timeout: opts.timeout })
64
86
  debug('retry', { waitUntil, isWhite, retry, duration: screenshotTime() })
65
87
  } while (isWhite && timePdf() < timeout)
66
88
 
67
89
  debug({ waitUntil, isWhite, timeout, duration: require('pretty-ms')(timePdf()) })
68
90
  }
91
+ pdfBuffer = await generatePdf(page)
69
92
  }
70
93
 
71
94
  return pdfBuffer