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 🙏

© 2026 – Pkg Stats / Ryan Hefner

line-by-line-pdf-generator

v1.2.1

Published

An easy to use Line by Line pdf generator for NodeJS using PDFKit, with support of text, images, backgrounds, borders, and page layout control without needing a browser engine installed!

Readme

📄 Line by line PDF generator for Node

An easy to use Line by Line pdf generator for NodeJS using PDFKit, with support of text, images, backgrounds, borders, and page layout control without needing a browser engine installed!

Features

  • Dynamic layout with rows and columns
  • Support for text, images, and layout control (page breaks, splits, etc.)
  • Customizable styling (fonts, colors, borders, margins)
  • Get PDF as a buffer as a return
  • No need for a browser engine to be installed

Installation

npm install line-by-line-pdf-generator

Usage

You can run the generatePdf function it expects 2 arguments, the first one is a 2-dimensional array with all the columns and the second one is optional and is the options for the pdf.

import pdfGenerator from "line-by-line-pdf-generator"


const generatedPdf = await pdfGenerator([
    [
        /* PDF columns for the first row */
    ],
    [
        /* PDF columns for the second row */
    ]
], {
    /* Optional options */
})

Example

An example of a very simple PDF

import pdfGenerator from "line-by-line-pdf-generator"
import {PdfColumnType} from "line-by-line-pdf-generator/types";

import fs from "fs"

const generatedPdf = await pdfGenerator([
    [
        {
            type: PdfColumnType.TEXT,
            text: "Hello world",
            justify: "center",
        },
        {
            type: PdfColumnType.EMPTY,
            cols: 2
        },
        {
            type: PdfColumnType.TEXT,
            text: "Goodbye",
        },
    ],
    [
        {
            type: PdfColumnType.TEXT,
            text: "Image: ",
            size: 24,
            justify: "left",
            color: "black",
            background: "yellow"
        },
        {
            type: PdfColumnType.IMAGE,
            cols: 3,
            url: "https://picsum.photos/300/200",
            options: {
                fit: ["colum-width", 300]
            }
        },
    ]
], {
    textColor: "green",
    textJustify: "right"
})


fs.writeFileSync("pdf.pdf", generatedPdf)

Options

The PDF options exists of the following arguments all of these are optional

| Option | Type | Default | Description | |-------------|-------------|-----------|-------------------------------------------------------------| | margin | number | 30 | A margin on the pdf page | | rowHeight | number | 1 | The amount of pixels on the top and bottom of texts columns | | colMargin | number | 0 | The amount of pixels on the right and left of texts columns | | textSize | number | 12 | The default font size of text | | textColor | string | black | The default text color | | textFont | string | Helvetica | The default font | | textJustify | TextJustify | left | The justify for all text (see text columns for more info) |

Rows and columns

To create a PDF with the line by line PDF generator you have to use a 2-dimensional array of Rows containing Columns, think of it like this

[
    [{ /* First col of the first line*/}, { /* Second col of the first line*/}], /* First line of the PDF*/
    [{ /* First col of the second line*/}, { /* Second col of the second line*/}] /* Second line of the PDF*/
]

The location if the columns will be automatically calculated. There are multiple column types

  • TEXT
  • IMAGE
  • EMPTY
  • PAGE_BREAK
  • PAGE_SPLIT

Each of these have their own unique features but all of them have common attributes that can be used by any of them

Common column attributes

These attributes can be used by all column types:

Background

The background of the column, it can be any a color name or a hex value

Example

const yellowColumn = {
    type: PdfColumnType.EMPTY,
    background: "yellow"
}

Border

The Border of the column, it has 4 optional sub attributes left, right, top, and bottom they indicate the axes of the border each axes has 2 attributes width and an optional color, width is the size of the border and color is the border color with will default to the font color

Example

const borderedColumn = {
    type: PdfColumnType.EMPTY,
    border: {
        top: {
            width: 1,
            color: "black"
        },
        bottom: {
            width: 1,
            color: "black"
        },
        left: {
            width: 1,
            color: "black"
        },
        right: {
            width: 1,
            color: "black"
        }
    }
}

cols

The width of Columns by default is all the same, but sometimes you want some colums to be bigger or smaller than other columns, you can use the cols attribute for that, cols is a number with default 1 that indicates the size this column indicates, if cols is 2 it will be twice as big as the default.

Example

const differentSizeRow = [
    {
        type: PdfColumnType.EMPTY,
        cols: 1 /* this col will take 25% of the page */
    },
    {
        type: PdfColumnType.EMPTY,
        cols: 2 /* this col will take 50% of the page */
    },
    {
        type: PdfColumnType.EMPTY,
        cols: 1 /* this col will take 25% of the page */
    }
]

you can also make cols intentionally smaller

const differentSizeRow = [
    {
        type: PdfColumnType.EMPTY,
        cols: 1 /* this col will take 50% of the page */
    },
    {
        type: PdfColumnType.EMPTY,
        cols: 0.5 /* this col will take 25% of the page */
    },
    {
        type: PdfColumnType.EMPTY,
        cols: 0.5 /* this col will take 25% of the page */
    }
]

Be aware that cols: 1 is the default so its not necessary to include, I only included it for extra clarity

Text column

Adds texts to the column, text will not exceed a size of a column and will be wrapped inside the column, the height will be automatically be taken care off. A text column can have the following attributes:

text

This is a required string, that will be the text that is placed in the column, it will be automatically wrapped to the size of the column

Example

const textColumn = {
    type: PdfColumnType.TEXT,
    text: "Hello world"
}

link

An oprional string to make text a clickable link.

Example

const textColumn = {
    type: PdfColumnType.TEXT,
    text: "Go to my website!",
    link: "https://michelle-honnebier.com"
}

color

An optional string of the color of the text will default to the textColor value in the PDF options, color can be a color name or HEX value.

Example

const textColumn = {
    type: PdfColumnType.TEXT,
    text: "Hello world",
    color: "green"
}

size

An optional string of the color of the text will default to the textSize value in the PDF options

Example

const textColumn = {
    type: PdfColumnType.TEXT,
    text: "Hello world!",
    size: 36
}

font

An optional string of the font of the text will default to the textFont value in the PDF options learn more about fonts here for now you can only use the default fonts the ability to register new fonts will be availible soon

Example

const textColumn = {
    type: PdfColumnType.TEXT,
    text: "Hello world",
    font: "Helvatica-Bolt",
}

justify

An optinal value that is indicate how the text can be aligned in the column it can be left, center, right, or justify. It will fallback to the textJustify value in the PDF options. read more about it here

Example

const textColumn = {
    type: PdfColumnType.TEXT,
    text: "Hello world",
    justify: "right",
}

Empty column

Empty columns are columns without anything, they can be used to create a buffer or make use of the common attributes to get a background text, it has one attribute sizewhich is the size in pixels how big the empty column.

Examples

You can use empty column to create a vertical buffer

const PdfRows = [
    [{
        type: PdfColumnType.TEXT,
        text: "Hello world"
    }],
    [{
        type: PdfColumnType.EMPTY,
        size: 150 /* 150px empty space between rows*/
    }],
    [{
        type: PdfColumnType.TEXT,
        text: "Goodbye!"
    }]
]

You can also use empty column to use default attributes and align all your columns correctly


const PdfRow = [
    {
        type: PdfColumnType.TEXT,
        text: "Hello world"
    }, {
        type: PdfColumnType.EMPTY,
        cols: 2,
        color: "yellow" /* ads an empty yellow block between the 2 texts that takes 50% of the page */
    }, {
        type: PdfColumnType.TEXT,
        text: "Goodbye!"
    }
]

Image column

Image columns can be used to insert images, it expects an attribute url, file, or buffer and options, url, file, or buffer is how the image should be fetched url points to a url file points to a file, and buffer is an ArrayBuffer of the image, options are the PDFKIT image options, If you want to use the column with as image with you can use the "column-with" string and it will be replaced by the column with, currently only width and fit are supported, more support is coming soon

Examples

Simple image from an url:

const imageColumn = {
    type: PdfColumnType.IMAGE,
    cols: 3,
    url: "https://picsum.photos/300/200",
    options: {
        width: 300,
        height: 200
    }
}

Simple image from a file:

const imageColumn = {
  type: PdfColumnType.IMAGE,
  cols: 3,
  file: "assets/images/logo.png",
  options: {
    width: 300,
    height: 200
  }
}

Simple image from a buffer:

const imageColumn = {
  type: PdfColumnType.IMAGE,
  cols: 3,
  buffer: <ArrayBuffer>,
  options: {
    width: 300,
    height: 200
  }
}

Image to fit in specific width and height:

const imageColumn = {
    type: PdfColumnType.IMAGE,
    cols: 3,
    url: "https://picsum.photos/300/200",
    options: {
        fit: [300, 200],
    }
}

Image to within column width:

const imageColumn = {
    type: PdfColumnType.IMAGE,
    cols: 3,
    url: "https://picsum.photos/300/200",
    options: {
        fit: ["column-width", 200],
    }
}

⚠️ Caveats

Images will not have their height calculated within the row height, this is intended behaviour since its quite common you want multiple text rows next to an image, if you want to text below an image you can create an Empty column with cols: 0 and size: image-size to make the height of the row the height of the image, a way to calculate the image height in the row height is coming soon.

Page break

End of page will end the page, all following rows will appear on a new page

Examples

const PdfRows = [
    [{
        type: PdfColumnType.TEXT,
        text: "Hello world" /* This will appear on page one */
    }],
    [{
        type: PdfColumnType.PAGE_BREAK,
    }],
    [{
        type: PdfColumnType.TEXT,
        text: "Goodbye!"  /* This will appear on page two */
    }]
]

You can also use default attributes on a page break

const PdfRows = [
    [{
        type: PdfColumnType.TEXT,
        text: "Hello world" /* This will appear on page one */
    }],
    [{
        type: PdfColumnType.EMPTY,
    }, {
        type: PdfColumnType.PAGE_BREAK,
        background: "blue",
        cols: 2 /* 66% of the rest of the page will a blue block*/
    }],
    [{
        type: PdfColumnType.TEXT,
        text: "Goodbye!"  /* This will appear on page two */
    }]
]

Page split

Will create a split in the page, the lines after a split will be rendered on the bottom of the page, if the 2 sections do not fit on one page a new page will be created.

Examples

const PdfRows = [
    [{
        type: PdfColumnType.TEXT,
        text: "Hello world" /* This on top */
    }], [{
        type: PdfColumnType.TEXT,
        text: "Hello world" /* This one line below*/
    }],
    [{
        type: PdfColumnType.PAGE_SPLIT,
    }],
    [{
        type: PdfColumnType.TEXT,
        text: "Goodbye!"  /* This will one line above the the bottom of the page */
    }],
    [{
        type: PdfColumnType.TEXT,
        text: "Goodbye!"  /* This will appear on the bottom of the age */
    }]
]

If the 2 sections are to big for one page it will look like this

const PdfRows = [
    [{
        type: PdfColumnType.TEXT,
        text: "Hello world" /* This on top */
    }], [{
        type: PdfColumnType.EMPTY,
        size: 1000
    }],
    [{
        type: PdfColumnType.PAGE_SPLIT,
    }],
    [{
        type: PdfColumnType.TEXT,
        text: "Goodbye!"  /* This be on top of a new page  */
    }],
    [{
        type: PdfColumnType.EMPTY,
        size: 1000
    }]
]

You can also use page split columns with the common attributes

const PdfRows = [
    [{
        type: PdfColumnType.TEXT,
        text: "Hello world" /* This on top */
    }], [{
        type: PdfColumnType.TEXT,
        text: "Hello world" /* This one line below*/
    }],
    [{
        type: PdfColumnType.PAGE_SPLIT,
        background: "orange",
        border: {
            bottom: {
                width: 1,
                color: white
            }
        } /* The space between the sections will be orange and there will be a white border before the second section */
    }],
    [{
        type: PdfColumnType.TEXT,
        text: "Goodbye!"  /* This will one line above the the bottom of the page */
    }],
    [{
        type: PdfColumnType.TEXT,
        text: "Goodbye!"  /* This will appear on the bottom of the age */
    }]
]

⚠️ Caveats

You can only use one page split per page, if you want to use another one you need to place an PAGE_BREAK component between them

This will give an error:

const PdfRows = [
    [{
        type: PdfColumnType.TEXT,
        text: "Hello world"
    }], [{
        type: PdfColumnType.TEXT,
        text: "Hello world"
    }],
    [{
        type: PdfColumnType.PAGE_SPLIT,
    }],
    [{
        type: PdfColumnType.TEXT,
        text: "Goodbye!"
    }],
    [{
        type: PdfColumnType.TEXT,
        text: "Goodbye!"
    }],
    [{
        type: PdfColumnType.PAGE_SPLIT,
    }],
    [{
        type: PdfColumnType.TEXT,
        text: "Goodbye!"
    }],
    [{
        type: PdfColumnType.TEXT,
        text: "Goodbye!"
    }]
]

This will work fine

const PdfRows = [
    [{
        type: PdfColumnType.TEXT,
        text: "Hello world"
    }], [{
        type: PdfColumnType.TEXT,
        text: "Hello world"
    }],
    [{
        type: PdfColumnType.PAGE_SPLIT,
    }],
    [{
        type: PdfColumnType.TEXT,
        text: "Goodbye!"
    }],
    [{
        type: PdfColumnType.TEXT,
        text: "Goodbye!"
    }],
    [{
        type: PdfColumnType.PAGE_BREAK,
    }],
    [{
        type: PdfColumnType.TEXT,
        text: "Goodbye!"
    }],
    [{
        type: PdfColumnType.TEXT,
        text: "Goodbye!"
    }],
    [{
        type: PdfColumnType.PAGE_SPLIT,
    }],
    [{
        type: PdfColumnType.TEXT,
        text: "Goodbye!"
    }],
    [{
        type: PdfColumnType.TEXT,
        text: "Goodbye!"
    }],
]