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