Skip to content

Commit 9c368ed

Browse files
committed
feat(chrome-renderer): add headless chrome renderer
1 parent d8f357b commit 9c368ed

File tree

1 file changed

+150
-0
lines changed

1 file changed

+150
-0
lines changed

src/renderers/chrome/index.js

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
import _ from 'lodash';
2+
import path from 'path';
3+
import puppeteer from 'puppeteer';
4+
5+
import Renderer from '../../renderer';
6+
7+
const { isString } = _;
8+
9+
const DEFAULT_BOOT_OPTIONS = {}; // use puppeteer defaults, https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#puppeteerlaunchoptions
10+
11+
export class ChromeRenderer extends Renderer {
12+
static get DEFAULT_BOOT_OPTIONS() {
13+
return this._DEFAULT_BOOT_OPTIONS || DEFAULT_BOOT_OPTIONS;
14+
}
15+
16+
static set DEFAULT_BOOT_OPTIONS(value) {
17+
this._DEFAULT_BOOT_OPTIONS = value;
18+
}
19+
20+
constructor(attrs = {}) {
21+
super(attrs);
22+
23+
this.bootOptions = this.bootOptions ||
24+
this.constructor.DEFAULT_BOOT_OPTIONS;
25+
}
26+
27+
get browser() {
28+
return this._browser;
29+
}
30+
31+
set browser(value) {
32+
this._browser = value;
33+
}
34+
35+
get bootOptions() {
36+
return this._bootOptions;
37+
}
38+
39+
set bootOptions(value) {
40+
this._bootOptions = value;
41+
}
42+
43+
async boot() {
44+
if (this.isBooted) {
45+
return;
46+
}
47+
48+
try {
49+
if (!this.isBooting) {
50+
let bootOptions = this.bootOptions;
51+
52+
this.isBooting = true;
53+
this.browser = bootOptions.hasOwnProperty('browserWSEndpoint') ?
54+
await puppeteer.connect(bootOptions) :
55+
await puppeteer.launch(bootOptions);
56+
57+
this.isBooted = true;
58+
}
59+
} catch (err) {
60+
this.isBooted = false;
61+
throw err;
62+
}
63+
}
64+
65+
async shutdown() {
66+
let browser = this.browser;
67+
68+
if (browser !== null && browser !== undefined) {
69+
browser.close();
70+
this.browser = undefined;
71+
}
72+
73+
this.isBooted = false;
74+
}
75+
76+
async ping() {
77+
return this.browser.pages();
78+
}
79+
80+
async loadPage(page, options) {
81+
let chromePage = page._chromePage;
82+
83+
if (chromePage === null || chromePage === undefined) {
84+
chromePage = await this.browser.newPage();
85+
page._chromePage = chromePage;
86+
}
87+
88+
page.isLoading = true;
89+
90+
try {
91+
let { url, html } = options;
92+
93+
if (html !== undefined && html !== null) {
94+
await chromePage.setContent(html);
95+
} else {
96+
if (url !== undefined && url !== null) {
97+
delete options.url;
98+
} else {
99+
url = page.id;
100+
}
101+
102+
await chromePage.goto(url, options);
103+
}
104+
105+
page.isLoaded = true;
106+
} catch (err) {
107+
page.isLoaded = false;
108+
throw err;
109+
}
110+
}
111+
112+
async renderPage(page, options = {}) {
113+
let { path: filepath, type } = options;
114+
let buffer;
115+
116+
if (!isString(type)) {
117+
type = isString(filepath) ? path.extname(filepath).slice(1) : 'html';
118+
type = type.length > 0 ? type : 'html';
119+
}
120+
121+
switch (type) {
122+
case 'html':
123+
buffer = await page._chromePage.content();
124+
break;
125+
case 'pdf':
126+
let { emulateMedia } = options;
127+
128+
if (emulateMedia !== null && emulateMedia !== undefined) {
129+
await page._chromePage.emulateMedia(emulateMedia);
130+
delete options.emulateMedia;
131+
}
132+
133+
buffer = await page._chromePage.pdf(options);
134+
break;
135+
default:
136+
buffer = await page._chromePage.screenshot(options);
137+
break;
138+
}
139+
140+
return isString(filepath) ? filepath : buffer;
141+
}
142+
143+
async unloadPage(page, ...args) {
144+
await page._chromePage.close();
145+
146+
return true;
147+
}
148+
}
149+
150+
export default ChromeRenderer;

0 commit comments

Comments
 (0)