pdf-slave
Tool that compiles haskintex
(TeX with embedded Haskell) files into PDF documents.
Templates are described in YAML format and can define dependencies.
Features:
-
Input JSON file for htex
file that holds template varying data.
-
Option for packing a template in all-in YAML bundle.
-
Support for template dependencies that include:
- Bibtex files
- Images, listings, other static files.
- Other
.htex
templates that compiles into TeX and includes into parent template.
- Other
.htex
templates that compiles into PDF and includes into parent template.
Template reference
Common template consists of several files:
template_input.json
- Input data for template in JSON format.
{
"line-width": 2,
"spiral-precision": 0.01,
"spiral-interval": [0,4],
"spiral-a": 0.1,
"spiral-b": 4
}
template.htex
- TeX/LaTeX with embedded Haskell that reads input data from
file template.json
. You have to provide code at the beginning of file that reads
the inputs, like that:
\begin{document}
\begin{haskellpragmas}
{-# LANGUAGE OverloadedStrings #-}
\end{haskellpragmas}
\begin{writehaskell}
import Data.Aeson
import System.IO.Unsafe (unsafePerformIO)
import qualified Data.ByteString.Lazy as BS
data Input = Input {
lineWidth :: Double
, spiralPrecision :: Double
, spiralInterval :: (Double, Double)
, spiralA :: Double
, spiralB :: Double
}
instance FromJSON Input where
parseJSON (Object o) = Input
<$> o .: "line-width"
<*> o .: "spiral-precision"
<*> o .: "spiral-interval"
<*> o .: "spiral-a"
<*> o .: "spiral-b"
inpt :: Input
inpt = case unsafePerformIO $ fmap eitherDecode' $ BS.readFile "template_input.json" of
Left e -> error (show e)
Right a -> a
\end{writehaskell}
template.yaml
- description of template and its dependencies.
name: template01 # name of template
input: template01_input.json # name of input file
body: template01.htex # name of .htex file
dependencies: {} # dependency tree (see below)
haskintex-opts: [] # additional flags to haskintex
Dependencies
There are 4 different types of dependencies:
-
other
- static files that don't require any processing. They could be images,
listings etc. Example of YAML configuration:
dependencies:
lambda.png: # name of dependency is equal to filename relative to parent template
type: other # marks type of dependency
code/demo.hs:
type: other
See examples/example02 for full example.
-
bibtex
- bibliography files that require additional passes with bibtex
. Example of YAML configuration:
dependencies:
biblio.bib: # name of dependency is equal to filename relative to parent template
type: bibtex # marks type of dependency
See examples/example03 for full example.
-
template
- other .htex
templates that are included in parent via \\input{...}
or \\include{..}
. Example of YAML configuration:
dependencies:
dep1: # name of dependency defines subfolder where the output tex file is located
type: template # marks type of dependency
name: dep1
input: dep1_input.json
body: dep1.htex
dep2:
type: template
name: dep2
body: dep2.htex
dependencies:
lambda.png:
type: other
code/demo.hs:
type: other
See examples/example04 for full example.
Note that code/demo.hs
subdependency should be included as dep2/code/demo.hs
in dep2.htex
as dep2.tex
is inlined into parent.
-
template_pdf
- other .htex
templates that are included as PDFs into parent template. Example of YAML configuration:
dependencies:
template01: # name of dependency defines subfolder where the output tex file is located
type: template_pdf # marks type of dependency
name: template01
input: template01_input.json
body: template01.htex
template02:
type: template_pdf
name: template02
body: template02.htex
dependencies:
lambda.png:
type: other
code/demo.hs:
type: other
See examples/example05 for full example.
When you work with dependencies you have two options how to handle inputs:
-
Define dependency inputs in its own file:
dependencies:
dep1:
type: template
name: dep1
input: dep1_input.json # private input file
body: dep1.htex
-
Define dependency inputs in parent file:
name: template06
input: template06_input.json # contains inputs for dep1
body: template06.htex
dependencies:
dep1:
type: template
name: dep1
body: dep1.htex
Contents of template06_input.json
:
{
"dep1": {
"line-width": 2,
"spiral-precision": 0.01,
"spiral-interval": [0,4],
"spiral-a": 0.1,
"spiral-b": 4
}
}
Note that key of subsection must be equal to name of dependency.
See examples/example06 for full example.
Making bundles
One can pack all .htex
, .json
, .yaml
and all dependencies in single YAML
bundle that can be easily distributed, transmitted between services and stored:
cd examples/template01
pdf-slave --template template01.yaml --output template01_bundle.yaml pack
As modification of such bundles isn't handy, one can unpack bundle:
pdf-slave --template template01_bundle.yaml --output template01_directory unpack
Rendering of bundles is handled with the same command that is used for ordinary
templates.
Compilation
You need:
Compilation with stack:
git clone https://github.com/NCrashed/pdf-slave.git
cd pdf-slave
stack install
Compilation with cabal:
git clone https://github.com/NCrashed/pdf-slave.git
cd pdf-slave
cabal sandbox init
cabal install --dependencies-only
cabal install
Running examples
You need:
-
LaTeX distribution (for instance, texlive or miktex)
-
stack or GHC+Cabal (yes, you need GHC to evaluate templates at runtime)
-
pdf-slave
and haskintex
executables in PATH
Stack users:
cd examples/template01
stack install aeson HaTeX
stack exec -- pdf-slave --template template01.yaml --output output.pdf pdf && xdg-open output.pdf
Cabal users:
cd examples/template01
cabal sandbox init
cabal install aeson HaTeX
pdf-slave --template template01.yaml --output output.pdf pdf && xdg-open output.pdf
Docker build
-
Run cook_doocker.sh
script. This will build two images, one pdf-slave-build
for compilation of binaries and the second one pdf-slave
for production usage.
-
Usage:
docker run -it --rm -v $(pwd)/examples/template01:/data/examples pdf-slave pdf --template examples/template01.yaml --output examples/output.pdf
xdg-open examples/template01/output.pdf
- Or download precompiled container from Docker Hub.