8

Looking for template engine like HTML::Mason (or Mason), so what "compiles" source components into perl code, but instead of perl-code will "compile" components into JavaScript code and after run/execute them with Javascript::V8 perl module.

Motivation: Looking for solution for safe template language, what can edit users without compromising the server security. JavaScript is full featured language so using it is probably better/faster than some "mini languages" like TT or similar. The best for me would be an extension (rewrite) of Mason for compiling into Joose/JavaScript instead of Moose/Perl. ;)

And yes, want do this from perl with Javascript::V8 because this way is possible having all perl's power available via Javascript::V8 $context->bind_function in very safe way.

Questions:

  • Anyone know something like? (found nothing in CPAN)...

EDIT: in Mason you can write for example

% #perl version
% my(@list) = qw(Jane John Doe);
<ul> 
% foreach my $item (@list) { 
  <li><% uc($item) %></li> 
% } 
</ul>

would be nice to have possibility write the above in JS, like:

% //javascript version
% var list = ["Jane", "John", "Doe"];
<ul> 
% for(var i in list) {
  <li><% perl_uc($list[i]) %></li>
  <!-- the "perl_uc" is the real perl uc() what is binded
       with Javascript::V8::bind_function(perl_uc => sub { return uc(@_) }
  -->
% } 
</ul>

The above source should be "compiled" into JavaScript (Joose), and executed with Javascript::V8. (like in Mason - the source is compiled into perl/Moose object and executed with perl)...

As you can see, the for(var i in list) is written in pure JS, and not in "mini-language"…

cytinus
  • 4,664
  • 8
  • 30
  • 44
kobame
  • 5,686
  • 2
  • 28
  • 57
  • 2
    You said "Javascript is full featured language so using it is probably better/faster than some 'mini languages'". You really think that a mini language like TT (which is a subset of Perl and is compiled down to Perl, which means compiled templates are just subroutines) is going to be slower than transforming your template into Javascript, invoking another completely different interpreter, sending data to that interpreter, running it and then collecting data back out of that interpreter? That sounds slow as molasses. While I think this is a neat project, I don't think it's all that practical. – mpeters Jul 11 '11 at 14:49
  • 1
    Err, why not allow it with TT? I think you may be under some misimpression. TT is designed for MVC separation, not like Embperl or Mason or the like. – ysth Jul 12 '11 at 03:05
  • so long as you don't have EVAL_PERL enabled, what possible safety problem do you see? I am bewildered. – ysth Jul 12 '11 at 19:11

2 Answers2

9

Revisited and edited after years :)

Here is the EJS::Template. It does exactly for what you asked - compiles the templates into JS and using V8 (or even JE) engines for evaluate. Unfortunately, has no Javascript::Duktape engine support (yet).

Also, here is a snipet how to use the Jemplate (server-side) from the great @ysth's answer with the Duktape engine.

use strict;
use warnings;

use Jemplate;
use JavaScript::Duktape;

# can omit these steps - see bellow 
# Get the lite runtime js-source without the unnecessary AJAX  (we are server side)
my $jemp_runtime = Jemplate::runtime_source_code('lite');

# The Template::Toolkit template
my $template = q{
[%- FOREACH pope IN perlmonks -%]
pope: [% pope.name %] = [% pope.experience %]
[% END -%]
};

# compile the Template source using Jemplate and name it
my $jemp_template = Jemplate->compile_template_content($template, 'monkstemplate');

# the data
my $data = {
    'perlmonks' => [
        { 'name' => 'vroom',    'experience' => '1007479', },
        { 'name' => 'BrowserUk','experience' => '167247', },
        { 'name' => 'Corion',   'experience' => '133975', },
        { 'name' => 'ikegami',  'experience' => '128977', }
    ]
};

# init
my $js = JavaScript::Duktape->new();
$js->set( 'write' => sub { print $_[0]; } );
$js->eval($jemp_runtime);   # eval the runtime code
$js->eval($jemp_template);  # the Template code compiled into JS
$js->set("monkdata", $data);# bind the data

# finally eval the template processing code
$js->eval(q!
    write(
        Jemplate.process('monkstemplate', monkdata)
    );
!);

produces

pope: vroom = 1007479
pope: BrowserUk = 167247
pope: Corion = 133975
pope: ikegami = 128977 

You can omit all Jemplate calls, by compiling the templates beforehand using the jemplate command, like:

jemplate --runtime=lite --compile /path/to/templates > jemplate_source.js

And just load the jemplate_source.js and eval it in the JS engine.

Just for note: On my noteboook, using the original TemplateToolkit i got 10k/sec. The above Jemplate/Duktape only 5k/sec.

The my original answer:

Here is Shotenjin what is derived from a Tenjin template system. (the perl Tenjin is here.

Shotenjin is joose based, so with some plus work will be possible use Shotenjin from a perl with Javascript::V8. But it is still not exacly for what youre looking.

EDIT: For what you're looking is already done - unfortunately, for the RUBY. https://github.com/elado/isotope

EDIT2: Just discovered: here is Template::JavaScript what is TT compiled into JS and executed with v8 server side...

jm666
  • 52,991
  • 14
  • 92
  • 160
4

Jemplate

(That said, I disagree entirely with your premise of "Javascript is full featured language so using it is probably better/faster than some "mini languages" like TT or similar" - IMO there is absolutely no reason to do what you are asking.)

ysth
  • 88,068
  • 5
  • 112
  • 203
  • @kobame: then I don't get what you want; you say you want to use javascript directly, but also that you want to compile a template to javascript? – ysth Jul 10 '11 at 19:03
  • Just checked Jemplate - unfortunately (if I understand it ok) it for broswer side execution, not server side. I'm looking for the server side execution - like with Javascript::V8. – kobame Jul 12 '11 at 18:59
  • I don't think that cleared things up; Jemplate doesn't care whether you execute the resulting javascript on the client or server (though the client is presumably a more common use) – ysth Jul 13 '11 at 07:48