packages feed

pdf-slave-1.3.0.0: README.md

pdf-slave
=========

[![Build Status](https://travis-ci.org/NCrashed/pdf-slave.svg?branch=master)](https://travis-ci.org/NCrashed/pdf-slave)

Tool that compiles [haskintex](http://daniel-diaz.github.io/projects/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.

Description
===========

In many real-world systems we need to produce reports, cheques and other documents
to users. One possible solution is rendering LaTeX files, but it is not flexible
enough as you need to solve burden with generation of LaTeX file from varying inputs,
manage static files like images and handling dependencies between pieces of document.

The new tool takes the burden away. Now all static files and generation code is
located within a single template project, that describes how to build your PDF document in a declaretive way.

Common work flow with pdf-slave:
* Develop template from several LaTeX files with embedded Haskell (thanks to [haskintex](http://daniel-diaz.github.io/projects/haskintex/)
 tool)

* Pack the template project into bundle all-in file.

* Distribute the bundle (for instance to your service server).

* Call pdf-slave with bundle and inputs in JSON file to generate PDF document.

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:

  Make a `Helper.hs` file in directory with template:
  ``` haskell
  module Helper where

  import qualified Data.ByteString.Lazy as BS
  import Data.Aeson
  import System.IO.Unsafe

  defaultInput :: FromJSON a => a
  {-# NOINLINE defaultInput #-}
  defaultInput = case unsafePerformIO $ fmap eitherDecode' $ BS.readFile "input.json" of
    Left e -> error (show e)
    Right a -> a
  ```

  Next in your `.htex` file:
  ``` Haskell
  \begin{document}

  \begin{haskellpragmas}
  {-# LANGUAGE OverloadedStrings #-}
  \end{haskellpragmas}
  \begin{writehaskell}
  import Data.Aeson
  import Helper

  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 = defaultInput
  \end{writehaskell}
  ```

  Note: The tool copies JSON with inputs to build folder with .htex twice, once with
  name specified at `input` key in template description and secondly at fixed `input.json`.

* `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
  ```

  For input `Helper.hs` you should make a record to inform `pdf-slave` that the module should be copied to build directory:

  ``` YAML
  dependencies:
    Helper.hs:
      type: other
  ```

## 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.


Credits
=======

* Daniel Díaz - author of `haskintex` tool that is core of the package.

* Alexander Vershilov aka qnikst - help with debugging and new `Helper.hs` module.