File Coverage

blib/lib/Text/Template/Inline.pm
Criterion Covered Total %
statement 53 53 100.0
branch 19 20 95.0
condition 6 6 100.0
subroutine 10 10 100.0
pod 1 1 100.0
total 89 90 98.8


line stmt bran cond sub pod time code
1             package Text::Template::Inline;
2 6     6   142655 use strict;
  6         12  
  6         201  
3 6     6   32 use warnings;
  6         11  
  6         167  
4 6     6   30 use base 'Exporter';
  6         25  
  6         609  
5             our @EXPORT = qw/ render /;
6              
7 6     6   29 use Carp qw/ croak /;
  6         9  
  6         496  
8 6     6   30 use Scalar::Util qw/ blessed reftype /;
  6         9  
  6         994  
9              
10             our $VERSION = '0.13';
11              
12             #
13             # The import function accepts an alternate name for the "render" function,
14             # then aliases and exports that name instead of the original.
15             #
16             sub import {
17 7     7   44 my ($package, $func_name) = @_;
18 7         19 local @EXPORT = @EXPORT;
19 7 100       29 if ($func_name) {
20             # export the provided name instead of "render"
21 2         11 @EXPORT = ($func_name);
22 6     6   31 no strict 'refs';
  6         10  
  6         2031  
23 2         3 *{$func_name} = *render;
  2         9  
24             }
25 7         13970 $package->export_to_level(1,@_);
26             }
27              
28             #
29             # This function is the only external module interface.
30             # If you don't like the name, just import a better one!
31             #
32             sub render ($$) {
33 46     46 1 3847 my ($data, $template) = @_;
34 46 50       113 return $template unless $template;
35              
36             # Trim leading whitespace, preserving relative indent.
37             # There's no way to know what your tabstops are, so we have to
38             # assume that you indent consistently w/ regards to tabs/spaces.
39 46         49 my $indent;
40 46         197 while ($template =~ m/^([\t ]+)/mg) {
41 9         14 my $lead = length $1;
42 9 100 100     50 $indent = (defined $indent && $lead > $indent) ? $indent : $lead;
43             }
44 46 100       146 $template =~ s/^[\t ]{$indent}//mg if defined $indent;
45 46         83 $template =~ s/^\n//; # remove leading newline
46              
47             # perform the data substitutions
48 46         219 $template =~ s/(\{(\w[.\w]*)\})/_traverse_ref_with_path($data,$2,$1)/ge;
  91         196  
49              
50 41         243 return $template;
51             }
52              
53             #
54             # This function dissects a period-delimited path of keys and follows them,
55             # traversing $theref. If the appropriate field exists at each level the final
56             # value is returned. If any field is not found, $default is returned.
57             #
58             sub _traverse_ref_with_path {
59 91     91   239 my ($theref, $path, $default) = @_;
60 91         239 my @keys = split /\./, $path;
61 91         119 my $ref = $theref;
62 91         145 for my $key (@keys) {
63 6     6   29 no warnings 'uninitialized'; # for comparisons involving a non-ref $ref
  6         16  
  6         1146  
64 137 100       618 if (blessed $ref) {
    100          
    100          
65 40 100       182 return $default unless $ref->can($key);
66 37         91 $ref = $ref->$key();
67             }
68             elsif (reftype $ref eq 'HASH') {
69 61 100       145 return $default unless exists $ref->{$key};
70 58         119 $ref = $ref->{$key};
71             }
72             elsif (reftype $ref eq 'ARRAY') {
73 31 100 100     205 return $default unless $key =~ /^\d+$/ and exists $ref->[$key];
74 27         67 $ref = $ref->[$key];
75             }
76             else {
77 5         11 local $Carp::CarpLevel = 2;
78 5         1372 croak "unable to use scalar '$theref' as template data";
79             }
80             }
81 76         377 return $ref;
82             }
83              
84             1;
85             __END__