mirror of
https://github.com/astefanutti/decktape.git
synced 2024-08-17 18:20:40 +03:00
358 lines
14 KiB
Plaintext
358 lines
14 KiB
Plaintext
= DeckTape
|
|
Antonin Stefanutti <https://github.com/astefanutti[@astefanutti]>
|
|
// Meta
|
|
:description: DeckTape is a high-quality PDF exporter for HTML presentation frameworks.
|
|
:decktape-version: 3.0.0
|
|
// Settings
|
|
:idprefix:
|
|
:idseparator: -
|
|
// Aliases
|
|
:bullet:  • 
|
|
ifdef::env-github[]
|
|
:note-caption: :information_source:
|
|
:icon-ban: :no_entry_sign:
|
|
:icon-check: :white_check_mark:
|
|
:icon-clock: :clock10:
|
|
:icon-exclamation: :exclamation:
|
|
:icon-exclamation-dim: :grey_exclamation:
|
|
:icon-edit: :pencil2:
|
|
endif::[]
|
|
ifndef::env-github[]
|
|
:icons: font
|
|
:icon-ban: icon:ban[fw,role=red]
|
|
:icon-check: icon:check-square-o[fw,role=green]
|
|
:icon-clock: icon:clock-o[fw,role=silver]
|
|
:icon-exclamation: icon:exclamation[fw,role=red]
|
|
:icon-exclamation-dim: icon:exclamation[fw,role=silver]
|
|
:icon-edit: icon:pencil[fw]
|
|
endif::[]
|
|
// URIs
|
|
:uri-badge-npm: https://img.shields.io/npm/v/decktape.svg
|
|
:uri-badge-node: https://img.shields.io/node/v/decktape.svg
|
|
:uri-decktape-npm: https://www.npmjs.com/package/decktape
|
|
:uri-decktape-release: https://github.com/astefanutti/decktape/releases/latest
|
|
|
|
:uri-puppeteer: https://github.com/GoogleChrome/puppeteer
|
|
:uri-w3c-uievents-key: https://www.w3.org/TR/uievents-key/
|
|
|
|
:uri-docker: https://www.docker.com
|
|
:uri-docker-hub: https://hub.docker.com
|
|
:uri-docker-image: https://hub.docker.com/r/astefanutti/decktape
|
|
:uri-docker-ref: http://docs.docker.com/engine/reference
|
|
|
|
:uri-bespokejs: http://markdalgleish.com/projects/bespoke.js
|
|
:uri-deckjs: http://imakewebthings.com/deck.js
|
|
:uri-dzslides: http://paulrouget.com/dzslides
|
|
:uri-flowtimejs: https://marcolago.github.io/flowtime.js/
|
|
:uri-impressjs: https://impress.js.org
|
|
:uri-inspire: https://inspirejs.org
|
|
:uri-nuedeck: https://github.com/twitwi/nuedeck
|
|
:uri-pageres: https://github.com/sindresorhus/pageres
|
|
:uri-remark: https://remarkjs.com
|
|
:uri-revealjs: https://revealjs.com
|
|
:uri-rise: https://github.com/damianavila/RISE
|
|
:uri-shower: https://shwr.me
|
|
:uri-slidy: https://www.w3.org/Talks/Tools/Slidy/
|
|
:uri-webslides: https://github.com/jlantunez/webslides
|
|
|
|
image:{uri-badge-npm}[link="{uri-decktape-npm}"] image:{uri-badge-node}[]
|
|
|
|
{description}
|
|
|
|
DeckTape is built on top of {uri-puppeteer}[Puppeteer] which relies on Google Chrome for laying out and rendering Web pages and provides a headless Chrome instance scriptable with a JavaScript API.
|
|
|
|
DeckTape currently supports the following presentation frameworks out of the box:
|
|
|
|
{uri-bespokejs}[Bespoke.js]{bullet}
|
|
{uri-deckjs}[deck.js]{bullet}
|
|
{uri-dzslides}[DZSlides]{bullet}
|
|
{uri-flowtimejs}[Flowtime.js]{bullet}
|
|
{uri-impressjs}[impress.js]{bullet}
|
|
{uri-inspire}[Inspire.js]{bullet}
|
|
{uri-nuedeck}[NueDeck]{bullet}
|
|
{uri-remark}[remark]{bullet}
|
|
{uri-revealjs}[reveal.js]{bullet}
|
|
{uri-rise}[RISE]{bullet}
|
|
{uri-shower}[Shower]{bullet}
|
|
{uri-slidy}[Slidy]{bullet}
|
|
{uri-webslides}[WebSlides]
|
|
|
|
DeckTape also provides a <<generic,generic command>> that works by emulating the end-user interaction, allowing it to be used to convert presentations from virtually any kind of framework.
|
|
The generic mode is particularly useful for supporting HTML presentation frameworks that don't expose an API or accessible state.
|
|
|
|
DeckTape's plugin-based architecture exposes an extension API, making it possible to add support for other frameworks or to tailor existing plugins to your specific needs.
|
|
|
|
DeckTape can optionally be used to capture screenshots of your slide decks in various resolutions (similar to {uri-pageres}[pageres]).
|
|
That can be useful to make sure your presentations are responsive or to create handouts for them.
|
|
|
|
You can browse some slide deck <<examples,examples>> below that have been exported with DeckTape.
|
|
|
|
== Install
|
|
|
|
=== NPM
|
|
|
|
Install DeckTape globally and run it:
|
|
|
|
```sh
|
|
$ npm install -g decktape
|
|
$ decktape
|
|
```
|
|
|
|
Or locally:
|
|
|
|
```sh
|
|
$ npm install decktape
|
|
$ `npm bin`/decktape
|
|
```
|
|
|
|
See the <<faq,FAQ>> for troubleshooting / alternatives.
|
|
|
|
== Usage
|
|
|
|
[source]
|
|
----
|
|
$ decktape -h
|
|
|
|
Usage: decktape [options] [command] <url> <filename>
|
|
decktape version
|
|
|
|
command one of: automatic, bespoke, deck, dzslides, flowtime, generic, impress, inspire,
|
|
nuedeck, remark, reveal, shower, slidy, webslides
|
|
url URL of the slides deck
|
|
filename Filename of the output PDF file
|
|
|
|
Options:
|
|
-s <size>, --size <size> Size of the slides deck viewport: <width>x<height> (e.g. '1280x720')
|
|
-p <ms>, --pause <ms> Duration in milliseconds before each slide is exported [1000]
|
|
--load-pause <ms> Duration in milliseconds between the page has loaded
|
|
and starting to export slides [0]
|
|
--url-load-timeout <ms> Timeout in milliseconds to use when waiting for the initial
|
|
URL to load [60000]
|
|
--page-load-timeout <ms> Timeout in milliseconds to use when waiting for the slide deck
|
|
page to load [20000]
|
|
--screenshots Capture each slide as an image [false]
|
|
--screenshots-directory <dir> Screenshots output directory [screenshots]
|
|
--screenshots-size <size> Screenshots resolution, can be repeated [--size]
|
|
--screenshots-format <format> Screenshots image format, one of [jpg, png] [png]
|
|
--slides <range> Range of slides to be exported, a combination of slide indexes
|
|
and ranges (e.g. '1-3,5,8')
|
|
--chrome-path <path> Path to the Chromium or Chrome executable to run instead of the
|
|
bundled Chromium
|
|
--chrome-arg <arg> Additional argument to pass to the Chrome instance, can be repeated
|
|
|
|
Defaults to the automatic command.
|
|
Iterates over the available plugins, picks the compatible one for presentation at the
|
|
specified <url> and uses it to export and write the PDF into the specified <filename>.
|
|
----
|
|
|
|
In addition to the general options listed above, command specific options can be displayed the following way:
|
|
|
|
$ decktape <command> -h
|
|
|
|
== Commands
|
|
|
|
[#automatic]
|
|
=== `automatic`
|
|
|
|
Iterates over the available link:plugins[], picks the compatible one for presentation at the specified `url` and uses it to export and write the PDF into the specified `filename`.
|
|
|
|
[#generic]
|
|
=== `generic`
|
|
|
|
Emulates the end-user interaction by pressing the key with the specified `--key` option and iterates over the presentation as long as:
|
|
|
|
[loweralpha]
|
|
. Any change to the DOM is detected by observing mutation events targeting the body element and its subtree nor
|
|
. the number of slides exported has reached the specified `--max-slides` option.
|
|
|
|
The `--key` value must be one of the {uri-w3c-uievents-key}[UI events `KeyboardEvent` key values] and defaults to `ArrowRight`, e.g.:
|
|
|
|
$ decktape generic --key=ArrowDown
|
|
|
|
== Options
|
|
|
|
=== `--screenshots`
|
|
|
|
Captures each slide as an image at the `--screenshots-size` resolution, exports it to the `--screenshots-format` image format and writes the output into the `--screenshots-directory` directory.
|
|
|
|
The `--screenshots-size` option can be set multiple times. For example:
|
|
|
|
$ decktape --screenshots --screenshots-size=400x300 --screenshots-size=800x600
|
|
|
|
=== `--slides`
|
|
|
|
Exports only the slides specified as a series of slides indexes and ranges, e.g.:
|
|
|
|
[source,shell]
|
|
----
|
|
# Capture a single slide
|
|
$ decktape --slides 1
|
|
# Capture a series of slides
|
|
$ decktape --slides 1,3,5
|
|
# Capture a range of slides
|
|
$ decktape --slides 1-10
|
|
# Capture a combination of slides and ranges
|
|
$ decktape --slides 1,2,5-10
|
|
----
|
|
|
|
The rendering stops and the file written out after the largest numbered slide is exported.
|
|
|
|
== Examples
|
|
|
|
The following slide deck examples have been exported using DeckTape:
|
|
|
|
[cols="1v,1v,1v"]
|
|
|===
|
|
|HTML5 Presentation |Framework |Exported PDF
|
|
|
|
|https://revealjs.com/demo/[Reveal.js Demo]
|
|
|reveal.js
|
|
|https://astefanutti.github.io/decktape/examples/reveal-js-demo.pdf[reveal-js-demo.pdf] (2.0MB)
|
|
|
|
|https://tdd.github.io/devoxx-es6-maintenant/[ES6+ maintenant !]
|
|
|reveal.js
|
|
|https://astefanutti.github.io/decktape/examples/devoxx-es6-maintenant.pdf[devoxx-es6-maintenant.pdf] (2.3MB)
|
|
|
|
|https://github.com/hakimel/reveal.js/blob/360bc940062711db9b8020ce4e848f6c37014481/test/examples/math.html[reveal.js MathJax example]
|
|
|reveal.js
|
|
|https://astefanutti.github.io/decktape/examples/reveal-js-mathjax.pdf[reveal-js-mathjax.pdf] (0.3MB)
|
|
|
|
|https://artificer.jboss.org/slides/general/opensource-getting-involved.html[Getting Involved in Open Source]
|
|
|reveal.js
|
|
|https://astefanutti.github.io/decktape/examples/opensource-getting-involved.pdf[opensource-getting-involved.pdf] (0.6MB)
|
|
|
|
|http://astefanutti.github.io/further-cdi[Going Further with CDI]
|
|
|Asciidoctor + DZSlides
|
|
|https://astefanutti.github.io/decktape/examples/going-further-with-cdi.pdf[going-further-with-cdi.pdf] (2.4MB)
|
|
|
|
|http://imakewebthings.com/deck.js[Deck.js Modern HTML Presentations]
|
|
|deck.js
|
|
|https://astefanutti.github.io/decktape/examples/deck-js-presentation.pdf[deck-js-presentation.pdf] (0.5MB)
|
|
|
|
|https://remarkjs.com[The Official Remark Slideshow]
|
|
|remark
|
|
|https://astefanutti.github.io/decktape/examples/remark-js-slideshow.pdf[remark-js-slideshow.pdf] (0.15MB)
|
|
|
|
|https://joshbode.github.io/remark/ansi.html[Coloured Terminal Listings in Remark]
|
|
|remark
|
|
|https://astefanutti.github.io/decktape/examples/remark-js-coloured-terminal.pdf[remark-js-coloured-terminal.pdf] (0.12MB)
|
|
|
|
|https://www.w3.org/Talks/Tools/Slidy[HTML Slidy: Slide Shows in HTML and XHTML]
|
|
|Slidy
|
|
|https://astefanutti.github.io/decktape/examples/html-slidy-presentation.pdf[html-slidy-presentation.pdf] (0.5MB)
|
|
|
|
|https://inspirejs.org[Inspire.js: Lean, hackable, extensible slide deck framework]
|
|
|Inspire.js
|
|
|https://astefanutti.github.io/decktape/examples/inspirejs-sample-slideshow.pdf[inspirejs-sample-slideshow.pdf] (1.9MB)
|
|
|
|
|https://shwr.me[Shower Presentation Engine]
|
|
|Shower
|
|
|https://astefanutti.github.io/decktape/examples/shower-presentation-engine.pdf[shower-presentation-engine.pdf] (0.6MB)
|
|
|
|
|http://mikemaccana.github.io/rejectjs2013[Welcome our new ES5 Overloards]
|
|
|Bespoke.js
|
|
|https://astefanutti.github.io/decktape/examples/new-es5-overloards.pdf[new-es5-overloards.pdf] (0.2MB)
|
|
|
|
|https://formidable.com/open-source/spectacle/[Spectacle: A ReactJS Presentation Library]
|
|
|Spectacle
|
|
|https://astefanutti.github.io/decktape/examples/spectacle-reactjs-presentation.pdf[spectacle-reactjs-presentation.pdf] (1.2MB)
|
|
|===
|
|
|
|
== Docker
|
|
|
|
DeckTape can be executed within a Docker container from the command-line using the {uri-docker-image}[`astefanutti/decktape`] Docker image available on {uri-docker-hub}[Docker Hub]:
|
|
|
|
$ docker run astefanutti/decktape -h
|
|
|
|
For example:
|
|
|
|
* To convert an online HTML presentation and have it exported into the working directory under the `slides.pdf` filename:
|
|
[source,shell,subs=attributes+]
|
|
$ docker run --rm -t -v `pwd`:/slides astefanutti/decktape https://revealjs.com/demo/ slides.pdf
|
|
|
|
* Or, to convert an HTML presentation that's stored on the local file system in the `home` directory:
|
|
[source,shell]
|
|
$ docker run --rm -t -v `pwd`:/slides -v ~:/home/user astefanutti/decktape /home/user/slides.html slides.pdf
|
|
|
|
* Or, to convert an HTML presentation that's deployed on the local host:
|
|
[source,shell]
|
|
$ docker run --rm -t --net=host -v `pwd`:/slides astefanutti/decktape http://localhost:8000 slides.pdf
|
|
+
|
|
You may have to use `host.docker.internal` instead of `localhost` on macOS and Windows.
|
|
|
|
You may want to specify a tag corresponding to a released version of DeckTape for the Docker image, e.g. `astefanutti/decktape:{decktape-version}`.
|
|
|
|
Besides, it is recommended to use the following options from the {uri-docker-ref}/run[`docker run`] command:
|
|
|
|
{uri-docker-ref}/run/#clean-up-rm[`--rm`]:: DeckTape is meant to be run as a short-term foreground process so that it's not necessary to have the container's file system persisted after DeckTape exits,
|
|
{uri-docker-ref}/commandline/run/#mount-volume-v-read-only[`-v`]:: to mount a data volume so that DeckTape can directly write to the local file system.
|
|
|
|
Alternatively, you can use the {uri-docker-ref}/commandline/cp[`docker cp`] command, e.g.:
|
|
|
|
[source,shell,subs=attributes+]
|
|
----
|
|
# Run docker run without the --rm option
|
|
$ docker run astefanutti/decktape {uri-revealjs} slides.pdf
|
|
# Copy the exported PDF from the latest used container to the local file system
|
|
$ docker cp `docker ps -lq`:slides/slides.pdf .
|
|
# Finally remove the latest used container
|
|
$ docker rm `docker ps -lq`
|
|
----
|
|
|
|
If your presentation relies on fonts installed on the host system, but not in the base Docker container, you can mount your fonts
|
|
directory as a volume, e.g. for macOS:
|
|
|
|
[source]
|
|
$ docker run -v "${HOME}/Library/Fonts:/home/node/.local/share/fonts" ...
|
|
|
|
== FAQ
|
|
|
|
=== Install
|
|
|
|
* *_I'm using Arch Linux, is there an AUR package?_*
|
|
+
|
|
Yes, it is available at https://aur.archlinux.org/packages/nodejs-decktape/.
|
|
|
|
=== Usage
|
|
|
|
* *_Is it possible to pass arguments to Chrome?_*
|
|
+
|
|
Yes, you can use the `--chrome-arg` option, e.g.:
|
|
+
|
|
[source,shell]
|
|
----
|
|
$ decktape ... \
|
|
--chrome-arg=--proxy-server="proxy:8080" \
|
|
--chrome-arg=--allow-file-access-from-files
|
|
----
|
|
+
|
|
The list of Chromium flags can be found https://peter.sh/experiments/chromium-command-line-switches/[here].
|
|
|
|
=== Troubleshooting
|
|
|
|
* *_No usable sandbox!_*
|
|
+
|
|
Arch Linux, among other Linux distributions may have the user namespace in the kernel disabled by default. You can verify this by accessing _chrome://sandbox_ in your chrom[e|ium] browser. You can find more about sandboxing, https://chromium.googlesource.com/chromium/src/+/master/docs/linux_sandboxing.md#User-namespaces-sandbox[here]. As a _temporary_ work-around, you can pass `--chrome-arg=--no-sandbox` as a CLI option.
|
|
|
|
* *_Failed to read the 'rules' property from 'CSSStyleSheet': Cannot access rules_*
|
|
+
|
|
Starting Chromium 64, accessing CSS rules in a stylesheet loaded from the local filesystem or an external location violates CORS policies.
|
|
As some Decktape plugins tweak the CSS rules for better PDF printing, you need to allow access to local files or external stylesheets by setting the `--disable-web-security` flag option, e.g.:
|
|
+
|
|
[source,shell]
|
|
----
|
|
$ decktape ... --chrome-arg=--disable-web-security
|
|
----
|
|
|
|
* *_Layout inconsistencies_*
|
|
+
|
|
Decktape relies on Pupeteer to convert each slide in PDF format. Slight layout inconsistencies can result as part of this transformation. One workaround is to set a specific slide size using the `-s` option. The value of `-s 1024x768` has generally worked well in such situations.
|
|
+
|
|
* *_Reveal.js slide generation never finishes_*
|
|
+
|
|
Decktape does not use the built-in PDF support of reveal.js, and instead captures each slide individually. Therefore you must not append `?print-pdf` or load the print stylesheets in any other way when using Decktape.
|
|
|
|
== Plugin API
|
|
|
|
{icon-edit}
|