Paged.js - Paged Media Tools
Paged.js is an open-source library to display paginated content in the browser and to generate print books using web technology.
It contains a set of handlers for CSS transformations and fragmented layout which polyfill the Paged Media and Generated Content CSS modules, along with hooks to create new handlers for custom properties.
The currently supported properties can be found on the pagedjs website.
A quick overview to getting started with Paged Media CSS and Paged.js is available on pagedjs.org/documentation.
NPM Module
$ npm install pagedjs
import { Previewer } from 'pagedjs';
let paged = new Previewer();
let flow = paged.preview(DOMContent, ["path/to/css/file.css"], document.body).then((flow) => {
console.log("Rendered", flow.total, "pages.");
})
Polyfill
Add the the paged.polyfill.js
script to replace all @page
css and render the html page with the Paged Media styles applied:
<script src="https://unpkg.com/pagedjs/dist/paged.polyfill.js"></script>
Try the polyfill with Aurorae.
By default the polyfill will run automatically as soon as the DOM is ready.
However, you can add an async before
function or return a Promise to delay the polyfill starting.
<script>
window.PagedConfig = {
before: () => {
return new Promise((resolve, reject) => {
setTimeout(() => { resolve() }, 1000);
})
},
after: (flow) => { console.log("after", flow) },
};
</script>
Otherwise you can disable auto
running the previewer and call window.PagedPolyfill.preview();
whenever you want to start.
<script>
window.PagedConfig = {
auto: false,
after: (flow) => { console.log("after", flow) },
};
setTimeout(() => {
window.PagedPolyfill.preview();
}, 1000);
</script>
Chunker
Chunks up a document into paged media flows and applies print classes.
Examples:
- Process the first 50 pages of Moby Dick.
- Upload and chunk an Epub using Epub.js.
Polisher
Converts @page
css to classes, and applies counters and content.
Examples:
- Test styles for print.
CLI
Command line interface to render out PDFs of HTML files using Puppeteer: https://gitlab.pagedmedia.org/tools/pagedjs-cli.
Modules
Modules are groups of handlers for that apply the layout and styles of a CSS module, such as Generated Content.
New handlers can be registered from import { registerHandlers } from 'pagedjs'
or by calling Paged.registerHandlers
on an html page.
<script src="https://unpkg.com/pagedjs/dist/paged.polyfill.js"></script>
<script>
class MyHandler extends Paged.Handler {
constructor(chunker, polisher, caller) {
super(chunker, polisher, caller);
}
afterPageLayout(pageFragment, page) {
console.log(pageFragment);
}
}
Paged.registerHandlers(MyHandler);
</script>
Handlers have methods that correspond to the hooks for the parsing, layout and rendering of the Chunker and Polisher. Returning a promise or async
function from a method in a handler will complete that task before continuing with the other registered methods for that hook.
// Previewer
beforePreview(content, renderTo)
afterPreview(pages)
// Chunker
beforeParsed(content)
filter(content)
afterParsed(parsed)
beforePageLayout(page)
onPageLayout(pageWrapper, breakToken, layout);
afterPageLayout(pageElement, page, breakToken)
finalizePage(pageElement, page, breakToken)
afterRendered(pages)
// Polisher
beforeTreeParse(text, sheet)
beforeTreeWalk(ast)
afterTreeWalk(ast, sheet)
onUrl(urlNode)
onAtPage(atPageNode)
onRule(ruleNode)
onDeclaration(declarationNode, ruleNode)
onContent(contentNode, declarationNode, ruleNode)
// Layout
layoutNode(node)
renderNode(node, sourceNode, layout)
onOverflow(overflow, rendered, bounds)
onBreakToken(breakToken, overflow, rendered)
afterOverflowRemoved(removed, rendered)
beforeRenderResult(breakToken, pageWrapper)
Setup
Install dependencies
$ npm install
Development
Run the local dev-server with livereload and autocompile on http://localhost:9090/
$ npm start
Deployment
Build the dist
output
$ npm run build
Compile the lib
output
$ npm run compile
Generate legacy builds with polyfills included
$ npm run legacy
Testing
Testing for Paged.js uses Jest but is split into Tests and Specs.
Tests
Unit tests for Chunker and Polisher methods are run in node using JSDOM.
npm test
Specs
Specs run a html file in Chrome (using puppeteer) to test against CSS specifications.
They can also output a pdf and compare pages (one at a time) in that PDF with samples PDFs (saved as images).
The PDF comparison tests depend on the ghostscript
and the ghostscript4js
package.
It is recomend to run these in the Docker container below via:
npm run docker-specs
However if you'd like to run the specs outside of Docker, you'll need to install a local version of Ghostscript for your system according to https://www.npmjs.com/package/ghostscript4js#prerequisites
For Mac you can install it with
brew install ghostscript
For Debian you can install it with
sudo apt-get install ghostscript
sudo apt-get install libgs-dev
Now you can install the ghostscript4js
library. For Linux you can optionally pass the location ghostscript was installed to in GS4JS_HOME
.
GS4JS_HOME="/usr/lib/$(gcc -dumpmachine)" npm install ghostscript4js
To test the pdf output of specs, you'll need to build the library locally.
npm run build
Then run the jest tests in puppeteer.
npm run specs
To debug the results of a test in a browser you can add NODE_ENV=debug
NODE_ENV=debug npm run specs
To update the stored pdf images you can run
npm run specs -- --updateSnapshot
Docker
A pagedmedia/pagedjs
docker image contains all the dependencies needed to run the pagedjs
development server, as well as the pdf comparison tests.
To build the image run
docker build -t pagedmedia/pagedjs .
By default the container will run the development server with npm start
docker run -it -p 9090:9090 pagedmedia/pagedjs
The tests and specs can be run within the container by passing a seccomp
file for Chrome and running npm test
docker run -it --security-opt 'seccomp=seccomp.json' pagedmedia/pagedjs npm test && npm run specs
Sponsorship ✨
The Coko Foundation has two staff members dedicated part time to Paged.js. The total cost is about 80k USD a year -- this isn't easily maintained by Coko as it is paid via the surplus from custom platform builds (all open source since Coko is a not-for-profit entity).
Join those sponsoring this project to support and maintain Paged.js. If you benefit from the library, or are using it in a commercial product or service, contribute today so that we can continue to deliver a quality tool for web-based document pagination. If you contribute at least $50 a month, create a pull request to add your name to the project sponsors listed below.
Contributors
Core team
The core team behind paged.js includes Adam Hyde, Julie Blanc, Fred Chasen & Julien Taquet.
Licence
MIT License (MIT), which you can read here