diff --git a/src/app.ts b/src/app.ts index 51a88d9..a1c2501 100644 --- a/src/app.ts +++ b/src/app.ts @@ -2,7 +2,7 @@ import compression from 'compression'; import express from 'express'; import morgan from 'morgan'; import { getBrowser } from './browser.js'; -import render from './render.js'; +import { renderPdf, renderImage } from './render.js'; const app = express(); @@ -41,23 +41,21 @@ app.get('/.live', async (req, res, next) => { } }); -// render page -app.post('/', async (req, res, next) => { +// render pdf +const handleRender = (renderFunc, contentType) => async (req, res, next) => { try { - // get inputs from the json payload const { html = '', options = null } = req.body; - - // render the PDF - const pdf = await render(html, options); - - // reply with express - res.set('content-type', 'application/pdf'); - res.send(pdf); + const result = await renderFunc(html, options); + res.set('content-type', contentType); + res.send(result); } catch (error) { - // continue with the error next(error); } -}); +}; + +app.post('/image', handleRender(renderImage, 'image/jpeg')); +app.post('/pdf', handleRender(renderPdf, 'application/pdf')); +app.post('/', handleRender(renderPdf, 'application/pdf')); // error handler app.use((error, req, res, next) => { diff --git a/src/render.ts b/src/render.ts index e6a8186..103ce3e 100644 --- a/src/render.ts +++ b/src/render.ts @@ -7,6 +7,7 @@ export type RenderOptions = { viewport: puppeteer.Viewport; waitUntil: puppeteer.WaitForOptions['waitUntil']; pdf: puppeteer.PDFOptions; + image: puppeteer.ScreenshotOptions; }; const defaultOptions: RenderOptions = { @@ -14,9 +15,10 @@ const defaultOptions: RenderOptions = { viewport: { width: 1600, height: 1200 }, waitUntil: 'networkidle2', pdf: { format: 'a4', printBackground: true }, + image: {}, }; -const render = async (html: string, customOptions?: Partial | null) => { +export const renderPdf = async (html: string, customOptions?: Partial | null) => { const options = merge(defaultOptions, customOptions); // start browser @@ -57,4 +59,43 @@ const render = async (html: string, customOptions?: Partial | nul return pdf; }; -export default render; +export const renderImage = async (html: string, customOptions?: Partial | null) => { + const options = merge(defaultOptions, customOptions); + + // start browser + const browser = await getBrowser(); + // start page + const page = await browser.newPage(); + + // print on console + page.on('console', (...messages) => console.info('Console logs:', ...messages)); + + // print on error + page.on('error', err => { + console.error(`Error event emitted: ${err}`); + console.error(err.stack); + browser.close(); + }); + + let image: Buffer; + + try { + // set view port + await page.setViewport(options.viewport); + + if (options.emulateScreenMedia) { + await page.emulateMediaType('screen'); + } + + // set html content + await page.setContent(html, { waitUntil: options.waitUntil }); + + // render to image + image = (await page.screenshot(options.image)) as Buffer; + } finally { + // close the page + await page.close(); + } + + return image; +};