File Coverage

blib/lib/Inline/TT.pm
Criterion Covered Total %
statement 59 81 72.8
branch 6 12 50.0
condition n/a
subroutine 13 17 76.4
pod 1 6 16.6
total 79 116 68.1


line stmt bran cond sub pod time code
1             package Inline::TT;
2 5     5   126985 use strict; use warnings;
  5     5   14  
  5         173  
  5         24  
  5         8  
  5         140  
3              
4 5     5   23 use Carp;
  5         15  
  5         346  
5              
6 5     5   6992 use Storable qw( store retrieve );
  5         17882  
  5         396  
7             # Storable is used to store/retrieve the compiled template on disk
8              
9 5     5   5187 use Template::Parser;
  5         203090  
  5         175  
10 5     5   5545 use Template::Document;
  5         8403  
  5         142  
11 5     5   7451 use Template::Context;
  5         50535  
  5         218  
12 5     5   6543 use Template::Stash;
  5         83216  
  5         3035  
13              
14             our $TRIM_LEADING_SPACE = 'TRIM_LEADING_SPACE';
15             our $TRIM_TRAILING_SPACE = 'TRIM_TRAILING_SPACE';
16              
17             our $VERSION = '0.07';
18             our @ISA = qw( Inline );
19             our %default_inline_tt_option_for = (
20             $TRIM_LEADING_SPACE => 1,
21             $TRIM_TRAILING_SPACE => 1,
22             );
23              
24             # To understand the methods here it helps to read the Inline API docs:
25             # http://search.cpan.org/~ingy/Inline-0.44/Inline-API.pod
26              
27             sub register {
28             return {
29 0     0 0 0 language => 'TT',
30             aliases => [ qw( tt template ) ],
31             type => 'interpreted',
32             suffix => 'tt2',
33             };
34             }
35              
36             # TRIM_LEADING_SPACES and TRIM_TRAILING_SPACES are valid options. They
37             # both default to 1. All other options are passed directly to TT.
38             sub validate {
39 4     4 0 115 my $o = shift;
40 4         13 my %option_for = @_;
41              
42 4         17 foreach my $option ( keys %default_inline_tt_option_for ) {
43 8 100       29 if ( defined $option_for{$option} ) {
44              
45 1         8 $o->{ILSM}{Inline_TT_options}{$option} = $option_for{$option};
46              
47 1         3 delete $option_for{$option};
48              
49             }
50             else {
51 7         44 $o->{ILSM}{Inline_TT_options}{$option}
52             = $default_inline_tt_option_for{$option};
53             }
54             }
55              
56 4         16 $o->{ILSM}{TT_options} = {};
57              
58 4         19 foreach my $option ( keys %option_for ) {
59 3         14 $o->{ILSM}{TT_options}{$option} = $option_for{$option};
60             }
61             }
62              
63             # To provide any useful information, we must rehydrate the stored object.
64             # This is not really a problem, since this method is not likely called in
65             # production.
66             #
67             # XXX This does not work for the first invocation. That's bad, since
68             # that's the most likely one to request info.
69             sub info {
70 0     0 1 0 my $o = shift;
71 0         0 my $obj = $o->{API}{location};
72 0         0 my $retval;
73              
74 0         0 eval {
75             # retrieve is exported from Storable
76 0         0 my $tt_code = retrieve( $obj );
77 0         0 my $document = Template::Document->new( $tt_code );
78 0         0 my $blocks = join( "\n ", sort keys %{$document->{_DEFBLOCKS}} );
  0         0  
79              
80 0         0 $retval = "The following tt2 blocks have been bound as subs:"
81             . "\n $blocks\n";
82             };
83              
84             # If the _Inline directory is not yet built, this error will occur.
85 0 0       0 if ( $@ ) {
86 0         0 $retval = "Rerun, without deleting _Inline, to see INFO.\n";
87             }
88              
89 0         0 return $retval;
90             }
91              
92 0     0 0 0 sub working_info { return "no useful info, sorry\n"; }
93              
94             # This build receives $code from the template object $o, parses it,
95             # makes a path for it and stores it. This handles all the BLOCKS at once.
96             # Inline will only call this if the md5sum of the input template does not
97             # match one that is available in the _Inline directory (or its moral
98             # equivalent). Otherwise, it will only call load below.
99             sub build {
100 0     0 0 0 my $o = shift;
101 0         0 my $code = $o->{API}{code};
102              
103 0         0 my $parser = Template::Parser->new( $o->{ILSM}{TT_options} );
104 0         0 my $content = $parser->parse( $code );
105              
106 0         0 my $path = "$o->{API}{install_lib}/auto/$o->{API}{modpname}";
107 0         0 my $obj = $o->{API}{location};
108              
109 0 0       0 $o->mkpath( $path ) unless -d $path;
110              
111 0         0 store( $content, $obj ); # from Storable
112             }
113              
114             # This routine rehydrates the parsed Template object which was originally
115             # generated by build. This happens each time the program runs. After the
116             # the parsed object it reconstituted, load turns it into a document.
117             # Each key in that document's _DEFBLOCKS list is made a sub in the caller's
118             # package. No, we really shouldn't be peeking inside to the _DEFBLOCKS
119             # level, but I couldn't find the relavent API.
120             sub load {
121 4     4 0 17 my $o = shift;
122 4         12 my $obj = $o->{API}{location};
123              
124 4         24 my $tt_code = retrieve( $obj ); # from Storable
125 4         1084 my $document = Template::Document->new( $tt_code );
126              
127 4         2933 foreach my $sub ( keys %{$document->{_DEFBLOCKS}} ) {
  4         41  
128              
129 5     5   63 no strict 'refs';
  5         11  
  5         1655  
130              
131 6         21 *{"$o->{API}{pkg}\::$sub"} = _make_block_sub( $sub, $document, $o );
  6         41  
132             }
133              
134 4 50       36 croak "Unable to load TT module $obj:\n$@" if $@;
135             }
136              
137             # _make_block_sub takes the name of a block and the document containing it
138             # and returns a closure for the block. The closure expects a hash of values
139             # for template interpolation. It always processes its block and only its
140             # block. A lot of trimming happens. Typically, no space is left for
141             # template directives. Further, no leading or trailing spaces survive.
142             sub _make_block_sub {
143 6     6   11 my $name = shift;
144 6         10 my $doc = shift;
145 6         11 my $o = shift;
146              
147             return sub {
148 6     6   2508 my $args = shift;
149              
150 6         55 my $stash = Template::Stash->new( $args );
151 6         202 my $context = Template::Context->new(
152             {
153             STASH => $stash,
154             TRIM => 1,
155             BLOCKS => $doc->{_DEFBLOCKS},
156             }
157             );
158              
159 6         144343 my $retval = $doc->{_DEFBLOCKS}{$name}( $context );
160              
161 6 100       22608 if ( $o->{ILSM}{Inline_TT_options}{$TRIM_LEADING_SPACE} ) {
162 5         77 $retval =~ s/^\s+//;
163             }
164 6 50       46 if ( $o->{ILSM}{Inline_TT_options}{$TRIM_TRAILING_SPACE} ) {
165 6         36 $retval =~ s/\s+$//;
166             }
167              
168 6         39 return $retval;
169             }
170 6         36 }
171              
172             1;
173             __END__