npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@rainbow-o23/n5

v1.0.45

Published

o23 pdf print

Downloads

414

Readme

Static Badge

Puppeteer

Module Formats

o23/n5

o23/n5 provides a pipeline step that converts HTML templates to PDF, implemented based on Puppeteer.

Environment Parameters

| Name | Type | Default Value | Comments | |-------------------------------------------|---------|---------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | puppeteer.executable.path | string | | Chromium path. | | puppeteer.browser.args | string | | Chromium browser launch arguments.Format follows --disable-gpu[,--no-sandbox[...]].See https://peter.sh/experiments/chromium-command-line-switches/ for more details. | | puppeteer.browser.cache | boolean | true | Use browser cache or not. | | puppeteer.devtools.enabled | boolean | false | Open devtools or not. | | puppeteer.headless.enabled | boolean | true | Use headless mode or not. | | puppeteer.max.pages | number | 50 | Maximum pages(tabs) in single browser, only works when browser cache is enabled. | | puppeteer.viewport.width | number | 1920 | Default viewport width, only works when viewport not present by constructor. | | puppeteer.viewport.height | number | 1080 | Default viewport height, only works when viewport not present by constructor. | | puppeteer.pdf.header.and.footer.display | boolean | false | Show pdf header and footer or not, only works when pdfOptions.displayHeaderFooter not present by constructor. | | puppeteer.pdf.background | boolean | false | Print background or not, only works when pdfOptions.printBackground not present by constructor. | | puppeteer.pdf.format | string | a4 | Print page format, only works when pdfOptions.format not present by constructor. | | puppeteer.pdf.timeout | number | 30 | Print timeout, in seconds, only works when pdfOptions.timeout not present by constructor. | | puppeteer.page.keep | boolean | false | Keep browser page after printed, enable this feature will disable headless mode automatically, also, recommend to disable browser cache.Only for debug purpose, never enable it in production. |

Constructor Parameters

| Name | Type | Default Value | Comments | |-------------|----------------------|---------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | browserArgs | string | | Additional browser arguments.Format follows --disable-gpu[,--no-sandbox[...]].See https://peter.sh/experiments/chromium-command-line-switches/ for more details. | | viewport | puppeteer.Viewport | | | | pdfOptions | puppeteer.PDFOptions | | |

Request and Response

export interface PrintPdfPipelineStepInFragment {
	/** it is a html */
	template: Buffer | string;
	data: any;
}

export interface PrintPdfPipelineStepOutFragment {
	file: Buffer;
}

An Example

Data

const data = {
	type: 'Test Pdf',
	information: [
		{name: 'John', age: 25, birthday: '1998-03-27', addresses: ['address line 1', 'address line 2']},
		{name: 'Jane', age: 27, birthday: '1996-08-12', addresses: ['address line 3']},
		{name: 'Mike', age: 21, birthday: '2002-11-20'}
	],
	policy: [
		{id: 1000001, productName: 'PRDT-001', productInfo: 'PRDT-001-INFO'},
		{id: 1000002, productName: 'PRDT-002', productInfo: 'PRDT-002-INFO'}
	]
};

Template


<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
<div>
    <h1 style="color: red" data-print="field" data-print-field="type">Name</h1>
    <table>
        <thead>
        <tr>
            <th>Name</th>
            <th>Age</th>
            <th>Birthday</th>
        </tr>
        </thead>
        <tbody>
        <tr data-print="loop" data-print-field="information">
            <td data-print="field" style="color: red" data-print-field="name">Name</td>
            <td data-print="field" data-print-field="age">Age</td>
            <td data-print="field" data-print-field="birthday">Birthday</td>
            <td>
                <span data-print="loop" data-print-field="addresses">
                    <span data-print="field" data-print-field="" style="display: block">Address</span>
                </span>
            </td>
        </tr>
        </tbody>
    </table>
    <table>
        <thead>
        <tr>
            <th>Id</th>
            <th>Product Name</th>
            <th>Product Info</th>
        </tr>
        </thead>
        <tbody>
        <tr data-print="loop" data-print-field="policy">
            <td data-print="field" style="color: red" data-print-field="id">id</td>
            <td data-print="field" data-print-field="productName">productName</td>
            <td data-print="field" data-print-field="productInfo">productInfo</td>
        </tr>
        </tbody>
    </table>
</div>
</body>
</html>
  • Supports nested loops,
  • data-print=loop represents loop,
  • data-print=field represents property,
  • data-print-field represents property name,
    • Supports multi-level property names, connected by .. For example, person.name represents that person is an object and name is a property under person,
  • `` or . represents use loop array itself,
  • All properties are relative paths, calculated relative to their parent node. Therefore, within a loop, only the values of each element can be accessed.

Use Sub-templates

Use <data-print-template data-code="YOUR-TEMPLATE-CODE"></data-print-template> to use sub-template. Sub-templates replacement are executed before data replacement, accessed through the findSubTemplate function provided pipeline step constructor.

Sub-templates also use the data from the page, so sub-templates do not need to prepare data separately.

Post Data Prepare

After the data preparation phase is completed, but before obtaining the header, footer, and printing parameters, the system will automatically detect and invoke the postDataPrepare function in order to incorporate additional custom logic. This function receives a parameter of the current printing data, and custom logic can be written based on the data.

Please note that this function is executed synchronously, so it is not recommended to perform time-consuming operations.

Page Header and Footer

Both headers and footers are supported simultaneously, and you only need to use standard HTML node definitions with specified IDs. Additionally, thanks to the support provided by Puppeteer itself, the following fixed usage patterns can be used to obtain the specified information:

| HTML | Description | |------------------------------------|------------------------------------| | <header id="header"></header> | Page header, can include anything. | | <footer id="footer"></footer> | Page footer, can include anything. | | <span class=”date”></span> | Current date | | <span class=”title”></span> | Document title | | <span class=””url></span> | Document URL | | <span class=”pageNumber”></span> | Current page number | | <span class=”totalPages”></span> | Total pages in the document |

PDF Options

Furthermore, pdfOptions can also be specified by the template, allowing each template to have its own settings. The syntax is as follows:

<!-- format of data-attr follows pdfOptions signature -->
<template id="pdfOptions" data-attr='{"margin": {"top": "100px", "bottom": "100px", "left": "50px", "right": "50px"}}'></template>

In the example above, the margin of the print page header is set. Typically, when using headers and footers, it is necessary to manually set the page margin information as well.

Installation

Generally speaking, when installing dependencies, Node will automatically download Chromium. If it is not automatically installed, you can use the following command for installation. The installed Chromium can be found in the puppeteer directory.


// workspace mode
node ../node_modules/puppeteer/install.mjs

// single project mode
node ./node_modules/puppeteer/install.mjs

Use puppeteer.config.cjs to provide the location of chromium, see https://pptr.dev/guides/configuration for more details.

Performance Benchmark

This benchmark was conducted on the following hardware and environment:

  • CPU: 2.6 GHz 6-Core Intel Core i7,
  • Memory: 64 GB 2667 MHz DDR4,
  • OS: macOS Sonoma 14.2.1,
  • MySQL: 8.2.0,
  • NodeJS: v18.19.0,
  • NPM: v10.2.3.

With scenario:

  • With one headless Chrome instance,
  • Flow:
    • Load template from database,
    • Print file,
    • Write printed file to database,
    • Return to client,
  • Template size: 1.7mb, 9 pages,
  • No command inside.
  • Output size: 1.1mb, 9 pages.

| # | Item | Max CPU Usage | Max Memory Usage | Avg. Response Time (ms) | |---|--------------------------------------|---------------|------------------|-------------------------| | 1 | 100 iterations, single thread | 25% | 400M | 2128 | | 2 | 100 iterations, 4 concurrent threads | 60% | 450M | 2541 | | 3 | 100 iterations, 8 concurrent threads | 70% | 450M | 3991 |