File Coverage

blib/lib/EJS/Template.pm
Criterion Covered Total %
statement 65 71 91.5
branch 17 30 56.6
condition 6 12 50.0
subroutine 16 16 100.0
pod 11 11 100.0
total 115 140 82.1


line stmt bran cond sub pod time code
1 8     8   27487 use 5.006;
  8         16  
2 8     8   27 use strict;
  8         10  
  8         151  
3 8     8   25 use warnings;
  8         16  
  8         235  
4              
5             =head1 NAME
6              
7             EJS::Template - EJS (Embedded JavaScript) template engine
8              
9             =cut
10              
11             package EJS::Template;
12              
13 8     8   2535 use EJS::Template::Executor;
  8         13  
  8         209  
14 8     8   2608 use EJS::Template::Parser;
  8         11  
  8         4654  
15              
16             =head1 VERSION
17              
18             Version 0.08
19              
20             =cut
21              
22             our $VERSION = '0.08';
23              
24             our @CONFIG_KEYS = qw(engine escape);
25             our $context;
26              
27             =head1 SYNOPSIS
28              
29             EJS is an "Embedded JavaScript" template engine.
30              
31             Anything inside the tag C<< <%...%> >> is executed as JavaScript code,
32             and anything inside the tag C<< <%=...%> >> is replaced by the evaluated value.
33              
34             # Perl
35             use EJS::Template;
36             EJS::Template->process('source.ejs', {name => 'World'});
37            
38             # EJS ('source.ejs')
39             <% for (var i = 0; i < 3; i++) { %>
40             Hello, <%= name %>!
41             <% } %>
42            
43             # Output (STDOUT)
44             Hello, World!
45             Hello, World!
46             Hello, World!
47              
48             In the above example, the C method takes an input file path as the
49             first argument and variables passed to JavaScript as the second argument.
50             The output is printed out to STDOUT by default.
51              
52             The C method can optionally take both input and output targets (file
53             paths, IO handles, or scalar refs to strings).
54              
55             EJS::Template->process('source.ejs', {name => 'World'}, 'destination.ejs');
56              
57             A simpler way to apply a template without an external file is to use C
58             method, which looks something like this:
59              
60             my $text = EJS::Template->apply('Hello, <%= name %>!', {name => 'World'});
61              
62             Within C<< <%...%> >>, it is also possible to call C function:
63              
64             # EJS
65             <%
66             for (var i = 0; i < 3; i++) {
67             print("i = ", i, "\n");
68             }
69             %>
70            
71             # Output
72             i = 0
73             i = 1
74             i = 2
75              
76             C supports auto-escaping that minimizes the risk of forgetting
77             HTML-escape every individual variable. (See L for more details.)
78              
79             # Perl
80             my $ejs = EJS::Template->new(escape => 'html'); # Set default escape type
81            
82             $ejs->process('sample.ejs', {
83             address => '"Foo Bar" ', # to be escaped
84             message => '

Hello, World!

', # not to be escaped

85             });
86            
87             # EJS ('<%=' escapes the value, while '<%:raw=' does *not*)
88            

<%= address %>

89            
90             <%:raw= message %>
91            
92            
93             # Output
94            

"Foo Bar" <foo.bar@example.com>

95            
96            

Hello, World!

97            
98              
99             Extra white spaces around C<< <% >> and C<< %> >> are appropriately trimmed
100             so that the result output will look fairly clean intuitively.
101              
102            
103             <% for (...) { %>
104            
  • ...
  • 105             <% } %>
    106            
    107              
    108             In the above example, the C-loop line has the indent whitespace and the line break at the end.
    109             In order to make the result HTML look clean, these whitespaces are automatically removed.
    110             See L for more details.
    111              
    112              
    113             =head1 DESCRIPTION
    114              
    115             EJS is a template with JavaScript code embedded, and this module provides a
    116             template engine to generate output from EJS templates.
    117              
    118             It can be used as a general-purpose template engine to generate text documents,
    119             configurations, source code, etc.
    120             For web applications, EJS can be used as a template of HTML.
    121              
    122             EJS is suitable when template authors should not embed potentially dangerous
    123             code such as file system manipulations, command executions, and database
    124             connections, while at the same time, they can still utilize JavaScript as a
    125             well-established programming language.
    126              
    127             Especially for web applications, there are several different approaches to
    128             implement similar EJS functionality, such as parsing EJS and/or executing
    129             JavaScript on the server side or the browser side.
    130             This module implements both parsing and executing on the server side from that
    131             perspective.
    132              
    133             =head1 METHODS
    134              
    135             =head2 new
    136              
    137             Creates an C object with configuration name/value pairs.
    138              
    139             Usage:
    140              
    141             my $ejs = EJS::Template->new( [NAME => VALUE, ...] );
    142              
    143             Available configurations are as below:
    144              
    145             =over 4
    146              
    147             =item * escape => ESCAPE_TYPE
    148              
    149             Sets the default escape type for all the interpolation tags (C<< <%=...%> >>).
    150              
    151             Possible values are: C<'raw'> (default), C<'html'>, C<'xml'>, C<'uri'>, and
    152             C<'quote'>. See L for more details.
    153              
    154             =item * engine => ENGINE_CLASS
    155              
    156             Sets the JavaScript engine class.
    157             See L for more details.
    158              
    159             =back
    160              
    161             =cut
    162              
    163             sub new {
    164 74     74 1 854 my ($class, %config) = @_;
    165 74         133 my $self = {map {$_ => $config{$_}} @CONFIG_KEYS, qw(parser executor)};
      296         524  
    166 74         203 return bless $self, $class;
    167             }
    168              
    169             =head2 process
    170              
    171             Usage:
    172              
    173             # Simple
    174             EJS::Template->process([INPUT [, VARIABLES [, OUTPUT ] ] ]);
    175            
    176             # Custom
    177             my $ejs = EJS::Template->new(...);
    178             $ejs->process([INPUT [, VARIABLES [, OUTPUT ] ] ]);
    179              
    180             INPUT is the EJS source (default: STDIN).
    181             It can be either a string (as a file path), a string ref (as a source text), or
    182             an open file handle.
    183              
    184             VARIABLES is a hash ref that maps variable names to values, which are made
    185             available in the JavaScript code (default: an empty hash).
    186             The values of VARIABLES can be a nested structure of hashes, arrays, strings,
    187             numbers, and/or subroutine refs.
    188             A function (subroutine) named C is automatically defined, unless
    189             overwritten in VARIABLES.
    190              
    191             OUTPUT is where the final result is written out (default: STDOUT).
    192             It can be either a string (as a file path), a string ref (as a source text), or
    193             an open file handle.
    194              
    195             Examples:
    196              
    197             # Reads the file 'source.ejs' and prints the result to STDOUT
    198             EJS::Template->process('source.ejs', {name => 'World'});
    199              
    200             # Reads STDIN as the EJS source and writes the result to the file 'output.txt'
    201             EJS::Template->process(\*STDIN, {name => 'World'}, 'output.txt');
    202              
    203             # Parses the EJS source text and stores the result to the variable $out
    204             my $out;
    205             EJS::Template->process(\'Hello <%=name%>', {name => 'World'}, \$out);
    206              
    207             =cut
    208              
    209             sub process {
    210 63     63 1 1303 my ($self, $input, $variables, $output) = @_;
    211 63 100       167 local $context = ref $self ? $self : $self->new();
    212            
    213 63         67 eval {
    214 63         58 my $parsed;
    215 63         154 $context->parse($input, \$parsed);
    216 63         140 $context->execute(\$parsed, $variables, $output);
    217             };
    218            
    219 63 50       134 die $@ if $@;
    220 63         220 return 1;
    221             }
    222              
    223             =head2 apply
    224              
    225             Usage:
    226              
    227             EJS::Template->apply(INPUT_TEXT [, VARIABLES])
    228              
    229             Example:
    230              
    231             my $text = EJS::Template->apply('Hello <%= name %>', {name => 'World'});
    232             print $text;
    233              
    234             This method serves as a syntax sugar for the C method, focused on
    235             text-to-text conversion.
    236              
    237             =cut
    238              
    239             sub apply {
    240 1     1 1 72297 my ($self, $input, $variables) = @_;
    241 1 50       7 local $context = ref $self ? $self : $self->new();
    242 1         1 my $output;
    243            
    244 1         1 eval {
    245 1         3 $context->process(\$input, $variables, \$output);
    246             };
    247            
    248 1 50       2 die $@ if $@;
    249 1         12 return $output;
    250             }
    251              
    252             =head2 parse
    253              
    254             Usage:
    255              
    256             EJS::Template->parse([INPUT [, OUTPUT ] ]);
    257              
    258             INPUT is the EJS source, and OUTPUT is a JavaScript code,
    259             which can then be executed to generate the final output.
    260             (See C method.)
    261              
    262             The parsed code can be stored in a file as an intermediate code,
    263             and can be executed at a later time.
    264              
    265             The semantics of INPUT and OUTPUT types are similar to C.
    266              
    267             =cut
    268              
    269             sub parse {
    270 83     83 1 107 my ($self, $input, $parsed_output) = @_;
    271 83 100       173 local $context = ref $self ? $self : $self->new();
    272            
    273 83         76 eval {
    274 83         182 $context->parser->parse($input, $parsed_output);
    275             };
    276            
    277 83 50       537 die $@ if $@;
    278 83         168 return 1;
    279             }
    280              
    281             =head2 execute
    282              
    283             Usage:
    284              
    285             EJS::Template->execute([INPUT [, VARIABLES [, OUTPUT ] ] ]);
    286              
    287             INPUT is a JavaScript code generated by C method,
    288             and OUTPUT is the final result.
    289              
    290             The semantics of INPUT and OUTPUT types are similar to C.
    291              
    292             =cut
    293              
    294             sub execute {
    295 63     63 1 89 my ($self, $parsed_input, $variables, $output) = @_;
    296 63 50       127 local $context = ref $self ? $self : $self->new();
    297            
    298 63         61 eval {
    299 63         126 $context->executor->execute($parsed_input, $variables, $output);
    300             };
    301            
    302 63 50       143 die $@ if $@;
    303 63         145 return 1;
    304             }
    305              
    306              
    307             =head2 context
    308              
    309             Usage:
    310              
    311             EJS::Template->context;
    312              
    313             Retrieves the C object under the current execution context.
    314              
    315             It is useful when retrieving the object from within the JavaScript execution.
    316              
    317             my $template = EJS::Template->new();
    318              
    319             $template->process(\*STDIN, {
    320             callFromJS => sub {
    321             my $context = EJS::Template->context;
    322             # In this case, $context is the same as $template.
    323             ...
    324             }
    325             });
    326              
    327             The above example is trivial because the current context can also be easily referenced
    328             from the outer C<$template> variable via the closure.
    329             However, even if this subroutine is defined in some other places, the current template
    330             object can always be retrieved via this call.
    331              
    332             =cut
    333              
    334             sub context {
    335 8     8 1 17438 my $class = shift;
    336 8   33     37 $class = ref($class) || $class;
    337 8   33     36 return $context ||= $class->new;
    338             }
    339              
    340             =head2 parser
    341              
    342             Gets or sets an C object.
    343              
    344             # Getter
    345             $template->parser;
    346              
    347             # Setter
    348             $template->parser(EJS::Template::Parser->new($template));
    349              
    350             =cut
    351              
    352             sub parser {
    353 83     83 1 71 my $self = shift;
    354 83 50       167 $self = $self->context unless ref $self;
    355              
    356 83 50       151 if (@_) {
    357 0         0 my $old = $self->{parser};
    358 0         0 $self->{parser} = shift;
    359 0         0 return $old;
    360             } else {
    361 83   66     522 return $self->{parser} ||= EJS::Template::Parser->new($self);
    362             }
    363             }
    364              
    365             =head2 executor
    366              
    367             Gets or sets an C object.
    368              
    369             # Getter
    370             $template->executor;
    371              
    372             # Setter
    373             $template->executor(EJS::Template::Executor->new($template));
    374              
    375             =cut
    376              
    377             sub executor {
    378 74     74 1 74 my $self = shift;
    379 74 50       146 $self = $self->context unless ref $self;
    380              
    381 74 50       150 if (@_) {
    382 0         0 my $old = $self->{executor};
    383 0         0 $self->{executor} = shift;
    384 0         0 return $old;
    385             } else {
    386 74   66     478 return $self->{executor} ||= EJS::Template::Executor->new($self);
    387             }
    388             }
    389              
    390             =head2 bind
    391              
    392             Binds name-value pairs to the associated JavaScript engine.
    393              
    394             $template->bind({name1 => $value1});
    395             $template->apply('<% print("name1 = ", name1) %>');
    396              
    397             =cut
    398              
    399             sub bind {
    400 5     5 1 4555 my $self = shift;
    401 5 50       15 $self = $self->context unless ref $self;
    402 5         12 return $self->executor->adapter->bind(@_);
    403             }
    404              
    405             =head2 eval
    406              
    407             Invokes the C function of the associated JavaScript engine.
    408              
    409             $template->eval('new Date().toString()');
    410              
    411             =cut
    412              
    413             sub eval {
    414 1     1 1 6 my $self = shift;
    415 1 50       4 $self = $self->context unless ref $self;
    416 1         3 return $self->executor->adapter->eval(@_);
    417             }
    418              
    419             =head2 print
    420              
    421             Prints text to the current output target.
    422              
    423             $template->print('Hello, World!');
    424              
    425             This method can only be called under the execution context, usually from
    426             within a subroutine invoked by JavaScript.
    427              
    428             $template->process('example.ejs', {
    429             callFromJS => sub {
    430             $template->print('Hello, World!');
    431             }
    432             });
    433              
    434             =cut
    435              
    436             sub print {
    437 5     5 1 3970 my $self = shift;
    438 5 50       15 $self = $self->context unless ref $self;
    439 5         9 return $self->executor->print(@_);
    440             }
    441              
    442              
    443             =head1 DETAILS
    444              
    445             =head2 Auto-escaping
    446              
    447             C supports auto-escaping if it is configured via the C
    448             method.
    449              
    450             EJS::Template->new(escape => 'html')->process(...);
    451              
    452             If the C is set to 'html', all the texts inside C<< <%=...%> >> are
    453             HTML-escaped automatically.
    454              
    455             # Input
    456             <% var text = "x < y < z"; %>
    457             <%= text %>
    458            
    459             # Output
    460             x < y < z
    461              
    462             In case a raw HTML needs to be embedded without escaping, it can be annotated like this:
    463              
    464             <%:raw= text %>
    465              
    466             In addition, the following escape types are available in a similar manner
    467             (both for the C<< escape => >> config or in each individual tag C<< <%=...%> >>):
    468              
    469             =over 4
    470              
    471             =item * html
    472              
    473             <%:html= plainText %>
    474              
    475             =item * xml
    476              
    477             <%:xml= plainText %>
    478              
    479             =item * uri
    480              
    481             Link
    482              
    483             =item * quote
    484              
    485            
    488              
    489             =item * raw
    490              
    491            
    <%:raw= htmlText %>
    492              
    493             =back
    494              
    495             =head2 Trimming white spaces
    496              
    497             C trims appropriate white spaces around C<< <%...%> >>
    498             (but not around C<< <%=...%> >>).
    499              
    500             It helps the template author generate a fairly well-formatted output:
    501              
    502             EJS:
    503              
    504            
    505             <% for (var i = 1; i <= 5; i++) { %>
    506            
  • 507             <% if (i % 2 == 1) { %>
    508             <%=i%> x <%=i%> = <%=i * i%>
    509             <% } %>
    510            
    511             <% } %>
    512            
    513              
    514             Output:
    515              
    516            
    517            
  • 518             1 x 1 = 1
    519            
    520            
  • 521             3 x 3 = 9
    522            
    523            
  • 524             5 x 5 = 25
    525            
    526            
    527              
    528             Note: If no white spaces were trimmed, the result output would look much more ugly,
    529             because of extra indent spaces and line breaks around C<< <% for (...) %> >>,
    530             C<< <% if (...) %> >>, etc.
    531              
    532             The trimming occurs only when C<< <% >> is at the beginning of a line with any indent
    533             spaces, and its corresponding C<< %> >> is at the end of the same or another line
    534             with any trailing spaces.
    535              
    536             When the above trimming condition is met,
    537             any white spaces to the left of C<< <% >> (not including any line breaks) and
    538             any white spaces to the right of C<< %> >> (including the line break) are trimmed.
    539              
    540             =head2 Data conversion between Perl and EJS
    541              
    542             In the current version, the data conversion is limited to basic types
    543             (strings, numbers, hashes, arrays, and functions), although arbitrarily nested
    544             structures are allowed.
    545              
    546             EJS::Template->process('sample.ejs', {
    547             name => 'World',
    548             hash => {foo => 123, bar => 456, baz => [7, 8, 9]},
    549             array => ['a'..'z'],
    550             square => sub {
    551             my $value = shift;
    552             return $value * $value;
    553             }
    554             });
    555              
    556             If a blessed reference in Perl is passed to EJS, it is converted into a basic type.
    557              
    558             If a Perl subroutine is invoked from inside EJS, the types of the arguments depend
    559             on the JavaScript engine that is in use internally (See L).
    560              
    561             # Perl
    562             sub printRefs {
    563             print(ref($_) || '(scalar)', "\n") foreach @_;
    564             }
    565            
    566             EJS::Template->process(\< \&printRefs});
    567             <%
    568             printRefs(
    569             'str',
    570             123,
    571             [4, 5, 6],
    572             {x: 7, y: 8},
    573             function () {return 90}
    574             );
    575             %>
    576             END
    577            
    578             # Output with JavaScript::V8
    579             (scalar)
    580             (scalar)
    581             ARRAY
    582             HASH
    583             CODE
    584            
    585             # Output with JE
    586             JE::String
    587             JE::Number
    588             JE::Object::Array
    589             JE::Object
    590             JE::Object::Function
    591              
    592             For portability, it is recommended to keep data types as simple as possible
    593             when data is passed between Perl and EJS.
    594              
    595             =head2 JavaScript engines
    596              
    597             C automatically determines the available JavaScript engine from
    598             the below:
    599              
    600             =over 4
    601              
    602             =item * V8 (same engine as Google Chrome):
    603              
    604             L (default for C)
    605              
    606             =item * SpiderMonkey (same engine as Mozilla Firefox):
    607              
    608             L
    609              
    610             L
    611              
    612             =item * Pure Perl implementation
    613              
    614             L
    615              
    616             =back
    617              
    618             It is also possible to specify a particular engine:
    619              
    620             EJS::Template->new(engine => 'JE')->process(...);
    621             EJS::Template->new(engine => 'JavaScript::SpiderMonkey')->process(...);
    622              
    623             =head2 Including another EJS file
    624              
    625             Although this module does not provide the C function as a built-in,
    626             it can be implemented as below, depending on the use case.
    627              
    628             # Perl
    629             my $template = EJS::Template->new({escape => 'html'});
    630             $template->process('index.html.ejs', {
    631             include => sub {
    632             my ($path) = @_;
    633             # TODO: Validate $path to avoid reading arbitrary files
    634             my $context = EJS::Template->context;
    635             $context->process($path);
    636             }
    637             });
    638              
    639             # EJS (index.html.ejs)
    640             <%
    641             include('header.html.ejs');
    642             include('content.html.ejs');
    643             include('footer.html.ejs');
    644             %>
    645              
    646             =head2 Unicode/UTF-8
    647              
    648             Some JavaScript engines correctly translate Unicode strings in Perl (utf8 flag turned on)
    649             into Unicode strings in JavaScript, and vice versa.
    650              
    651             # Perl to JavaScript
    652             use utf8;
    653             my $input = "{Unicode string}";
    654             EJS::Template->process(\'<%=str%>', {str => $input});
    655              
    656             # JavaScript to Perl
    657             my $output;
    658             EJS::Template->process(\'<%func("{Unicode string}")%>', {
    659             func => sub {$output = shift}
    660             });
    661              
    662             Currently, C and C work as expected, but SpiderMonkey-based engines
    663             seem to have issues with Unicode as below.
    664              
    665             If Unicode strings in Perl are passed to JavaScript, then the strings are unexpectedly
    666             encoded as UTF-8, where each character in JavaScript strings corresponds to each byte
    667             of UTF-8 characters.
    668              
    669             If Unicode strings in JavaScript are passed to Perl, then the strings may
    670             become corrupted.
    671              
    672              
    673             =head1 AUTHOR
    674              
    675             Mahiro Ando, C<< >>
    676              
    677             =head1 BUGS
    678              
    679             Please report any bugs or feature requests to C, or through
    680             the web interface at L. I will be notified, and then you'll
    681             automatically be notified of progress on your bug as I make changes.
    682              
    683             =head1 SUPPORT
    684              
    685             You can find documentation for this module with the perldoc command.
    686              
    687             perldoc EJS::Template
    688              
    689             You can also look for information at:
    690              
    691             =over 4
    692              
    693             =item * GitHub repository (report bugs here)
    694              
    695             L
    696              
    697             =item * RT: CPAN's request tracker (report bugs here, alternatively)
    698              
    699             L
    700              
    701             =item * AnnoCPAN: Annotated CPAN documentation
    702              
    703             L
    704              
    705             =item * CPAN Ratings
    706              
    707             L
    708              
    709             =item * Search CPAN
    710              
    711             L
    712              
    713             =back
    714              
    715             =head1 ACKNOWLEDGEMENTS
    716              
    717             Many thanks to authors of JavaScript engines for making them available,
    718             and to authors of those in the SEE ALSO section for giving me
    719             ideas and inspirations.
    720              
    721             =head1 SEE ALSO
    722              
    723             =over 4
    724              
    725             =item * Template Toolkit (a.k.a. TT)
    726              
    727             L
    728              
    729             =item * JavaScript Template engine based on TT2
    730              
    731             L
    732              
    733             =item * Browser-side EJS
    734              
    735             L
    736              
    737             L
    738              
    739             =item * EJS for Ruby:
    740              
    741             L
    742              
    743             =back
    744              
    745             =head1 LICENSE AND COPYRIGHT
    746              
    747             Copyright 2012 Mahiro Ando.
    748              
    749             This program is free software; you can redistribute it and/or modify it
    750             under the terms of either: the GNU General Public License as published
    751             by the Free Software Foundation; or the Artistic License.
    752              
    753             See http://dev.perl.org/licenses/ for more information.
    754              
    755             =cut
    756              
    757             1; # End of EJS::Template