15

I have been using template toolkit for extending an existing domain specific language(verilog) for over 3 years now. While overall I am happy with it, the major irritant is that when there is a syntax/undef error the error message does not contain the correct line number information to debug the error.

e.g. I would get a message indicating "0 is not defined" since I would be using [%x.0%] and similar constructs at multiple locations in the file figuring out which line has the problem becomes difficult.

TT3 seems to be under development indefinitely

My question to the gurus is is there a better alternative to TT. My requirements are

  1. Support for complex data structures
  2. Good error reporting and debug capabilities.
  3. Stable and proven ( no alpha/beta level engines)
  4. Extensible (plugin's etc)
  5. Should not be restricted to a given language (html etc.)
  6. support for IF/Else, looping(foreach while), Loop indexing, etc.
  7. Preferably perl
  8. Support for data dumper or equivalent plugin from within the template is a plus
vijayvithal
  • 551
  • 1
  • 5
  • 13
  • 2
    Here is an old writeup. I don't think it is complete (doesn't include xslate for instance), but may still be helpful to you: https://perl.apache.org/docs/tutorials/tmpl/comparison/comparison.html – Craig Treptow Jan 09 '13 at 14:38
  • 2
    [Xslate](http://xslate.org/) – alex Jan 09 '13 at 16:34

5 Answers5

20

I can only recommend Text::Xslate here. It is better than TT in every way and beats out most of the competition as well. And lastly, it fits all your requirements. Literally. All of them.

It is even proven in practice, as it is used by one of the Top 100 websites worldwide and one of the Top 10 websites in Japan: Livedoor

Xslate in comparison to TT:

  • faster startup
  • faster processing
  • strict mode by default
  • much more advanced strict mode that catches inconsistencies beyond just "var is undef"
  • detailed errors that show the exact template position
  • automatic HTML entity escaping (XSS-safe)
  • actively maintained and not just left to languish
  • syntax is straight-forward and modern perl

Two things to note for your special case:

  1. As you're porting from TT, you might want to pass syntax => 'TTerse' to the constructor to get a syntax that's designed to be as close to TT as possible.
  2. When generating non-HTML, you want to pass type => 'text' to the constructor to disable html_escape interpolation.
Starfish
  • 1,083
  • 10
  • 23
Mithaldu
  • 2,393
  • 19
  • 39
  • 1
    I agree that xslate meets most of my specification. But since Template Alloy addressed my major problem (cryptic error messages) and has syntax similar to TT (less migration headache) I am going with it for my project – vijayvithal Jan 28 '13 at 15:26
  • 1
    You did see the note i wrote about enabling TT syntax in Xslate? There is not a single thing T::A is superior to Xslate in, and a number of things where it's actively inferior. You opted for the worse choice here, for what can only be described as "no reason whatsoever". – Mithaldu Jan 28 '13 at 15:29
  • 1
    I agree that you may be right. I will do an eval of Xslate on of these days. If as you say XSlate supports the complete TT Syntax the transition should be seamless. I will comeback and comment on this thread once I am done with the eval – vijayvithal Feb 27 '13 at 11:02
  • I did not expect an answer to this, so i have to say: Thank you. :) As a note, the TT syntax is not *completely* supported, but enough of it is supported that transitions should be quite trivial. :) – Mithaldu Feb 27 '13 at 12:49
  • I benchmarked Xslate against Template and mojo::template and I found that Xslate is no longer that fasted. It is about 5 times faster than Template, and 2x slower than mojo::template. – Renato Cron Jun 26 '17 at 15:28
  • Link to benchmark, and feature comparison of the two? – Mithaldu Jun 27 '17 at 16:26
12

I'm currently experimenting with Template::Alloy and it seems to be, by and large, a drop-in replacement for TT. Template::Alloy::TT lists the differences between TT and Alloy, most of which are of the form "This works/is allowed in Alloy, but not in TT." Addressing your specific issue, the list includes:

  • Alloy has better line information

When debug dirs is on, directives on different lines separated by colons show the line they are on rather than a general line range.

Parse errors actually know what line and character they occured at.

Dave Sherohman
  • 45,363
  • 14
  • 64
  • 102
  • Tested Template::Alloy today. Debug_dirs is not suitable for my purpose because it assumes that I am generating HTML and inserts HTML style comments. For a case of x=[] /*empty array*/ followed by x.0 somewhere in the template Template::Alloy was comparatively more helpful as is gave the complete message x.0 is not defined as opposed to TT2 which said 0 is undefined.... Will try Xslate tomorrow. – vijayvithal Jan 10 '13 at 14:58
  • If I use Template::Alloy and DEBUG => DEBUG_DIRS I get "var.undef error - undefined variable: bar in ln.tt". but it's missing the line information – tinita Jan 10 '13 at 15:09
  • As a note for anyone stumbling upon this at a later point in time: T::A is slightly better than TT, but considerably inferior to any other templating library on CPAN. Most damningly, it's been abandoned by its maintainer, with the last release being "SEP 20, 2013", roughly 2 years ago. – Mithaldu Aug 11 '15 at 20:16
  • 1
    @Mithaldu - Thanks for that update! I'm using Xslate myself these days, too. – Dave Sherohman Aug 12 '15 at 07:35
10

Mojolicious comes with its own templating system Mojo::Template. Its lightweight and can be used even outside of the mojolicious system. Here is an example from the docs:

use Mojo::Template;
  my $mt = Mojo::Template->new;

  # Simple
  my $output = $mt->render(<<'EOF');
  % use Time::Piece;
  <!DOCTYPE html>
  <html>
    <head><title>Simple</title></head>
    % my $now = localtime;
    <body>Time: <%= $now->hms %></body>
  </html>
  EOF
  say $output;

and another

  # More advanced
  my $output = $mt->render(<<'EOF', 23, 'foo bar');
  % my ($number, $text) = @_;
  %= 5 * 5
  <!DOCTYPE html>
  <html>
    <head><title>More advanced</title></head>
    <body>
      test 123
      foo <% my $i = $number + 2; %>
      % for (1 .. 23) {
      * some text <%= $i++ %>
      % }
    </body>
  </html>
  EOF
  say $output;
Joel Berger
  • 20,180
  • 5
  • 49
  • 104
  • 3
    @downvoter, care to comment? Mojo::Template addresses all the OPs concerns and is quick and easy to install and start using. – Joel Berger Jan 15 '13 at 17:41
5

I can suggest HTML::Template:Compiled (but note I'm the author ;-)

It is quite compatible to HTML::Template, but has additional features.

Support for complex data structures

yes

Good error reporting and debug capabilities.

You can debug cache hits, misses, automatically add template filename to output and can use a filter "DUMP" for the current variable in stash (or any variable). If it's easy to implement I'll happily add more useful debugging.

Stable and proven ( no alpha/beta level engines)

I would consider it stable now, with the documented limitations/bugs (for example query())

Extensible (plugin's etc)

supports escape (filter) plugins and more, though the latter is not documented very well yet.

Should not be restricted to a given language (html etc.)

yes

support for IF/Else, looping(foreach while), Loop indexing, etc.

yes

Preferably perl

yes

Support for data dumper or equivalent plugin from within the template is a plus

like mentioned above, use escape=dump

all additional features are listed in the documentation: https://metacpan.org/release/HTML-Template-Compiled at "ADDITIONAL FEATURES"

edit: regarding reporting runtime errors: unfortunately H::T::C also does not report the template line number for errors that happen at runtime, since it compiles the template to perl-code (I think I experimented with manipulating line numbers once, maybe I'll have another look). template syntax errors are reported with the correct line number.

edit2: So here's an example with the new options warnings and line_info:

t/templates/line_info1.html:

test
test2
test3
foo:<%= foo %> undef line 4
test4

script:

use HTML::Template::Compiled;
my $t = HTML::Template::Compiled->new(
    filename => "t/templates/line_info1.html",
    warnings => 1,
    line_info => 1,
);
say $t->output;
__END__
Use of uninitialized value in concatenation (.) or string at t/templates/line_info1.html line 4.
test
test2
test3
foo: undef line 4
test4
tinita
  • 3,987
  • 1
  • 21
  • 23
  • tinita, regretfully I am looking to move away from TT only because it does not report the correct line numbers for the error :( – vijayvithal Jan 09 '13 at 16:35
  • @vijayvithal: I had another look and it seems to be possible by adding a SIG handler for __WARN__ and by manipulating line numbers via #line directives. test suite suceeds. – tinita Jan 09 '13 at 21:50
  • oh, I don't need the sig handler at all. I think about adding an option to activate this feature in the next version. – tinita Jan 09 '13 at 22:12
  • @vijayvithal: I uploaded 1.000_004. added option 'warnings' and 'line_info' (forgot to update Changes file though) – tinita Jan 09 '13 at 23:42
2

take a look on Template::Semantic for pure template abstraction

vividsnow
  • 21
  • 3