pdf-slave-1.0.0.0: README.md
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.
``` JSON
{
"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:
``` Haskell
\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.
``` YAML
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:
``` YAML
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](https://github.com/NCrashed/pdf-slave/tree/master/examples/template02) for full example.
* `bibtex` - bibliography files that require additional passes with `bibtex`. Example of YAML configuration:
``` YAML
dependencies:
biblio.bib: # name of dependency is equal to filename relative to parent template
type: bibtex # marks type of dependency
```
See [examples/example03](https://github.com/NCrashed/pdf-slave/tree/master/examples/template03) for full example.
* `template` - other `.htex` templates that are included in parent via `\\input{...}` or `\\include{..}`. Example of YAML configuration:
``` YAML
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](https://github.com/NCrashed/pdf-slave/tree/master/examples/template04) 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:
``` YAML
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](https://github.com/NCrashed/pdf-slave/tree/master/examples/template05) for full example.
### Input propagation
When you work with dependencies you have two options how to handle inputs:
* Define dependency inputs in its own file:
``` YAML
dependencies:
dep1:
type: template
name: dep1
input: dep1_input.json # private input file
body: dep1.htex
```
* Define dependency inputs in parent file:
``` YAML
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`:
``` 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](https://github.com/NCrashed/pdf-slave/tree/master/examples/template06) 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:
``` bash
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:
``` bash
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:
* LaTeX distribution (for instance, texlive or miktex)
* [stack](https://docs.haskellstack.org/en/stable/README/) or system wide GHC 8.0.1 + Cabal 1.24.0.
Compilation with stack:
``` bash
git clone https://github.com/NCrashed/pdf-slave.git
cd pdf-slave
stack install
```
Compilation with cabal:
``` bash
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:
``` bash
cd examples/template01
stack install aeson HaTeX
stack exec -- pdf-slave --template template01.yaml --output output.pdf pdf && xdg-open output.pdf
```
Cabal users:
``` bash
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
============
1. 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.
2. Usage:
``` bash
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
```
3. Or download [precompiled container](https://hub.docker.com/r/ncrashed/pdf-slave/) from Docker Hub.