node-html-to-image

repository·master·Indexed 21 days ago

https://github.com/frinyvonnick/node-html-to-image

A Node.js library that generates PNG or JPEG images from HTML content using Puppeteer. It supports dynamic templating via Handlebars, TypeScript type definitions, and the ability to output images either as files or Buffers. Version 6.2.0 requires Node.js 22.12 or newer.

Tokens
5.2K
Snippets
18
Records
24
Agent score
75%

What's inside node-html-to-image

  1. Handle asset loading with `waitUntil: 'load'` in v6

    master

    In v6, the default waitUntil behavior is load, which does not wait for the network to be idle. This can result in missing remote images or fonts in your output.

    To fix this, you have two options:

    1. Use Base64: Embed your images and fonts directly into the HTML as base64 strings.
    2. Use beforeScreenshot: Manually wait for assets to load using the beforeScreenshot hook by evaluating a script on the page to check image completion.

    Example of waiting for images in beforeScreenshot:

    await nodeHtmlToImage({
      html: "<html><body><img src='https://example.com/logo.png' /></body></html>",
      beforeScreenshot: async (page) => {
        // wait until all images are loaded
        await page.evaluate(() =>
          Promise.all(
            Array.from(document.images).map((image) =>
              image.complete
                ? null
                : new Promise((done) => (image.onload = image.onerror = done)),
            ),
          );
        // Note: The snippet above requires a closing parenthesis for page.evaluate
      },
    });
    await nodeHtmlToImage({
      html: "<html><body><img src='https://example.com/logo.png' /></body></html>",
      beforeScreenshot: async (page) => {
        // wait until all images are loaded
        await page.evaluate(() =>
          Promise.all(
            Array.from(document.images).map((image) =>
              image.complete
                ? null
                : new Promise((done) => (image.onload = image.onerror = done)),
            ),
          );
      },
    });
  2. Install node-html-to-image

    master

    Install the library using npm or yarn. Note that the installation includes Puppeteer, which will download a compatible version of Chromium (approximately 170MB on Mac, 282MB on Linux, and 280MB on Windows).

    npm install node-html-to-image
    # or
    yarn add node-html-to-image
  3. Set output image resolution using CSS

    master

    Since node-html-to-image takes a screenshot of the body tag's content, you can control the output resolution by setting the width and height of the body element via CSS within your HTML string.

    const nodeHtmlToImage = require('node-html-to-image')
    
    nodeHtmlToImage({
      output: './image.png',
      html: `<html>
        <head>
          <style>
            body {
              width: 2480px;
              height: 3508px;
            }
          </style>
        </head>
        <body>Hello world!</body>
      </html>
      `
    })
      .then(() => console.log('The image was created successfully!'))
  4. Handle local images and fonts

    master

    Local Images

    To include local images, convert them to a base64 data URI and pass the URI via the content property to your template.

    const nodeHtmlToImage = require('node-html-to-image')
    const fs = require('fs');
    
    const image = fs.readFileSync('./image.jpg');
    const base64Image = new Buffer.from(image).toString('base64');
    const dataURI = 'data:image/jpeg;base64,' + base64Image
    
    nodeHtmlToImage({
      output: './image.png',
      html: '<html><body><img src="{{{imageSource}}}" /></body></html>',
      content: { imageSource: dataURI }
    })

    Local Fonts

    To apply local fonts, convert the font file to base64 and include it in a @font-face rule within your HTML <style> block using a data URI.

    const font2base64 = require('node-font2base64')
    
    const _data = font2base64.encodeToDataUrlSync('../my/awesome/font.ttf')
    
    const html = `
    <html
      <head
        <style
          @font-face {
            font-family: 'testFont';
            src: url("{{{_data}}}") format('woff2'); // don't forget the format!
          }
        </style>
      </head>
    ...`
  5. Migrate from v5 to v6

    master

    When upgrading to node-html-to-image v6, you must ensure your environment and configuration are updated to accommodate breaking changes in Puppeteer and Node.js requirements.

    Migration Checklist

    1. Update Node.js: Ensure you are using Node.js 22.12 or newer on your local machine, CI, and servers.
    2. Update waitUntil option: The default value for waitUntil has changed from networkidle0 to load. Because load does not wait for network activity to settle, remote assets (images/fonts) might not be fully rendered in the screenshot.
    3. TypeScript Fixes: If using TypeScript, networkidle0 and networkidle2 are no longer valid types and will cause errors. Replace them with load.
    4. Puppeteer Compatibility: If you provide your own puppeteer or puppeteer-core instance via options, ensure it is compatible with Puppeteer 25.
    5. Install v6:
      npm install node-html-to-image@6
  6. Understand the Screenshot class structure

    master

    The Screenshot class represents the data and configuration for a generated image. When using the library, you interact with this model to define what HTML is being rendered, which CSS selector to target, and how the resulting image should be encoded or saved.

    Key properties include:

    • html: The source HTML string to render.
    • selector: The CSS selector used to target a specific element within the HTML (defaults to body).
    • type: The image format (e.g., png, jpeg).
    • output: The file path where the image should be saved.
    • quality: The image quality (only applicable when type is jpeg).
    • transparent: A boolean indicating if the background should be transparent.
    • buffer: The raw data of the image (Buffer or string).
  7. Define Content for multi-element screenshots

    master

    The Content type allows you to provide either a single object or an array of objects to handle multiple outputs. When using an array, you can specify a unique output path and an optional selector for each item.

    Content can be:

    • An object: { [key: string]: any } (used for Handlebars context).
    • An array of objects: Array<{ output: string; selector?: string }>.
    export type Content = Array<{ output: string; selector?: string }> | object;
  8. Fix TypeScript errors for `waitUntil` in v6

    master

    In v6, Puppeteer 25 has removed networkidle0 and networkidle2. Using these values in TypeScript will result in a TS2322 error. You should replace them with load.

    // error TS2322
    await nodeHtmlToImage({ html, waitUntil: "networkidle0" });
    
    // use this instead
    await nodeHtmlToImage({ html, waitUntil: "load" });
  9. Get image as a Buffer instead of saving to disk

    master

    If you do not provide an output path, nodeHtmlToImage returns a Promise that resolves to a Buffer containing the image data. This is useful for serving images directly via web frameworks like Express.

    const express = require('express');
    const router = express.Router();
    const nodeHtmlToImage = require('node-html-to-image');
    
    router.get(`/api/tweet/render`, async function(req, res) {
      const image = await nodeHtmlToImage({
        html: '<html><body><div>Check out what I just did! #cool</div></body></html>'
      });
      res.writeHead(200, { 'Content-Type': 'image/png' });
      res.end(image, 'binary');
    });