views:

109

answers:

2

I'm trying to create a cpan module that integrates Text::Haml into Template Toolkit. I think that Haml is an interesting templating language but rather limited, it doesn't support loops or conditionals let alone more advanced things. But I can't seem to get eve a very simple version to work. The following are some test scripts that work to make sure my logic works.

Here's my attempt at the filter module using the Template::Plugin::Filter Documentation

use strict;
use warnings;
package Template::Plugin::Haml;

use Template::Plugin::Filter;

use parent 'Template::Plugin::Filter';

sub filter {
    my ( $self, $text ) = @_;

# thes aren't actually the problem
#   my $haml = Text::Haml->new;
#   my $html = $haml->render($text);
#   return $html;

    return $text;
}
1;

and some code to use it

#!/usr/bin/perl
# test0.pl
use strict;
use warnings;

use Template;

my $tt = Template->new;

my $vars = {};
my $output = \do{my $i};

$tt->process(\*DATA, $vars, $output);

print $$output;
__DATA__
[% USE Haml %]
[% FILTER Haml %]
#profile
[% END %]

but I get this warning Use of uninitialized value in print at test0.pl line 15, <DATA> line 1.

I know what this error means... but I'm not sure why the filter causing this. Any help would be appreciated

The following are some test scripts that other parts of my logic work, so that we're not looking at the wrong code to fix the issue. Otherwise they aren't really necessary for the problem

This shows how to use Template::Toolkit

#!/usr/bin/perl
# test1.pl - show how to use tt
use strict;
use warnings;

use Template;

my $tt = Template->new;

my $vars = {};
my $output = \do{my $i};

$tt->process(\*DATA, $vars, $output);

print $$output; # #profile
__DATA__
#profile

this shows us how to use Text::Haml

#!/usr/bin/perl
# test2.pl
use 5.010;
use strict;
use warnings;

use Text::Haml;

my $text = '#profile';
my $haml = Text::Haml->new;
my $html = $haml->render($text);
say $html; # <div id='profile'></div>

UPDATE 1

I've tried this (which is almost identical to the markdown plugin and one almost identical to the Textile plugin as well)

use strict;
use warnings;
package Template::Plugin::Haml;

use parent 'Template::Plugin::Filter';
use 'Text::Haml';

sub init {
    my $self = shift;
    $self->{_DYNAMIC} = 1;
    $self->install_filter( $self->{_ARGS}->[0] || 'haml');
    $self;
}

sub filter {
    my ( $self, $text, $args, $config ) = @_;

    my $haml = Text::Haml->new;
    return $haml->render($text);
}
1;

UPDATE 2 output from enabling DEBUG => 'all', at TT initialization

[Template::Provider] creating cache of unlimited slots for [ . ]
[Template::Service] process(GLOB(0x1719608), HASH(0x16f1650))
[Template::Context] template(GLOB(0x1719608))
[Template::Context] asking providers for [GLOB(0x1719608)] []
[Template::Provider] _load(GLOB(0x1719608), <no alias>)
[Template::Provider] _compile(HASH(0x1a947a0), <no compfile>)
[Template::Parser] compiled main template document block:
sub {
    my $context = shift || die "template sub called without context\n";
    my $stash   = $context->stash;
    my $output  = '';
    my $_tt_error;

    eval { BLOCK: {
#line 1 "input file handle"
$output .=  $context->debugging('msg', { 'line' => '1', 'text' => 'USE Haml', 'file' => 'input file handle' }); ## DEBUG ##
#line 1 "input file handle"
# USE
$stash->set('Haml',
            $context->plugin('Haml'));
#line 2 "input file handle"
$output .=  $context->debugging('msg', { 'line' => '2', 'text' => 'FILTER haml', 'file' => 'input file handle' }); ## DEBUG ##
#line 4 "input file handle"

# FILTER
$output .=  do {
    my $output = '';
    my $_tt_filter = $context->filter('haml')
              || $context->throw($context->error);

$output .=  "#profile";
#line 4 "input file handle"
$output .=  $context->debugging('msg', { 'line' => '4', 'text' => 'END', 'file' => 'input file handle' }); ## DEBUG ##

    &$_tt_filter($output);
};

    } };
    if ($@) {
        $_tt_error = $context->catch($@, \$output);
        die $_tt_error unless $_tt_error->type eq 'return';
    }

    return $output;
}
[Template::Service] PROCESS: Template::Document=HASH(0x1c69ba0)
[Template::Context] process([ Template::Document=HASH(0x1c69ba0) ], <no params>, <unlocalized>)
[Template::Context] template(Template::Document=HASH(0x1c69ba0))
[Template::Context] plugin(Haml, [ ])
[Template::Plugins] fetch(Haml, <no args>, Template::Context=HASH(0x1972040))
[Template::Plugins] loading Template/Plugin/Haml.pm (PLUGIN_BASE)
[Template::Plugins] calling Template::Plugin::Haml->load()
[Template::Plugins] Haml => Template::Plugin::Haml
[Template::Filters] store(haml, ARRAY(0x1c1f4d8))
[Template::Context] filter(haml, [ ]<no alias>)
[Template::Filters] fetch(haml, <no args>, Template::Context=HASH(0x1972040))
Use of uninitialized value in string eq at /usr/share/perl5/vendor_perl/Text/Haml.pm line 452, <DATA> line 1.
Use of uninitialized value in string eq at /usr/share/perl5/vendor_perl/Text/Haml.pm line 452, <DATA> line 1.
Use of uninitialized value in string eq at /usr/share/perl5/vendor_perl/Text/Haml.pm line 452, <DATA> line 1.
Use of uninitialized value in string eq at /usr/share/perl5/vendor_perl/Text/Haml.pm line 452, <DATA> line 1.
Use of uninitialized value in string eq at /usr/share/perl5/vendor_perl/Text/Haml.pm line 452, <DATA> line 1.
Use of uninitialized value in string eq at /usr/share/perl5/vendor_perl/Text/Haml.pm line 452, <DATA> line 1.
Use of uninitialized value in string eq at /usr/share/perl5/vendor_perl/Text/Haml.pm line 452, <DATA> line 1.
Use of uninitialized value in string eq at /usr/share/perl5/vendor_perl/Text/Haml.pm line 452, <DATA> line 1.
Use of uninitialized value in string eq at /usr/share/perl5/vendor_perl/Text/Haml.pm line 452, <DATA> line 1.
Use of uninitialized value in string eq at /usr/share/perl5/vendor_perl/Text/Haml.pm line 452, <DATA> line 1.
Use of uninitialized value in concatenation (.) or string at /usr/share/perl5/vendor_perl/Text/Haml.pm line 674, <DATA> line 1.
Use of uninitialized value in concatenation (.) or string at /usr/share/perl5/vendor_perl/Text/Haml.pm line 683, <DATA> line 1.

## input file handle line 1 : [% USE Haml %] ##

## input file handle line 2 : [% FILTER haml %] ##
<div id='profile'></div>
<>## input file handle line 4 : [% END %] ##</>
A: 

OK, I can't get this to work either.

Refining the test script somewhat to remove possible distractions:

#!/usr/bin/env perl
use strict;
use warnings;
use FindBin qw/$Bin/;
use lib "$Bin/../lib";

use Template;
my $tt = Template->new(
    STRICT => 1,
    PLUGINS => { MyFilter => 'Template::Plugin::Haml'},
    );

$tt->process(\*DATA, {});

__DATA__
Some non haml stuff
[% USE Haml %]
[% FILTER Haml %]
%h1. some haml stuff
[% END %]

And when I run it with perl -Ilib t/01-test.t (having set up a cpan dist) I get no output. However if I run this without the HAML block in the template I get the output:

Some non haml stuff

(If I comment out the Filter HAML and the END bit, then I get the full output as expected too)

singingfish
+1  A: 

Here's a link to the final product on CPAN Template::Plugin::Haml

Got it

use strict;
use warnings;
package Template::Plugin::Haml;

use parent 'Template::Plugin::Filter';
use Text::Haml;

sub init {
    my $self = shift;
    $self->{_DYNAMIC} = 1;
    $self->install_filter( $self->{_ARGS}->[0] || 'haml');
    $self;
}

sub filter {
    my ( $self, $text, $args, $config ) = @_;

    my $haml = Text::Haml->new;
    return $haml->render($text);
}
1;

and test0.pl

#!/usr/bin/perl
# test0.pl
use strict;
use warnings;

use Template;

my $tt = Template->new; #or die $Template::Error, "\n";

my $vars = {};
my $output = \do{my $i};

$tt->process(\*DATA, $vars, $output);

print $$output; # \n\n<div id='profile'></div>\n\n
__DATA__
[% USE Haml %]
[% FILTER haml %]
#profile
[% END %]

seems I had quoted use 'Text::Haml' and that I needed some init code.

xenoterracide