File Coverage

lib/Template/Plugin/Latex.pm
Criterion Covered Total %
statement 13 15 86.6
branch n/a
condition n/a
subroutine 5 5 100.0
pod n/a
total 18 20 90.0


line stmt bran cond sub pod time code
1             #============================================================= -*-perl-*-
2             #
3             # Template::Plugin::Latex
4             #
5             # $Id:$
6             #
7             # DESCRIPTION
8             # Template Toolkit plugin for Latex
9             #
10             # AUTHOR
11             # Chris Travers <chris.travers@gmail.com> (Current Maintainer)
12             # Andrew Ford <a.ford@ford-mason.co.uk>
13             # Andy Wardley <abw@wardley.org>
14             #
15             # COPYRIGHT
16             # Copyright (C) 2014-2016 Chris Travers. All Rights Reserved.
17             # Copyright (C) 2006-2014 Andrew Ford. All Rights Reserved.
18             # Copyright (C) 1996-2006 Andy Wardley. All Rights Reserved.
19             #
20             # This module is free software; you can redistribute it and/or
21             # modify it under the same terms as Perl itself.
22             #
23             # HISTORY
24             # * Originally written by Craig Barratt, Apr 28 2001.
25             # * Win32 additions by Richard Tietjen.
26             # * Extracted into a separate Template::Plugin::Latex module by
27             # Andy Wardley, 27 May 2006
28             # * Removed the program pathname options on the FILTER call
29             # Andrew Ford, 05 June 2006
30             # * Totally rewritten by Andrew Ford September 2007
31             # * Version 3.00 released March 2009
32             #
33             #========================================================================
34              
35             package Template::Plugin::Latex;
36              
37 4     4   60222 use strict;
  4         10  
  4         99  
38 4     4   20 use warnings;
  4         10  
  4         137  
39 4     4   20 use base 'Template::Plugin';
  4         8  
  4         1567  
40              
41 4     4   2009 use File::Spec;
  4         20  
  4         86  
42 4     4   1969 use LaTeX::Driver 0.07;
  0            
  0            
43             use LaTeX::Encode;
44             use LaTeX::Table;
45              
46              
47             our $VERSION = '3.12'; # Update "=head1 VERSION" below!!!!
48             our $DEBUG; $DEBUG = 0 unless defined $DEBUG;
49             our $ERROR = '';
50             our $FILTER = 'latex';
51             our $THROW = 'latex'; # exception type
52              
53             #------------------------------------------------------------------------
54             # constructor
55             #
56             #------------------------------------------------------------------------
57              
58             sub new {
59             my ($class, $context, $options) = @_;
60              
61             # make sure that $options is a hash ref
62             $options ||= {};
63              
64             # create a closure to generate filters with additional options
65             my $filter_factory = sub {
66             my $factory_context = shift;
67             my $filter_opts = ref $_[-1] eq 'HASH' ? pop : { };
68             my $filter_args = [ @_ ];
69             $filter_opts->{$_} //= $options->{$_} for keys %$options;
70             return sub {
71             # Template::Plugin::Latex::_filter->run($context, $filter_opts, $filter_args, @_);
72             _tt_latex_filter($class, $factory_context, $filter_opts, $filter_args, @_);
73             };
74             };
75              
76             # create a closure to generate filters with additional options
77             my $encode_filter_factory = sub {
78             my $factory_context = shift;
79             my $filter_opts = ref $_[-1] eq 'HASH' ? pop : { };
80             my $filter_args = [ @_ ];
81             $filter_opts->{$_} //= $options->{$_} for keys %$options;
82             return sub {
83             # Template::Plugin::Latex::_filter->run($context, $filter_opts, $filter_args, @_);
84             _tt_latex_encode_filter($class, $factory_context, $filter_opts, $filter_args, @_);
85             };
86             };
87              
88             # and a closure to represent the plugin
89             my $plugin = sub {
90             my $plugopt = ref $_[-1] eq 'HASH' ? pop : { };
91             $plugopt->{$_} //= $options->{$_} for keys %$options;
92             # Template::Plugin::Latex::_filter->run($context, $plugopt, @_ );
93             _tt_latex_filter($class, $context, $plugopt, {}, @_ );
94             };
95              
96              
97             # now define the filter and return the plugin
98             $context->define_filter('latex_encode', [ $encode_filter_factory => 1 ]);
99             $context->define_filter($options->{filter} || $FILTER, [ $filter_factory => 1 ]);
100              
101             return bless $plugin, $class;
102             }
103              
104              
105             #------------------------------------------------------------------------
106             # _tt_latex_encode_filter
107             #
108             #
109             #------------------------------------------------------------------------
110              
111             sub _tt_latex_encode_filter {
112             my ($class, $context, $options, $filter_args, @text) = @_;
113             my $text = join('', @text);
114             return latex_encode($text, %{$options});
115             }
116              
117              
118             #------------------------------------------------------------------------
119             # _tt_latex_filter
120             #
121             #
122             #------------------------------------------------------------------------
123              
124             sub _tt_latex_filter {
125             my ($class, $context, $options, $filter_args, @text) = @_;
126             my $text = join('', @text);
127              
128             # Get the output and format options
129              
130             # my $output = $options->{output};
131             my $output = delete $options->{ output } || shift(@$filter_args) || '';
132             my $format = $options->{format};
133              
134             # If the output is just a format specifier then set the format to
135             # that and undef the output
136              
137             if ($output =~ /^ (?: dvi | ps | pdf(?:\(\w+\))? ) $/x) {
138             ($format, $output) = ($output, undef);
139             }
140              
141             # If the output is a filename then convert to a full pathname in
142             # the OUTPUT_PATH directory, outherwise set the output to a
143             # reference to a temporary variable.
144              
145             if ($output) {
146             my $path = $context->config->{ OUTPUT_PATH }
147             or $class->_throw('OUTPUT_PATH is not set');
148             $output = File::Spec->catfile($path, $output);
149             }
150             else {
151             my $temp;
152             $output = \$temp;
153             }
154              
155             # Run the formatter
156              
157             eval {
158             my $drv = LaTeX::Driver->new( source => \$text,
159             output => $output,
160             format => $format,
161             maxruns => $options->{maxruns},
162             extraruns => $options->{extraruns},
163             texinputs => _setup_texinput_paths($context),
164             );
165             $drv->run;
166             };
167             if (my $e = LaTeX::Driver::Exception->caught()) {
168             $class->_throw("$e");
169             }
170              
171             # Return the text if it was output to a scalar variable, otherwise
172             # return nothing.
173              
174             return ref $output ? $$output : '';
175             }
176              
177              
178             #------------------------------------------------------------------------
179             # $self->setup_texinput_paths
180             #
181             # setup the TEXINPUT path environment variables
182             #------------------------------------------------------------------------
183              
184             sub _setup_texinput_paths {
185             my ($context) = @_;
186             my $template_name = $context->stash->get('template.name');
187             my $include_path = [];
188              
189             # Ask each Template::Provider object for a list of paths. This properly
190             # handles coderefs and objects in INCLUDE_PATH.
191             for my $provider (@{ $context->{LOAD_TEMPLATES} }) {
192             push @$include_path, @{ $provider->paths || [] };
193             }
194              
195             my @texinput_paths = ("");
196             foreach my $path (@$include_path) {
197             my $template_path = File::Spec->catfile($path, $template_name);
198             if (-f $template_path) {
199             my($volume, $dir) = File::Spec->splitpath($template_path);
200             $dir = File::Spec->catfile($volume, $dir);
201             unshift @texinput_paths, $dir;
202             next if $dir eq $path;
203             }
204             push @texinput_paths, $path;
205             }
206             return \@texinput_paths;
207             }
208              
209              
210             sub _throw {
211             my $self = shift;
212             die Template::Exception->new( $THROW => join('', @_) );
213             }
214              
215              
216             sub table {
217             my $args = ref($_[-1]) eq 'HASH' ? pop(@_) : { };
218             my ($table, $text);
219             eval {
220             $table = LaTeX::Table->new($args);
221             $text = $table->generate_string;
222             };
223             if ($@) {
224             die Template::Exception->new( $THROW => $@ );
225             }
226             return $text;
227             }
228              
229              
230             1;
231              
232             __END__
233              
234             =head1 NAME
235              
236             Template::Plugin::Latex - Template Toolkit plugin for Latex
237              
238             =head1 VERSION
239              
240             This documentation refers to C<Template::Plugin::Latex> version 3.12
241              
242             =head1 SYNOPSIS
243              
244             Sample Template Toolkit code:
245              
246             [%- USE Latex;
247              
248             mystr = "a, b & c" | latex_encode;
249              
250             FILTER latex("pdf"); -%]
251              
252             \documentclass{article}
253             \begin{document}
254             This is a PDF document generated by
255             LaTeX and the Template Toolkit, with some
256             interpolated data: [% mystr %]
257             \end{document}
258              
259             [% END; -%]
260              
261              
262             =head1 DESCRIPTION
263              
264             The C<Latex> Template Toolkit plugin provides a C<latex> filter that
265             allows the use of LaTeX to generate PDF, PostScript and DVI output files
266             from the Template Toolkit. The plugin uses L<LaTeX::Driver> to run the
267             various LaTeX programs.
268              
269             Processing of the LaTeX document takes place in a temporary directory
270             that is deleted once processing is complete. The standard LaTeX
271             programs (C<latex> or C<pdflatex>, C<bibtex> and C<makeindex>) are run
272             and re-run as necessary until all references, indexes, bibliographies,
273             table of contents, and lists of figures and tables are stable or it is
274             apparent that they will not stabilize. The format converters C<dvips>,
275             C<dvipdf>, C<ps2pdf> and C<pdf2ps> are run as necessary to convert the
276             output document to the requested format. The C<TEXINPUTS> environment
277             variable is set up to include the template directory and the C<INCLUDES>
278             directories, so that LaTeX file inclusion commands should find the
279             intended files.
280              
281             The output of the filter is binary data (although PDF and PostScript are
282             not stictly binary). You should be careful not to prepend or append any
283             extraneous characters (even space characters) or text outside the FILTER
284             block as this text will be included in the file output. Notice in the
285             example below how we use the post-chomp flags ('-') at the end of the
286             C<USE> and C<END> directives to remove the trailing newline characters:
287              
288             [% USE Latex(format='pdf') -%]
289             [% FILTER latex %]
290             ...LaTeX document...
291             [% END -%]
292              
293             If you're redirecting the output to a file via the third argument of
294             the Template module's C<process()> method then you should also pass
295             the C<binmode> parameter, set to a true value to indicate that it is a
296             binary file.
297              
298             use Template;
299              
300             my $tt = Template->new({
301             INCLUDE_PATH => '/path/to/templates',
302             OUTPUT_PATH => '/path/to/pdf/output',
303             });
304             my $vars = {
305             title => 'Hello World',
306             }
307             $tt->process('example.tt2', $vars, 'example.pdf', binmode => 1)
308             || die $tt->error();
309              
310             If you want to capture the output to a template variable, you can do
311             so like this:
312              
313             [% output = FILTER latex %]
314             ...LaTeX document...
315             [% END %]
316              
317             You can pass additional arguments when you invoke the filter, for
318             example to specify the output format.
319              
320             [% FILTER latex(format='pdf') -%]
321             ...LaTeX document...
322             [% END %]
323              
324             If you want to write the output to a file then you can specify an
325             C<output> parameter.
326              
327             [% FILTER latex(output='example.pdf') %]
328             ...LaTeX document...
329             [% END %]
330              
331             If you don't explicitly specify an output format then the filename
332             extension (e.g. 'pdf' in the above example) will be used to determine
333             the correct format.
334              
335             You can specify a different filter name using the C<filter> parameter.
336              
337             [% USE Latex(filter='pdf') -%]
338             [% FILTER pdf %]
339             ...LaTeX document...
340             [% END %]
341              
342             You can also specify the default output format. This value can be
343             C<latex>, C<pdf> or C<dvi>.
344              
345             [% USE Latex(format='pdf') %]
346              
347              
348             Note: the C<LaTeX::Driver> distribution includes three filter programs
349             (C<latex2dvi>, C<latex2pdf> and C<latex2ps>) that use the
350             C<LaTeX::Driver> package to process LaTeX source data into DVI, PDF or
351             PostScript file respectively. These programs have a C<-tt2> option to
352             run their input through the Template Toolkit before processing as LaTeX
353             source. The programs do not use the C<Latex> plugin unless the template
354             requests it, but they may provide an alternative way of processing
355             Template Toolkit templates to generate typeset output.
356              
357              
358             =head1 SUBROUTINES/METHODS
359              
360             =head2 C<USE Latex(options)>
361              
362             This statement loads the plugin (note that prior to version 2.15 the
363             filter was built in to Template Toolkit so this statement was
364             unnecessary; it is now required).
365              
366              
367             =head2 The C<latex> Filter
368              
369             The C<latex> filter accepts a number of options, which may be
370             specified on the USE statement or on the filter invocation.
371              
372             =over 4
373              
374             =item C<format>
375              
376             specifies the format of the output; one of C<dvi> (TeX device
377             independent format), C<ps> (PostScript) or C<pdf> (Adobe Portable
378             Document Format). The follow special values are also accepted:
379             C<pdf(ps)> (generates PDF via PostScript, using C<dvips> and
380             C<ps2pdf>), C<pdf(dvi)> (generates PDF via dvi, using C<dvipdfm>)
381              
382             =item C<output>
383              
384             the name of the output file, or just the output format
385              
386             =item C<indexstyle>
387              
388             the name of the C<makeindex> style file to use (this is passed with
389             the C<-s> option to C<makeindex>)
390              
391             =item C<indexoptions>
392              
393             options to be passed to C<makeindex>. Useful options are C<-l> for
394             letter ordering of index terms (rather than the default word
395             ordering), C<-r> to disable implicit page range formation, and C<-c>
396             to compress intermediate blanks in index keys. Refer to L<makeindex(1)>
397             for full details.
398              
399             =item C<maxruns>
400              
401             The maximum number of runs of the formatter program (defaults to 10).
402              
403             =item C<extraruns>
404              
405             The number of additional runs of the formatter program after it seems
406             that the formatting of the document has stabilized (default 0). Note
407             that the setting of C<maxruns> takes precedence, so if C<maxruns> is
408             set to 10 and C<extraruns> is set to 3, and formatting stabilizes
409             after 8 runs then only 2 extra runs will be performed.
410              
411             =back
412              
413              
414             =head2 The C<latex_encode> filter
415              
416             The C<latex_encode> filter encodes LaTeX special characters in its
417             input into their LaTeX encoded representations. It also encodes other characters that have
418              
419             The special characters are: C<\> (command character), C<{> (open
420             group), C<}> (end group), C<&> (table column separator), C<#>
421             (parameter specifier), C<%> (comment character), C<_> (subscript),
422             C<^> (superscript), C<~> (non-breakable space), C<$> (mathematics mode).
423              
424              
425             =over 4
426              
427             =item C<except>
428              
429             Lists the characters that should be excluded from encoding. By
430             default no special characters are excluded, but it may be useful to
431             specify C<except = "\\{}"> to allow the input string to contain LaTeX
432             commands such as C<"this is \textbf{bold} text">.
433              
434             =item C<use_textcomp>
435              
436             By default the C<latex_encode> filter will encode characters with the
437             encodings provided by the C<textcomp> LaTeX package (for example the
438             Pounds Sterling symbol is encoded as C<\textsterling{}>). Setting
439             C<use_textcomp = 0> turns off these encodings.
440              
441             =back
442              
443             =head2 C<table()>
444              
445             The C<table()> function provides an interface to the C<LaTeX::Table> module.
446              
447             The following example shows how a simple table can be set up.
448              
449             [%- USE Latex;
450              
451             data = [ [ 'London', 'United Kingdom' ],
452             [ 'Berlin', 'Germany' ],
453             [ 'Paris', 'France' ],
454             [ 'Washington', 'USA' ] ] );
455              
456             text = Latex.table( caption = 'Capitol Cities',
457             label = 'table:capitols',
458             headings = [ [ 'City', 'Country' ] ],
459             data = data );
460             -%]
461              
462             The variable C<text> will hold the LaTeX commands to typeset the table
463             and can be further interpolated into a LaTeX document template.
464              
465             =head1 DIAGNOSTICS
466              
467             Most failures result from invalid LaTeX input and are propagated up from
468             L<LaTeX::Driver>, L<LaTeX::Encode> or L<LaTeX::Table>.
469              
470             Failures detected in this module include:
471              
472             =over 4
473              
474             =item C<OUTPUT_PATH is not set>
475              
476             an output filename was specified but the C<OUTPUT_PATH> configuration
477             option has not been set.
478              
479             =back
480              
481              
482             =head1 DEPENDENCIES
483              
484             =over 4
485              
486             =item L<Template>
487              
488             The Template Toolkit.
489              
490             =item L<LaTeX::Driver>
491              
492             Provides the logic for driving the LaTeX programs.
493              
494             =item L<LaTeX::Encode>
495              
496             Underpins the C<latex_encode> filter.
497              
498             =item L<LaTeX::Table>
499              
500             Underpins the C<table> function.
501              
502             =back
503              
504              
505             =head1 INCOMPATIBILITIES
506              
507             The C<latex> filter was distributed as part of the core
508             Template Toolkit distribution until version 2.15 (released in May 2006),
509             when it was moved into the separate Template-Latex distribution. The
510             C<Latex> plugin must now be explicitly to enable the C<latex> filter.
511              
512              
513             =head1 BUGS AND LIMITATIONS
514              
515             The paths to the F<latex>, F<pdflatex> and F<dvips> should be
516             pre-defined as part of the installation process of L<LaTeX::Driver>
517             (i.e. when you run C<perl Makefile.PL> for that package). Alternative
518             values can be specified from Perl code using the C<program_path> class
519             method from that package, but there are deliberately no options to
520             specify these paths from TT code.
521              
522              
523             =head1 AUTHOR
524              
525             Andrew Ford E<lt>a.ford@ford-mason.co.ukE<gt> (current maintainer)
526              
527             Andy Wardley E<lt>abw@wardley.orgE<gt> L<http://wardley.org/>
528              
529             The original Latex plugin on which this is based was written by Craig
530             Barratt with additions for Win32 by Richard Tietjen. The code has
531             subsequently been radically refactored by Andrew Ford.
532              
533             =head1 LICENSE AND COPYRIGHT
534              
535             Copyright (C) 1996-2006 Andy Wardley. All Rights Reserved.
536             Copyright (C) 2006-2014 Andrew Ford. All Rights Reserved.
537             Copyright (C) 2014-2016 Chris Travers. All Rights Reserved.
538              
539             This module is free software; you can redistribute it and/or
540             modify it under the same terms as Perl itself.
541              
542             This software is distributed in the hope that it will be useful, but
543             WITHOUT ANY WARRANTY; without even the implied warranty of
544             MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
545              
546             =head1 SEE ALSO
547              
548             L<Template>, L<LaTeX::Driver>, L<LaTeX::Table>, L<LaTeX::Encode>
549              
550              
551             L<latex2dvi(1)>, L<latex2pdf(1)> and L<latex2ps(1)> (part of the
552             C<LaTeX::Driver> distribution)
553              
554             =cut
555              
556              
557             # Local Variables:
558             # mode: perl
559             # perl-indent-level: 4
560             # indent-tabs-mode: nil
561             # End:
562             #
563             # vim: expandtab shiftwidth=4: