Percollate is a command-line tool that turns web pages into beautifully formatted PDF, EPUB, or HTML files.
percollate is a Node.js command-line tool that works best when installed globally from npm:
npm install -g percollatePercollate and its dependencies require Node.js version 10.22.0 or later.
Run
percollate --helpfor a list of available commands and options.
Percollate is invoked on one or more operands (usually URLs):
percollate <command> [options] url [url]...The following commands are available:
percollate pdfproduces a PDF file;percollate epubproduces an EPUB file;percollate htmlproduces a HTML file.
The operands can be URLs, paths to local files, or the - character which stands for stdin (the standard inputs).
Unless otherwise stated, these options apply to all three commands.
Specify the path of the resulting bundle relative to the current folder.
percollate pdf https://example.com -o my-example.pdfUsing the - operand you can read the HTML content from stdin, as fetched by a separate command, such as curl. In this sort of setup, percollate does not know the URL from which the content has been fetched, and relative paths on images, anchors, et cetera won't resolve correctly.
Use the --url option to supply the source's original URL.
curl https://example.com | percollate pdf - --url=https://example.comBy default, percollate bundles all web pages in a single file. Use the --individual flag to export each source to a separate file.
percollate pdf --individual http://example.com/page1 http://example.com/page2Path to a custom HTML template. Applies to pdf and html.
Path to a custom CSS stylesheet, relative to the current folder.
Additional CSS styles you can pass from the command-line to override styles specified by the default/custom stylesheet.
Don't prefer the AMP version of the web page.
Print more detailed information.
Provide a title for the bundle.
percollate epub http://example.com/page-1 http://example.com/page-2 --title="Best Of Example"Provide an author for the bundle.
percollate pdf --author="Ella Example" http://example.comGenerate a cover. The option is implicitly enabled when the --title option is provided, or when bundling more than one web page to a single file. Disable this implicit behavior by passing the --no-cover flag.
Generate a hyperlinked table of contents. The option is implicitly enabled when bundling more than one web page to a single file. Disable this implicit behavior by passing the --no-toc flag.
Applies to pdf and html.
To turn a single web page into a PDF:
percollate pdf --output=some.pdf https://example.comTo bundle several web pages into a single PDF, specify them as separate arguments to the command:
percollate pdf --output=some.pdf https://example.com/page1 https://example.com/page2You can use common Unix commands and keep the list of URLs in a newline-delimited text file:
cat urls.txt | xargs percollate pdf --output=some.pdfTo transform several web pages into individual PDF files at once, use the --individual flag:
percollate pdf --individual https://example.com/page1 https://example.com/page2If you'd like to fetch the HTML with an external command, you can use - as an operand, which stands for stdin (the standard input):
curl https://example.com/page1 | percollate pdf --url=https://example.com/page1 -Notice we're using the url option to tell percollate the source of our (now-anonymous) HTML it gets on stdin, so that relative URLs on links and images resolve correctly.
The --css option lets you pass a small snippet of CSS to percollate. Here are some common use-cases:
The default page size is A5 (portrait). You can use the --css option to override it using any supported CSS size:
percollate pdf --css "@page { size: A3 landscape }" http://example.comSimilarly, you can define:
- custom margins, e.g.
@page { margin: 0 } - the base font size:
html { font-size: 10pt }
The default stylesheet includes CSS variables for the fonts used in the PDF:
:root {
--main-font: Palatino, 'Palatino Linotype', 'Times New Roman',
'Droid Serif', Times, 'Source Serif Pro', serif, 'Apple Color Emoji',
'Segoe UI Emoji', 'Segoe UI Symbol';
--alt-font: 'helvetica neue', ubuntu, roboto, noto, 'segoe ui', arial,
sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol';
--code-font: Menlo, Consolas, monospace;
}| CSS variable | What it does |
|---|---|
--main-font |
The font stack used for body text |
--alt-font |
Used in headings, captions, et cetera |
--code-font |
Used for code snippets |
To override them, use the --css option:
percollate pdf --css ":root { --main-font: 'PT Serif'; --alt-font: Roboto; }" http://example.comπ‘ To work correctly, you must have the fonts installed on your machine. Custom web fonts currently require you to use a custom CSS stylesheet / HTML template.
The idea with percollate is to make PDFs that can be printed without losing where the hyperlinks point to. However, for some link-heavy pages, the appended hrefs can become bothersome. You can remove them using:
percollate pdf --css "a:after { display: none }" http://example.comThe --style option lets you use your own CSS stylesheet instead of the default one. Here are some common use-cases for this option:
β οΈ TODO add examples here
The --template option lets you use a custom HTML template for the PDF.
π‘ The HTML template is parsed with nunjucks, which is a close JavaScript relative of Twig for PHP, Jinja2 for Python and L for Ruby.
Here are some common use-cases:
Puppeteer can print some basic information about the page in the PDF. The following CSS class names are available for the header / footer, into which the appropriate content will be injected:
dateβ The formatted print datetitleβ The document titleurlβ document location (Note: this will print the path of the temporary html, not the original web page URL)pageNumberβ the current page numbertotalPagesβ total pages in the document
π See the Chromium source code for details.
You place your header / footer template in a template element in your HTML:
<template class="header-template"> My header </template>
<template class="footer-template">
<div class="text center">
<span class="pageNumber"></span>
</div>
</template>See the default HTML for example usage.
You can add CSS styles to the header / footer with either the --css option or a separate CSS stylesheet (the --style option).
π‘ The header / footer template do not inherit their styles from the rest of the page (i.e. they are not part of the cascade), so you'll have to write the full CSS you want to apply to them.
An example from the default stylesheet:
.footer-template {
font-size: 10pt;
font-weight: bold;
}To keep the tool up-to-date, you can run:
npm install -g percollateOccasionally, an ugrade might not go according to plan; in this case, you can uninstall and re-install percollate:
npm uninstall -g percollate && npm install -g percollateAll export formats follow a common pipeline:
- Fetch the page(s) using
node-fetch - If an AMP version of the page exists, use that instead (disable with
--no-ampflag) - Enhance the DOM using
jsdom - Pass the DOM through
mozilla/readabilityto strip unnecessary elements - Apply the HTML template and the stylesheet to the resulting HTML
Different formats then use different tools:
- PDFs are generated with
puppeteer; - EPUBs have external images fetched and bundled together with the HTML of each article;
- HTMLs are saved without any further changes (images are not saved to the disk).
Percollate inherits the limitations of two of its main components, Readability and Puppeteer (headless Chrome).
The imperative approach Readability takes will not be perfect in each case, especially on HTML pages with atypical markup; you may occasionally notice that it either leaves in superfluous content, or that it strips out parts of the content. You can confirm the problem against Firefox's Reader View. In this case, consider filing an issue on mozilla/readability.
Using a browser to generate the PDF is a double-edged sword. On the one hand, you get excellent support for web platform features. On the other hand, print CSS as defined by W3C specifications is only partially implemented, and it seems unlikely that support will be improved any time soon. However, even with modest print support, I think Chrome is the best (free) tool for the job.
On some Linux machines you'll need to install a few more Chrome dependencies before percollate works correctly. (Thanks to @ptica for sorting it out)
The percollate pdf command supports the --no-sandbox Puppeteer flag, but make sure you're aware of the implications before disabling the sandbox.
Contributions of all kinds are welcome! See CONTRIBUTING.md for details.
Here are some other projects to check out if you're interested in building books using the browser:
