Skip to content

Commit

Permalink
Merge branch 'master' into patch-1
Browse files Browse the repository at this point in the history
  • Loading branch information
gutschilla authored May 2, 2019
2 parents 4843b59 + 645d165 commit 16cbce9
Show file tree
Hide file tree
Showing 13 changed files with 1,438 additions and 175 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@
erl_crash.dump
*.ez
/doc

.elixir_ls
/node_modules
42 changes: 41 additions & 1 deletion CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,45 @@
# Changes

- 0.5.3
- **BUGFIX** introduced in 0.5.0 when certain shells don't accept
`["foo=bar", …]` parameters which should correctly be `["foo", "bar"]`
Thanks to [@egze](https://github.com/egze) for submitting a patch.
- Refactored `PathAgent` that holds configuration state for readability and
more fashionable and extensible error messages. Extensible towards new
generators.
- Updated README to be more elaborative on how to install `wkhtmltopdf` and
`chrome-headless-render-pdf`
- 0.5.2
- **BUGFIX** introduced in 0.5.0 when global options to wkhtmltopdf weren't
accepted any more due to wrong shell parameter order. Thanks to
[manukall](https://github.com/manukall) for reporting.
- 0.5.1
- allow chrome to be executed as root via default config option
`disable_chrome_sandbox` – this is required for an easy usage within a
docker container as in
[elixir-pdf-server](https://github.com/gutschilla/elixir-pdf-server)
- 0.5.0
- **Got rid of Porcelain** dependency as it interferes with many builds using
plain `System.cmd/3`. Please note, that as of the documentation
(https://hexdocs.pm/elixir/System.html#cmd/3) ports will be closed but in
case wkhtmltopdf somehow hangs, nobody takes care of terminating it.
- Refactored some sections
- **Support URLs** instead of just plain HTML
- **Support for chrome-headless** for (at least for me) faster and nicer renderings.
- Since this is hopefully helpful, I rose the version to 0.5.0 even tough
the API stays consistent
- 0.4.0
- Got rid of misc_random dependency. This was here to manage between
depreciated random functions in Erlang. We go ahead using plain
`Enum.random/1` instead, implementing our own
`PdfGenerator.Random.string/1` function. This also removes a common
pitfall when drafting a release with distillery.
* Thanks to [Hugo Maia Vieira](https://github.com/hugomaiavieira) for this
contribution!
* Since `Enum.random/1` is only available since September 2015 (three
years ago) I am OK with raising the minimum Elixir version to v1.1 –
Since this may break projects still running on Elixir v1.0
**I bumped the version to 0.4.0***.
- 0.3.7
- Adding in raise_on_missing_wkhtmltopdf_binary config, thanks
to [veverkap](https://github.com/veverkap)
Expand Down Expand Up @@ -51,7 +92,6 @@
- make paths configurable in `config/ENV.exs` as well
- add some tests (Yay!)
- better README- 0.3.0

- 0.2.0
- adding support for PDFTK to create encrypted PDFs
- **API-CHANGE** PdfGenerator.generate now returns tuple `{:ok, file_name}`
Expand Down
207 changes: 143 additions & 64 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,37 +1,106 @@
# elixir-pdf-generator

A wrapper for wkhtmltopdf (HTML to PDF) and PDFTK (adds in encryption) for use
in Elixir projects. If available, it will use xvfb-run (x virtual frame buffer)
to use wkhtmltopdf on systems that have no X installed, e.g. a server.

# New in 0.3.7 - raise_on_missing_wkhtmltopdf_binary

- 0.3.7
- Adding in raise_on_missing_wkhtmltopdf_binary config, thanks
to [veverkap](https://github.com/veverkap)
- Document using xvfb-run with auto-servernum option, thanks
to [Tony van Riet](https://github.com/tonyvanriet)
A wrapper for both wkhtmltopdf and chrome-headless plus PDFTK (adds in
encryption) for use in Elixir projects.

If available, it will use xvfb-run (x
virtual frame buffer) to use wkhtmltopdf on systems that have no X installed,
e.g. a server.

# New in 0.5.0 - farewell Porcelain, hello chrome-headless (puppeteer)

- 0.5.0
- **Got rid of Porcelain** dependency as it interferes with many builds using
plain `System.cmd/3`. Please note, that as of the documentation
(https://hexdocs.pm/elixir/System.html#cmd/3) ports will be closed but in
case wkhtmltopdf somehow hangs, nobody takes care of terminating it.
- Refactored some sections
- **Support URLs** instead of just plain HTML
- **Support for chrome-headless** for (at least for me) faster and nicer renderings.
- Since this is hopefully helpful, I rose the version to 0.5.0 even tough
the API stays consistent
- 0.5.1
- allow chrome to be executed as root via default config option
`disable_chrome_sandbox` – this is required for an easy usage within a
docker container as in
[elixir-pdf-server](https://github.com/gutschilla/elixir-pdf-server)
- 0.5.2
- **BUGFIX** introduced in 0.5.0 when global options to wkhtmltopdf weren't
accepted any more due to wrong shell parameter order. Thanks to
[manukall](https://github.com/manukall) for reporting.
- 0.5.3
- **BUGFIX** introduced in 0.5.0 when certain shells don't accept
`["foo=bar", …]` parameters which should correctly be `["foo", "bar"]`
Thanks to [@egze](https://github.com/egze) for submitting a patch.
- Refactored `PathAgent` that holds configuration state for readability and
more fashionable and extensible error messages. Extensible towards new
generators.
- Updated README to be more elaborative on how to install `wkhtmltopdf` and
`chrome-headless-render-pdf`

For a proper changelog, see [CHANGES](CHANGES.md)

# System prerequisites

Download wkhtmltopdf and place it in your $PATH. Current binaries can be found
here: http://wkhtmltopdf.org/downloads.html

_(optional)_ To use wkhtmltopdf on systems without an X window server installed,
please install `xvfb-run` from your repository (on Debian/Ubuntu: `sudo apt-get
install xvfb`).

On current (2018) Macintosh computers `/usr/X11/bin/xvfb` should be available
and is reported to do the same thing. _warning:_ This is untested. PLS report to
me if you ran this successfully on a Mac.

_(optional)_ For best results, download goon and place it in your $PATH. Current
binaries can be found here: https://github.com/alco/goon/releases

_(optional)_ Install pdftk via your package manager or homebrew. The
project page also contains a Windows installer
# System prerequisites

It's either

* wkhtmltopdf or

* nodejs and possibly chrome/chromium

## chrome-headless

This will allow you to make more use of Javascript and advanced CSS as it's just
your Chrome/Chromium browser rendering your web page as HTML and printing it as
PDF. Rendering _tend_ to be a bit faster than with wkhtmltopdf. The price tag is
that PDFs printed with chrome/chromium are usually considerably bigger than
those generated with wkhtmltopdf.

1. Run `npm -g install chrome-headless-render-pdf puppeteer`.

This requires [nodejs](https://nodejs.org), of course. This will install a
recent chromium and chromedriver to run Chrome in headless mode and use this
browser and its API to print PDFs globally on your machine.

If you prefer a project-local install, just use `npm install` This will
install dependencies under `./node_modules`. Be aware that those won't be
packaged in your distribution (I will add support for this later).

On some machines, this doesn't install Chromium and fails. Here's how to get
this running on Ubtunu 18:

```
DEBIAN_FRONTEND=noninteractive PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=TRUE \
apt-get install -y chromium-chromedriver \
&& npm -g install chrome-headless-render-pdf puppeteer
```

## wkhtmltopdf

2. Download wkhtmltopdf and place it in your $PATH. Current binaries can be
found here: http://wkhtmltopdf.org/downloads.html

For the impatient:

```
apt-get -y install xfonts-base xfonts-75dpi \
&& wget https://downloads.wkhtmltopdf.org/0.12/0.12.5/wkhtmltox_0.12.5-1.bionic_amd64.deb \
&& dpkg -i wkhtmltox_0.12.5-1.bionic_amd64.deb
```

3. _optional:_ Install `xvfb` (shouldn't be required with the binary mentioned above):

To use other wkhtmltopdf executables comiled with an unpatched Qt on systems
without an X window server installed, please install `xvfb-run` from your
repository (on Debian/Ubuntu: `sudo apt-get install xvfb`).

I haven't heard any feedback of people using this feature since a while since
the wkhtmltopdf projects ships ready-made binaries. I will deprecate this
starting in `0.6.0` since, well, YAGNI.

4. _optional:_ Install `pdftk` via your package manager or homebrew. The project
page also contains a Windows installer. On Debian/Ubuntu just type:
`apt-get -y install pdftk`

# Usage

Expand All @@ -40,15 +109,15 @@ Add this to your dependencies in your mix.exs:
```Elixir
def application do
[applications: [
:logger,
:logger,
:pdf_generator # <-- add this
]]
end

defp deps do
[
# ... whatever else
{ :pdf_generator, ">=0.3.7" }, # <-- and this
{ :pdf_generator, ">=0.5.3" }, # <-- and this
]
end
```
Expand All @@ -60,11 +129,24 @@ $ iex -S mix

html = "<html><body><p>Hi there!</p></body></html>"
# be aware, this may take a while...
{ :ok, filename } = PdfGenerator.generate html, page_size: "A5"
{ :ok, pdf_content } = File.read filename
{:ok, filename} = PdfGenerator.generate(html, page_size: "A5")
{:ok, pdf_content} = File.read(filename)

# or, if you prefer methods that raise on error:
filename = PdfGenerator.generate! html
filename = PdfGenerator.generate!(html, generator: :chrome)
```

Or, pass some URL

```
PdfGenerator.generate {:url, "http://google.com"}, page_size: "A5"
```

Or, use chrome-headless

```
html_works_too = "<html><body><h1>Minimalism!"
{:ok, filename} = PdfGenerator.generate html_works_too, generator: :chrome
```

Or use the bang-methods:
Expand All @@ -78,22 +160,32 @@ pdf_binary = PdfGenerator.generate_binary! "<html>..."

This module will automatically try to finde both `wkhtmltopdf` and `pdftk` in
your path. But you may override or explicitly set their paths in your
`config/config.exs`.
`config/config.exs`.

```Elixir
config :pdf_generator,
wkhtml_path: "/usr/bin/wkhtmltopdf", # <-- this program actually does the heavy lifting
pdftk_path: "/usr/bin/pdftk" # <-- only needed for PDF encryption
```

## Running headless (server-mode)
or, if you prefer shrome-headless

```
config :pdf_generator,
use_chrome: true # <-- will be default by 0.6.0
pdftk_path: "/usr/bin/pdftk" # <-- only needed for PDF encryption
```

## Running wkhtml headless (server-mode)

This section only applies to `wkhtmltopdf` users.

If you want to run `wkhtmltopdf` with an unpatched verison of webkit that requires
an X Window server, but your server (or Mac) does not have one installed,
you may find the `command_prefix` handy:

```Elixir
PdfGenerator.generate "<html..", command_prefix: "xvfb-run"
PdfGenerator.generate "<html..", command_prefix: "xvfb-run"
```

This can also be configured globally in your `config/config.exs`:
Expand All @@ -115,14 +207,23 @@ config :pdf_generator,

## More options

- `page_size`: defaults to `A4`, see `wkhtmltopdf` for more options
- `filename` - filename for the output pdf file (without .pdf extension, defaults to a random string)

- `page_size`:
* defaults to `A4`, see `wkhtmltopdf` for more options
* A4 will be translated to `page-height 11` and `page-width 8.5` when
chrome-headless is used

- `open_password`: requires `pdftk`, set password to encrypt PDFs with

- `edit_password`: requires `pdftk`, set password for edit permissions on PDF
- `shell_params`: pass custom parameters to `wkhtmltopdf`. **CAUTION: BEWARE OF SHELL INJECTIONS!**

- `shell_params`: pass custom parameters to `wkhtmltopdf`. **CAUTION: BEWARE OF SHELL INJECTIONS!**

- `command_prefix`: prefix `wkhtmltopdf` with some command or a command with options
(e.g. `xvfb-run -a`, `sudo` ..)

- `delete_temporary`: immediately remove temp files after generation
- `filename` - filename for the output pdf file (without .pdf extension, defaults to a random string)

## Heroku Setup

Expand All @@ -136,32 +237,10 @@ https://github.com/gjaldon/phoenix-static-buildpack
```

__note:__ The list also includes Elixir and Phoenix buildpacks to show you that they
must be placed after `pdftk` and `wkhtmltopdf`. It won't work if you load the
must be placed after `pdftk` and `wkhtmltopdf`. It won't work if you load the
Elixir and Phoenix buildpacks first.

# Documentation

For more info, read the [docs on hex](http://hexdocs.pm/pdf_generator) or issue
`h PdfGenerator` in your iex shell.

# Common issues

## Running from within distillery or exrm releases

**ERROR**

`(UndefinedFunctionError) function Misc.Random.string/0 is undefined (module Misc.Random is not available)`

**FIX**

For now, unfortunately, it's required to add `misc_random` to either your
`included_applications` section in your `mix.exs` (exrm) or for (distillery) add
it to your release/applications list in `rel/config.exs`.

```Elixir
...
release :your_app do
set version: current_version(:your_app)
set applications: [:misc_random]
end
```
11 changes: 7 additions & 4 deletions config/config.exs
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
use Mix.Config

# config :pdf_generator,
# wkhtml_path: "/usr/bin/wkhtmltopdf",
# pdftk_path: "/usr/bin/pdftk",
# command_prefix: "/usr/bin/xvfb-run"
config :pdf_generator,
# wkhtml_path: "/usr/bin/wkhtmltopdf",
# pdftk_path: "/usr/bin/pdftk",
# command_prefix: "/usr/bin/xvfb-run",

# allow chrome to run as root
disable_chrome_sandbox: true

import_config "#{Mix.env}.exs"

Loading

0 comments on commit 16cbce9

Please sign in to comment.