NAME

LaTeX::Easy::Templates - Easily format content into PDF/PS/DVI with LaTeX templates.

VERSION

Version 0.01

SYNOPSIS

This module provides functionality to format text content, living in a Perl data structure, into printer-ready documents (PDF/Postscript/DVI). It utilises the idea of Templates and employs the powerful LaTeX (via LaTeX::Driver) in order to format and render the final documents into printer feed.

Its use requires that LaTeX is already installed in your system. Don't be alarmed! LaTeX is simple to install in any OS. Download the installer from here: https://www.tug.org/texlive/ or, if you have Linux, add it via your package manager. Using LaTeX will not only empower you like Guttenberg's press did and does, but it will also satisfy even the highest aesthetic standards with its 20/20 perfect typography. LaTeX is one of the rare cases where Software can be termed as Hardware. Install it and use it. Now.

Here is a basic scenario borrowed from Dilbert's adventures. You have a number of emails with fields like sender, recipient, subject and content. This data can be represented in Perl as an array of hashes like:

[
  {
    sender => 'jack',
    recipient => 'the clown',
    subject => 'hello',
    content => 'blah blah',
  },
  {
    sender => 'dede',
    recipient => 'kinski',
    subject => 'Paris rooftops',
    content => 'blah2 blah2',
  },
  ...
]

You want to render this data to PDF.

A more interesting scenario:

You are scraping a, say, News website. You want each article rendered as PDF. Your scraper provides the following data for each News article, and you have lots of those:

[
  {
    author => 'jack',
    title => '123',
    date => '12/12/2012',
    content => [
       'paragraph1',
       'paragraph2',
       ...
    ],
    comments => [
      {
        'author' => 'sappho',
        'content' => 'yearning ...',
     },
     ... # more comments
  }
  ... # more News articles
]

Once you collect your data and save it into a Perl data structure as above (note: the stress is on structure) you need to create a templated LaTeX document which will be complete except that where the author, sender, recipient, content, etc. would be, you will place some tags like:

<: $author :>
<: $sender :>

etc.

The LaTeX::Easy::Templates module will then take your data and your LaTeX template and produce the final rendered documents.

In section "STARTING WITH LaTeX" you will see how to easily build a LaTeX template from open source, publicly available, superbly styled "themes".

use LaTeX::Easy::Templates;

# templated LaTeX document in-memory
# (with variables to be substituted)
my $latex_template =<<'EOLA';
% basic LaTeX document
\documentclass[a4,12pt]{article}
\begin{document}
\title{ <: $data.title :> }
\author{ <: $data.author.name :> <: $data.author.surname :> }
\date{ <: $data.date :> }
\maketitle
<: $data.content :>
\end{document}
EOLA

# my template variable substitutions
my $template_data = {
  'title' => 'a test title',
  'author' => {
    'name' => 'myname',
    'surname' => 'surname',
  },
  'date' => '2024/12/12',
  'content' => 'blah blah',
};

my $latte = LaTeX::Easy::Templates->new({
  debug => {verbosity=>2, cleanup=>1},
  'processors' => {
    'mytemplate' => {
      'template' => {
        'content' => $latex_template_string,
      },
      'output' => {
        'filepath' => 'output.pdf'
      }
    }
  }
});
die unless $latte;

my $ret = $latter->format({
  'template-data' => $template_data,
  'outfile' => 'xyz.pdf',
  # this is the in-memory LaTeX template
  'processor' => 'mytemplate'
});
die unless $ret;

In this way you can nicely and easily typesed your data into a PDF.

METHODS

new()

The constructor.

The full list of arguments, provided as a hashref, is as follows:

The constructor returns undef on failure.

Here is example code for calling the constructor:

 use LaTeX::Easy::Template;
 my $latter = LaTeX::Easy::Template->new({
  'processors' => {
    'in-memory' => {
       'latex' => {
            'filename' => undef # create tmp
       },
       'template' => {
            # the template is in-memory string
            'content' => '...'
       },
       'output' => {
            'filename' => 'out.pdf'
       }
    }
    'on-disk' => {
      'latex' => {
            'filename' => undef, # create tmp
       },
       'template' => {
            'filepath' => 't/templates/simple01/main.tex.tx'
       },
       'output' => {
            'filename' => 'out2.pdf'
       }
    }
  }, # end processors
  # log to this file, path will be created if not exists
  'logfile' => 'xyz/abc.log',
  'latex' => {
    'latex-driver-parameters' => {
       # we want PDF output run with xelatex which
       # easily supports multi-language documents
       'format' => 'pdf(xelatex)',
       'paths' => {
          # the path to the xelatex needed only if not standard
          'xelatex' => '/non-standard-path/xyz/xelatex'
       }
    }
  },
  'verbosity' => 1,
  'cleanup' => 0,
});

The above creates a LaTeX::Easy::Templates object which has 2 "processors" one which uses a LaTeX template from disk and one in-memory. Default LaTeX::Driver parameters are specified as well and will be used for these processors which do not specify any.

untemplate()

It creates a LaTeX source file from a template. This is the first step in rendering the final typeset document. which is done by "format()".

Note that calling this method is not necessary if you intend to call "format()" next. The latter will call the former if needed.

The full list of arguments is as follows:

RETURN

On failure, "untemplate()" returns back undef.

On success, it returns back a hash(ref) with two entries:

format()

It renders the final typeset document. It will call "untemplate()" if is required to produce the intermediate LaTeX source file. If that file was specified, then it will render the final document by calling LaTeX::Driver.

The full list of arguments, provided by a hashref, is as follows:

RETURN

On failure, "format()" returns back undef.

On success, it returns back a hash(ref) with three entries:

max_size_for_filecopy($maxsize)

It gets or sets (with optional parameter $maxsize) the maximum size for doing a recursive file copy. Recursive file copies are done for template extra files which may be needed for processing the template or running latex. They are specified if template->basedir is explicitly set (then the whole basedir will be copied) or when template->auxfiles are specified as an arrayref of files/dirs to copy individually. In order to reduce the risk of unintentionally copying vast files and directories there is a limit to the total (recursively calculated) size of files/directories to be copied. This can be set here. The default is 3MB. However if you set this limit to a negative integer no checks will be make and file copying will be done unreservedly.

verbosity($verbosity)

It gets or sets (with optional parameter $verbosity) the verbosity level.

cleanup($c)

It gets or sets (with optional parameter $c) the cleanup parameter which contols the cleaning up of temporary files and directories or not. Set it to 1 to clean up. This is currently the default. Set it to 0 to keep these files for inspection during debugging.

templater($t)

It gets or sets (with optional parameter $t) the templater object. This is the object which convertes the LaTeX template into LaTeX source. Currently only Text::Xslate is supported.

templater_reset()

Reset the templater object which means to forget all the templates it knows and had possibly loaded in memory. After a reset all "processors" will be forgotten as well.

templater_parameters($m, $n)

It gets or sets (with optional parameter $m and possiblt $n) the parameters to be passed to the templater's (Text::Xslate) constructor:

These are some common templater paramaters:

See Text::Xslate#Text::Xslate-%3Enew(%options) for more.

log($l)

It gets or sets (with optional parameter $l) the logger object. Currently the logger is of type Mojo::Log.

latex_driver_executable($program_name)

This is an exported sub (and not a method)

It enquires LaTeX::Driver for what is the fullpath to the program named $program_name. The program can be latex, dvips, makeindex, pdflatex etc. If the program is not found it returns undef.

The parameter is optional, if it is omitted a hash(ref) with all known paths is returned.

Note that LaTeX::Driver's paths are detected during its installation. Paths can be set during running "format()" by passing it latex->latex-driver-parameters->paths (a hashref mapping program names to their paths).

processors()

It returns the hash(ref) of known "processors" as they were set up during construction.

loaded_info()

It returns the hash(ref) of extra information relating to the "processors".

STARTING WITH LaTeX

Currently, the best place to get started with LaTeX is at the site https://www.overleaf.com/ (which I am not affiliated in any way). There is no subscription involved or any registration required.

Click on Templates and search for anything you are interested to typeset your data with. For example, if you are scraping a news website you may be interested in the Committee Times template. First check its license and if you agree with that, click on View Source, copy the contents and paste them into your new LaTeX file, let's call that main.tex located in a new directory templates/committee-times.

Firstly, run latex on it to with latex main.tex to see if there are any required files you need to install. For example it requires package newspaper. These packages are located at the Comprehensive TeX Archive Network (CTAN) . Search the package, download it, locate and change to your LaTeX installation directory (for example /usr/share/texlive/texmf-dist), change to tex. Decide which flavour of LaTeX this package is for, e.g. latex or xelatex, change to that directory and unzip the downloaded file there. This is the hard way. The easy way is via your package manager. For example on Fedora with dnf there is this package texlive-newspaper.noarch. Easy. Running latex will tell you if it requires more packages to be installed.

Now study that LaTeX source file and identify what template variables and control structures to use in order to turn it into a template. Rename the file to main.tex.tx and you are ready.

Naturally, there will be a lot of head banging and hair pulling before you manage to produce anything decent.

LaTeX TEMPLATES

Creating a LaTeX template is very easy. You need to start with a LaTeX document and identify those sections which can be replaced by the template variables. You can also identify repeated sections and replace them with loops. It is exactly the same procedure as with creating HTML templates or email messages templates.

TEMPLATE PROCESSING

The LaTeX templates will be processed with Text::Xslate and must follow its rules. It understands two template syntaxes:

The default syntax is Text::Xslate::Syntax::Kolon. This can be changed via the parameters to the constructor of LaTeX::Easy::Templates by specifying

'templater-parameters' => {
    'syntax' => 'Kolon' #or 'TTerse'
}

or setting it before running "untemplate()" with

$latte->templater_parameters('syntax' => 'Kolon');

The data for the template variables comes bundled into a hashref which comes bundled into a hashref of a single key data. Therefore all references must be preceded by key data.

So if your template data is this:

{
  name => 'aa',
}

Then your template will access name's value via <: $data.name : >.

Text::Xslate supports loops and conditional statements etc. etc. Read Text::Xslate::Syntax::Kolon and/or Text::Xslate::Syntax::TTerse.

AUTHOR

Andreas Hadjiprocopis, <bliako at cpan.org>

HUGS

!Almaz!

BUGS

Please report any bugs or feature requests to bug-latex-easy-templates at rt.cpan.org, or through the web interface at https://rt.cpan.org/NoAuth/ReportBug.html?Queue=LaTeX-Easy-Templates. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.

SUPPORT

You can find documentation for this module with the perldoc command.

perldoc LaTeX::Easy::Templates

You can also look for information at:

ACKNOWLEDGEMENTS

LICENSE AND COPYRIGHT

This software is Copyright (c) 2023 by Andreas Hadjiprocopis.

This is free software, licensed under:

The Artistic License 2.0 (GPL Compatible)