A lightweight Typescript library that interacts with Gotenberg's different routes to convert a variety of document formats to PDF files.
Using npm:
npm install chromiumly
Using yarn:
yarn add chromiumly
Before attempting to use Chromiumly, be sure you install Docker if you have not already done so.
After that, you can start a default Docker container of Gotenberg as follows:
docker run --rm -p 3000:3000 gotenberg/gotenberg:8
Chromiumly supports configurations via both dotenv and config configuration libraries or directly via code to add Gotenberg endpoint to your project.
GOTENBERG_ENDPOINT=http://localhost:3000
{
"gotenberg": {
"endpoint": "http://localhost:3000"
}
}
import { Chromiumly } from "chromiumly";
Chromiumly.configure({ endpoint: "http://localhost:3000" });
Gotenberg introduces basic authentication support starting from version 8.4.0. Suppose you are running a Docker container using the command below:
docker run --rm -p 3000:3000 \
-e GOTENBERG_API_BASIC_AUTH_USERNAME=user \
-e GOTENBERG_API_BASIC_AUTH_PASSWORD=pass \
gotenberg/gotenberg:8.4.0 gotenberg --api-enable-basic-auth
To integrate this setup with Chromiumly, you need to update your configuration as outlined below:
GOTENBERG_ENDPOINT=http://localhost:3000
GOTENBERG_API_BASIC_AUTH_USERNAME=user
GOTENBERG_API_BASIC_AUTH_PASSWORD=pass
Or
{
"gotenberg": {
"endpoint": "http://localhost:3000",
"api": {
"basicAuth": {
"username": "user",
"password": "pass"
}
}
}
}
Or
Chromiumly.configure({
endpoint: "http://localhost:3000",
username: "user",
password: "pass",
});
Chromiumly introduces different classes that serve as wrappers to
Gotenberg's routes. These classes encompass methods featuring an
input file parameter, such as html
, header
, footer
, and markdown
, capable of accepting inputs in the form of a
string
(i.e. file path), Buffer
, or ReadStream
.
There are three different classes that come with a single method (i.e.convert
) which calls one of
Chromium's Conversion routes to convert html
and markdown
files, or
a url
to a buffer
which contains the converted PDF file content.
Similarly, a new set of classes have been added to harness the recently introduced Gotenberg Screenshot routes. These classes include a single method called capture
, which allows capturing full-page screenshots of html
, markdown
, and url
.
import { UrlConverter } from "chromiumly";
const urlConverter = new UrlConverter();
const buffer = await urlConverter.convert({
url: "https://www.example.com/",
});
import { UrlScreenshot } from "chromiumly";
const screenshot = new UrlScreenshot();
const buffer = await screenshot.capture({
url: "https://www.example.com/",
});
The only requirement is that the file name should be index.html
.
import { HtmlConverter } from "chromiumly";
const htmlConverter = new HtmlConverter();
const buffer = await htmlConverter.convert({
html: "path/to/index.html",
});
import { HtmlScreenshot } from "chromiumly";
const screenshot = new HtmlScreenshot();
const buffer = await screenshot.capture({
html: "path/to/index.html",
});
This route accepts an index.html
file plus a markdown file.
import { MarkdownConverter } from "chromiumly";
const markdownConverter = new MarkdownConverter();
const buffer = await markdownConverter.convert({
html: "path/to/index.html",
markdown: "path/to/file.md",
});
import { MarkdownScreenshot } from "chromiumly";
const screenshot = new MarkdownScreenshot();
const buffer = await screenshot.capture({
html: "path/to/index.html",
markdown: "path/to/file.md",
});
convert()
method takes an optional properties
parameter of the following type which dictates how the PDF generated
file will look like.
type PageProperties = {
singlePage?: boolean; // Print the entire content in one single page (default false)
size?: {
width: number; // Paper width, in inches (default 8.5)
height: number; //Paper height, in inches (default 11)
};
margins?: {
top: number; // Top margin, in inches (default 0.39)
bottom: number; // Bottom margin, in inches (default 0.39)
left: number; // Left margin, in inches (default 0.39)
right: number; // Right margin, in inches (default 0.39)
};
preferCssPageSize?: boolean; // Define whether to prefer page size as defined by CSS (default false)
printBackground?: boolean; // Print the background graphics (default false)
omitBackground?: boolean; // Hide the default white background and allow generating PDFs with transparency (default false)
landscape?: boolean; // Set the paper orientation to landscape (default false)
scale?: number; // The scale of the page rendering (default 1.0)
nativePageRanges?: { from: number; to: number }; // Page ranges to print
};
In addition to the PageProperties
customization options, the convert()
method also accepts a set of parameters to further enhance the versatility of the conversion process. Here's an overview of the full list of parameters:
type ConversionOptions = {
properties?: PageProperties; // Customize the appearance of the generated PDF
pdfFormat?: PdfFormat; // Define the PDF format for the conversion
pdfUA?: boolean; // Enable PDF for Universal Access for optimal accessibility (default false)
userAgent?: string; // Customize the user agent string sent during conversion
header?: PathLikeOrReadStream; // Specify a custom header for the PDF
footer?: PathLikeOrReadStream; // Specify a custom footer for the PDF
emulatedMediaType?: EmulatedMediaType; // Specify the emulated media type for conversion
waitDelay?: string; // Duration (e.g., '5s') to wait when loading an HTML document before conversion
waitForExpression?: string; // JavaScript expression to wait before converting an HTML document into PDF
extraHttpHeaders?: Record<string, string>; // Include additional HTTP headers in the request
failOnHttpStatusCodes?: number[]; // List of HTTP status codes triggering a 409 Conflict response (default [499, 599])
failOnConsoleExceptions?: boolean; // Return a 409 Conflict response if there are exceptions in the Chromium console (default false)
skipNetworkIdleEvent?: boolean; // Do not wait for Chromium network to be idle (default true)
metadata?: Metadata; // Metadata to be written.
cookies?: Cookie[]; // Cookies to be written.
downloadFrom?: DownloadFrom; //Download a file from a URL. It must return a Content-Disposition header with a filename parameter.
};
Similarly, the capture()
method takes an optional properties
parameter of the specified type, influencing the appearance of the captured screenshot file.
type ImageProperties = {
format: "png" | "jpeg" | "webp"; //The image compression format, either "png", "jpeg" or "webp".
quality?: number; // The compression quality from range 0 to 100 (jpeg only).
omitBackground?: boolean; // Hide the default white background and allow generating screenshots with transparency.
width?: number; // The device screen width in pixels (default 800).
height?: number; // The device screen height in pixels (default 600).
clip?: boolean; // Define whether to clip the screenshot according to the device dimensions (default false).
};
Furthermore, alongside the customization options offered by ImageProperties
, the capture()
method accommodates a variety of parameters to expand the versatility of the screenshot process. Below is a comprehensive overview of all parameters available:
type ScreenshotOptions = {
properties?: ImageProperties;
header?: PathLikeOrReadStream;
footer?: PathLikeOrReadStream;
emulatedMediaType?: EmulatedMediaType;
waitDelay?: string; // Duration (e.g, '5s') to wait when loading an HTML document before convertion.
waitForExpression?: string; // JavaScript's expression to wait before converting an HTML document into PDF until it returns true.
extraHttpHeaders?: Record<string, string>;
failOnHttpStatusCodes?: number[]; // Return a 409 Conflict response if the HTTP status code is in the list (default [499,599])
failOnConsoleExceptions?: boolean; // Return a 409 Conflict response if there are exceptions in the Chromium console (default false)
skipNetworkIdleEvent?: boolean; // Do not wait for Chromium network to be idle (default true)
optimizeForSpeed?: boolean; // Define whether to optimize image encoding for speed, not for resulting size.
cookies?: Cookie[]; // Cookies to be written.
downloadFrom?: DownloadFrom; // Download the file from a specific URL. It must return a Content-Disposition header with a filename parameter.
};
The LibreOffice
class comes with a single method convert
. This method interacts with LibreOffice route to convert different documents to PDF files. You can find the file extensions
accepted here.
import { LibreOffice } from "chromiumly";
const buffer = await LibreOffice.convert({
files: [
"path/to/file.docx",
"path/to/file.png",
{ data: xlsxFileBuffer, ext: "xlsx" },
],
});
Similarly to Chromium's route convert
method, this method takes the following optional parameters :
properties
: changes how the PDF generated file will look like. It also includes apassword
parameter to open the source file.pdfa
: PDF format of the conversion resulting file (i.e.PDF/A-1a
,PDF/A-2b
,PDF/A-3b
).pdfUA
: enables PDF for Universal Access for optimal accessibility.merge
: merges all the resulting files from the conversion into an individual PDF file.metadata
: writes metadata to the generated PDF file.lolosslessImageCompression
: allows turning lossless compression on or off to tweak image conversion performance.reduceImageResolution
: allows turning on or off image resolution reduction to tweak image conversion performance.quality
: specifies the quality of the JPG export. The value ranges from 1 to 100, with higher values producing higher-quality images and larger file sizes.maxImageResolution
: specifies if all images will be reduced to the specified DPI value. Possible values are:75
,150
,300
,600
, and1200
.
The PDFEngines
class interacts with Gotenberg's PDF Engines routes to manupilate PDF files.
This method interacts with PDF Engines convertion route to transform PDF files into the requested PDF/A format and/or PDF/UA.
import { PDFEngines } from "chromiumly";
const buffer = await PDFEngines.convert({
files: ["path/to/file_1.pdf", "path/to/file_2.pdf"],
pdfa: PdfFormat.A_2b,
pdfUA: true,
});
This method interacts with PDF Engines merge route which gathers different engines that can manipulate and merge PDF files such as: PDFtk, PDFcpu, QPDF, and UNO.
import { PDFEngines } from "chromiumly";
const buffer = await PDFEngines.merge({
files: ["path/to/file_1.pdf", "path/to/file_2.pdf"],
pdfa: PdfFormat.A_2b,
pdfUA: true,
});
This method reads metadata from the provided PDF files.
import { PDFEngines } from "chromiumly";
const metadataBuffer = await PDFEngines.readMetadata([
"path/to/file_1.pdf",
"path/to/file_2.pdf",
]);
This method writes metadata to the provided PDF files.
import { PDFEngines } from "chromiumly";
const buffer = await PDFEngines.writeMetadata({
files: [
"path/to/file_1.pdf",
"path/to/file_2.pdf",
],
metadata: {
Author: 'Taha Cherfia',
Tite: 'Chromiumly'
Keywords: ['pdf', 'html', 'gotenberg'],
}
});
Please consider referring to ExifTool for a comprehensive list of accessible metadata options.
It is just a generic complementary method that takes the buffer
returned by the convert
method, and a
chosen filename
to generate the PDF file.
Please note that all the PDF files can be found __generated__
folder in the root folder of your project.
The following is a short snippet of how to use the library.
import { PDFEngines, UrlConverter } from "chromiumly";
async function run() {
const urlConverter = new UrlConverter();
const buffer = await urlConverter.convert({
url: "https://gotenberg.dev/",
});
await PDFEngines.generate("gotenberg.pdf", buffer);
}
run();