File Coverage

blib/lib/Text/MustacheTemplate/Evaluator.pm
Criterion Covered Total %
statement 55 55 100.0
branch 22 22 100.0
condition 12 12 100.0
subroutine 10 10 100.0
pod 3 3 100.0
total 102 102 100.0


line stmt bran cond sub pod time code
1             package Text::MustacheTemplate::Evaluator;
2 14     14   158086 use 5.022000;
  14         51  
3 14     14   75 use strict;
  14         34  
  14         454  
4 14     14   71 use warnings;
  14         26  
  14         891  
5              
6 14     14   103 use Exporter 5.57 'import';
  14         218  
  14         1030  
7              
8             our @EXPORT_OK = qw/retrieve_variable evaluate_section_variable evaluate_section/;
9              
10 14     14   115 use Scalar::Util qw/looks_like_number/;
  14         34  
  14         830  
11              
12 14     14   659 use Text::MustacheTemplate::Lexer ();
  14         193  
  14         3209  
13              
14             our $LAMBDA_RENDERER;
15              
16             sub retrieve_variable {
17 410     410 1 15541 my ($ctx, @keys) = @_;
18              
19             CTX_LOOP:
20 410         924 for my $root (map $ctx->[$_], reverse 0..$#{$ctx}) {
  410         2133  
21 669         1248 my $value = $root;
22 669         1594 for my $i (keys @keys) {
23 746         1465 my $key = $keys[$i];
24 746 100       2158 next CTX_LOOP if ref $value ne 'HASH';
25 660 100 100     4370 next CTX_LOOP if $i == 0 && !exists $value->{$key};
26              
27 459         912 my $is_last = $i == $#keys;
28 459         1078 $value = $value->{$key};
29 459 100 100     1613 $value = $value->() if !$is_last && ref $value eq 'CODE';
30             }
31 382 100       1009 next if ref $value eq 'HASH';
32              
33 379 100       1001 if (ref $value eq 'CODE') {
34 18         210 $value = $value->();
35 14 100   14   100 if (do { no warnings qw/once/; $Text::MustacheTemplate::LAMBDA_TEMPLATE_RENDERING }) {
  14         51  
  14         6197  
  18         53  
  18         66  
36 17         44 return $LAMBDA_RENDERER->($value);
37             }
38             }
39 362         15747 return $value;
40             }
41 31         806 return '';
42             }
43              
44             sub evaluate_section_variable {
45 274     274 1 13644 my ($ctx, @keys) = @_;
46              
47             CTX_LOOP:
48 274         606 for my $root (map $ctx->[$_], reverse 0..$#{$ctx}) {
  274         2577  
49 336         644 my $value = $root;
50 336         924 for my $i (keys @keys) {
51 375         936 my $key = $keys[$i];
52 375 100       1229 next CTX_LOOP if ref $value ne 'HASH';
53 366 100 100     1923 next CTX_LOOP if $i == 0 && !exists $value->{$key};
54              
55 298         627 my $is_last = $i == $#keys;
56 298         670 $value = $value->{$key};
57 298 100 100     1188 $value = $value->() if !$is_last && ref $value eq 'CODE';
58             }
59              
60 259         706 return evaluate_section($value);
61             }
62 15         322 return;
63             }
64              
65             sub evaluate_section {
66 277     277 1 287410 my $value = shift;
67 277 100       2972 return @$value if ref $value eq 'ARRAY';
68 209 100       2705 return $value ? $value : ();
69             }
70              
71             1;
72              
73             =head1 NAME
74              
75             Text::MustacheTemplate::Evaluator - [INTERNAL] Context evaluation for Mustache templates
76              
77             =head1 SYNOPSIS
78              
79             use Text::MustacheTemplate::Evaluator qw/
80             retrieve_variable
81             evaluate_section
82             evaluate_section_variable
83             /;
84            
85             my @context = ({ name => 'World', items => [1, 2, 3] });
86            
87             # Get a variable value
88             my $value = retrieve_variable(\@context, 'name');
89            
90             # Evaluate if a section should be rendered
91             my @section_ctx = evaluate_section_variable(\@context, 'items');
92            
93             # Evaluate a direct value
94             my @items_ctx = evaluate_section($context[-1]->{items});
95              
96             =head1 DESCRIPTION
97              
98             Text::MustacheTemplate::Evaluator provides functions for evaluating Mustache template contexts
99             and retrieving values from nested context structures according to the Mustache specification.
100              
101             This is internal interface for Text::MustacheTemplate.
102             The APIs may change without notice.
103              
104             =head1 FUNCTIONS
105              
106             =over 4
107              
108             =item retrieve_variable(\@context, @path)
109              
110             Retrieves a value from the context stack by following the given path.
111             Returns the value if found, otherwise undef.
112              
113             Parameters:
114              
115             =over 8
116              
117             =item \@context - An array reference to the context stack
118              
119             =item @path - The dot-separated path components to the variable
120              
121             =back
122              
123             =item evaluate_section($value)
124              
125             Evaluates whether a section should be rendered and how it should be processed.
126             Returns an array of context objects for iteration.
127              
128             Parameters:
129              
130             =over 8
131              
132             =item $value - The value to evaluate
133              
134             =back
135              
136             For different value types:
137              
138             =over 8
139              
140             =item * Undefined or falsy values: Returns an empty array (section not rendered)
141              
142             =item * Array references: Returns the array elements for iteration
143              
144             =item * Hash references: Returns the hash reference itself for context
145              
146             =item * Code references: Returns the code reference for lambda processing
147              
148             =item * True scalar values: Returns the value as a single-element array
149              
150             =back
151              
152             =item evaluate_section_variable(\@context, @path)
153              
154             Retrieves a variable by path and evaluates it as a section.
155             Combines retrieve_variable and evaluate_section.
156              
157             Parameters:
158              
159             =over 8
160              
161             =item \@context - An array reference to the context stack
162              
163             =item @path - The dot-separated path components to the variable
164              
165             =back
166              
167             =back
168              
169             =head1 LAMBDA SUPPORT
170              
171             When a section value is a code reference (lambda), the Evaluator provides special handling:
172              
173             =over 4
174              
175             =item * The lambda receives the raw section content as its first argument
176              
177             =item * If $LAMBDA_RENDERER is defined, the lambda's result will be processed by this renderer
178              
179             =item * This enables dynamic template generation within templates
180              
181             =back
182              
183             =head1 LICENSE
184              
185             =cut