Skip to content

Commit d8130c4

Browse files
committed
-
1 parent 9a5a40c commit d8130c4

27 files changed

+1119
-1679
lines changed

.prettierignore

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1 @@
1-
tests/email.html
2-
tests/image.html
3-
tests/pagedjs.html
4-
tests/pagedjs/paged.polyfill.min.js
1+
tests/*

Dockerfile

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
1-
FROM node:18
1+
FROM node:20
2+
3+
# Configure default locale (important for chrome-headless-shell).
4+
ENV LANG=en_US.UTF-8
25

36
# Install latest chrome dev package and fonts to support major charsets (Chinese, Japanese, Arabic, Hebrew, Thai and a few others)
47
# Note: this installs the necessary libs to make the bundled version of Chrome that Puppeteer
58
# installs, work.
69
RUN apt-get update \
710
&& apt-get install -y wget gnupg \
811
&& wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | gpg --dearmor -o /usr/share/keyrings/googlechrome-linux-keyring.gpg \
9-
&& sh -c 'echo "deb [arch=amd64 signed-by=/usr/share/keyrings/googlechrome-linux-keyring.gpg] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list' \
12+
&& sh -c 'echo "deb [arch=amd64 signed-by=/usr/share/keyrings/googlechrome-linux-keyring.gpg] https://dl-ssl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list' \
1013
&& apt-get update \
11-
&& apt-get install -y google-chrome-stable fonts-ipafont-gothic fonts-wqy-zenhei fonts-thai-tlwg fonts-khmeros fonts-kacst fonts-freefont-ttf libxss1 \
14+
&& apt-get install -y google-chrome-stable fonts-ipafont-gothic fonts-wqy-zenhei fonts-thai-tlwg fonts-khmeros fonts-kacst fonts-freefont-ttf libxss1 dbus dbus-x11 \
1215
--no-install-recommends \
1316
&& rm -rf /var/lib/apt/lists/* \
1417
&& groupadd -r pptruser && useradd -rm -g pptruser -G audio,video pptruser
@@ -17,6 +20,8 @@ USER pptruser
1720

1821
WORKDIR /home/pptruser
1922

23+
ENV DBUS_SESSION_BUS_ADDRESS=autolaunch:
24+
2025
COPY package.json .
2126
COPY package-lock.json .
2227

@@ -27,4 +32,4 @@ COPY keys/jwt-public.key keys/jwt-public.key
2732

2833
EXPOSE 5000
2934

30-
CMD node template-renderer.js
35+
CMD ["node", "template-renderer.js"]

LICENSE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
MIT License
22

3-
Copyright (c) 2023 GrumpSolutions
3+
Copyright (c) 2023 GrumpTech
44

55
Permission is hereby granted, free of charge, to any person obtaining a copy
66
of this software and associated documentation files (the "Software"), to deal

README.md

Lines changed: 25 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -1,77 +1,48 @@
1-
# Template renderer
1+
# template-renderer
22

3-
Creating PDF documents is a common task in software development. This repository shows how to create PDF's from HTML templates using three remarkable open source projects. It shows a free and open source alternative to commercial software like Aspose.Pdf or Exstream.
4-
5-
## General information
6-
7-
### Puppeteer
8-
9-
An open source Node.js library providing control to Chrome or Chromium used for automated testing and creating PDF's. Puppeteer is maintained by the Chrome DevTools team.\
10-
<https://pptr.dev>\
11-
<https://github.com/puppeteer/puppeteer>\
12-
License: See project, Apache License 2.0 at time of writing
13-
14-
### mustache.js
15-
16-
An open source javascript library to render mustache templates. The [mustache template syntax](https://github.com/janl/mustache.js#templates) is explained in the [mustache.js github repository](https://github.com/janl/mustache.js#templates). The mustache template engine is [widely available](https://mustache.github.io).\
17-
License: See project, MIT License at time of writing
18-
19-
### Paged.js
20-
21-
An open source library to paginate HTML content for printing to PDF. This library is used to design books with HTML and CSS.\
22-
<https://pagedjs.org>\
23-
<https://github.com/pagedjs/pagedjs>\
24-
<https://ashok-khanna.medium.com/beautiful-pdfs-from-html-9a7a3c565404>\
25-
<https://www.adamhyde.net/some-pagedjs-info>\
26-
License: See project, MIT license at time of writing
27-
28-
### Source code
29-
30-
- [template-renderer.js](/template-renderer.js) - Combines Puppeteer and mustache.js with just a few lines of code in order to create PDF's from mustache HTML templates.
31-
- [tests/pagedjs/pagedjs.html](/tests/pagedjs/pagedjs.html) - Uses Paged.js to create a document with a table of contents and page numbers.
32-
33-
### Typesetting with CSS
34-
35-
Browsers provide some interesting options for typesetting. For example the following CSS styles.
36-
37-
- **orphans** - minimum number of lines at the bottom of a page
38-
- **widows** - minimum number of lines at the top of a page
39-
- **break-before: avoid-page** - avoid page break before a HTML element
40-
- **break-after: avoid-page** - avoid page break after a HTML element
41-
- **text-align: justify** - align text to the left and right edges of lines, except at the last line
42-
- **hyphens: auto** - words are hyphenated according to language-specific hyphenation rules, where the language should be specified with a lang attribute
43-
44-
**Note:** It seems that Puppeteer does not yet handle hyphens correctly. Two possible workarounds are [hyphen](https://www.npmjs.com/package/hyphen) (node) and [Hyphenopoly](https://github.com/mnater/Hyphenopoly) (browser).
3+
This small demo project generates PDFs from HTML templates.
454

465
## Security
476

48-
Some remarks concerning security.
7+
Some remarks concerning security:
498

509
- Ensure user input is validated.
5110
- Ensure the npm packages and docker image are up to date.
52-
- Only allow access from trusted services. This is often achieved using json web tokens. Thanks to the package [jsonwebtoken](https://github.com/auth0/node-jsonwebtoken) this was easily implemented in template-renderer.js.
11+
- Only allow access from trusted services. This is often achieved using json web tokens. Thanks to the package [jsonwebtoken](https://github.com/auth0/node-jsonwebtoken) this was easily implemented in [template-renderer.js](/template-renderer.js).
5312
- For serving over https see <https://expressjs.com/en/5x/api.html#app.listen> and <https://nodejs.org/api/https.html#httpscreateserveroptions-requestlistener>.
5413

5514
## Getting started
5615

5716
### Npm commands
5817

59-
See package.json for scripts to run, build and test template-renderer.js and some example templates.
18+
See [package.json](/package.json) for scripts to run, build and test [template-renderer.js](/template-renderer.js). It provides scripts to build some example templates as well.
6019

61-
- Run `npm run generate-keys jwt` to create a private and public key. The public key is used by template-renderer.js for validating JWT's.
62-
- Run `npm run start:test` to serve template-renderer.js on port 5000 and a HTML test page on port 5021. See tests directory for some templates which can be used for testing.
20+
- Run `npm run generate-keys jwt` to create a private and public key. The public key is used by [template-renderer.js](/template-renderer.js) for validating JWT's.
21+
- Run `npm run start:test` to serve [template-renderer.js](/template-renderer.js) on port 5000 and a HTML test page on port 5021. The [examples directory](/examples) contains templates which can be used for testing.
22+
- Run `npm run start:image` to serve [template-renderer.js](/template-renderer.js) on port 5000 and run `start:test-page` to run a HTML test page on port 5021. The [examples directory](/examples) contains templates which can be used for testing.
23+
- Run `npx prettier . --check` or `npx prettier . --write` to format code using prettier (an opinionated formatter).
6324

6425
### Docker image
6526

66-
A Dockerfile is included in this is repository. See <https://pptr.dev/guides/docker> and <https://github.com/puppeteer/puppeteer/tree/main/docker> for more information.
27+
A [Dockerfile](/Dockerfile) is included in this repository. See <https://pptr.dev/guides/docker> and <https://github.com/puppeteer/puppeteer/blob/main/docker/Dockerfile> for more information.
28+
29+
### Source code
30+
31+
- [template-renderer.js](/template-renderer.js) - Combines Puppeteer and mustache.js with a few lines of code in order to create PDFs from mustache HTML templates.\
32+
The service waits until `window.readyForPdf != false`. This way the template can run JavaScript before it's rendered.
33+
- [generate-keys.js](/utils/generate-keys.js) - Generates a private and public key.
34+
- [test-page.js](/utils/test-page.js) - Serves a test page for testing [template-renderer.js](/template-renderer.js).
6735

6836
### Some example templates
6937

70-
- tests/a4-pages.html
71-
- tests/email
72-
- tests/image
73-
- tests/mustache.html
74-
- tests/pagedjs
38+
- [a4](/examples/a4.html)
39+
- [email](/examples/email.html)
40+
- [image](/examples/image.html)
41+
- [mustache](/examples/mustache.html)
42+
- [pagedjs](/examples/pagedjs.html)
43+
- [pagedjs-toc](/examples/pagedjs.html)
44+
- [partial-lorem-ipsum](/examples/partial-lorem-ipsum.html)
45+
- [partial-mustache](/examples/partial-mustache.html)
7546

7647
### Validating JWKS tokens
7748

@@ -108,26 +79,3 @@ function createTokenValidationFunction(url, requiredScope) {
10879
```
10980
11081
_For local testing -_ Extra self-signed certificate(s) can be provided with a node environment variable: [NODE_EXTRA_CA_CERTS](https://nodejs.org/api/cli.html#node_extra_ca_certsfile).
111-
112-
## Packages
113-
114-
- Puppeteer - library providing control to Chrome or Chromium
115-
- mustache.js - library to render mustache templates
116-
- Paged.js - library to paginate HTML content for printing to PDF
117-
- winston - a simple logging library with support for multiple transports
118-
- jsonwebtoken - an implementation of JSON Web Tokens used for signing and verifying JWT's
119-
- jwks-rsa - a library to retrieve signing keys from a JWKS endpoint
120-
121-
### Packages for testing
122-
123-
- axios - node package for http requests
124-
- http-server - serve files locally for testing
125-
- json5 - for parsing json written by hand
126-
- juice - inline web resources (styles, scripts, images)
127-
- nodemon - run script and restart when changed
128-
- npm-run-all - run multiple npm scripts with one command
129-
- web-resource-inliner - inline web resources without any changes (preserves all Paged.js styles)
130-
131-
### Package for formatting
132-
133-
- prettier - opinionated code formatter (run with `npx prettier . --check` or `npx prettier . --write`)

examples/a4.html

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<!doctype html>
2+
<html lang="en">
3+
<head>
4+
<title>{{htmlTitleTag}}</title>
5+
<style>
6+
@page {
7+
margin: 1in;
8+
size: A4;
9+
}
10+
p {
11+
text-align: justify;
12+
hyphens: auto;
13+
}
14+
h1,
15+
h2 {
16+
break-before: page;
17+
}
18+
h3,
19+
h4 {
20+
break-before: avoid-page;
21+
}
22+
23+
</style>
24+
</head>
25+
<body>
26+
{{> template}}
27+
</body>
28+
</html>

tests/email.html renamed to examples/email.html

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<!doctype html>
2-
<html lang="{{language}}">
2+
<html lang="en">
33
<head>
4-
<title>{{title}}</title>
4+
<title>{{htmlTitleTag}}</title>
55
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
66
<meta name="viewport" content="width=device-width">
77

@@ -14,17 +14,17 @@
1414
<table border="0" cellpadding="0" cellspacing="0" class="email-container" style="padding: 10px 20px 10px 20px; min-width: 580px; max-width: 720px; width: 100%; background-color: white;" width="100%" bgcolor="white">
1515
<tr>
1616
<td align="left" valign="middle">
17-
<p>{{title}}</p>
17+
<p style="text-align: justify; hyphens: auto;">{{header}}</p>
1818
</td>
1919
</tr>
2020
<tr>
2121
<td align="left" valign="top">
22-
<p>{{> content}}</p>
22+
<p style="text-align: justify; hyphens: auto;">{{> template}}</p>
2323
</td>
2424
</tr>
2525
<tr>
2626
<td align="left" valign="middle">
27-
<p>{{footer}}</p>
27+
<p style="text-align: justify; hyphens: auto;">{{footer}}</p>
2828
</td>
2929
</tr>
3030
</table>
File renamed without changes.
File renamed without changes.

tests/pagedjs.html renamed to examples/pagedjs-toc.html

Lines changed: 151 additions & 125 deletions
Large diffs are not rendered by default.

tests/pagedjs/paged.polyfill.min.js renamed to examples/pagedjs.html

Lines changed: 205 additions & 0 deletions
Large diffs are not rendered by default.
File renamed without changes.
File renamed without changes.

0 commit comments

Comments
 (0)