Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CL-WHO-like HTML templating for other languages? [closed]

Common Lisp guys have their CL-WHO, which makes HTML templating integrated with the "main" language thus making the task easier. For those who don't know CL-WHO, it looks like this (example from CL-WHO's webpage):

(with-html-output (*http-stream*)
(:table :border 0 :cellpadding 4
  (loop for i below 25 by 5
     do (htm
         (:tr :align "right"
          (loop for j from i below (+ i 5)
                do (htm
                    (:td :bgcolor (if (oddp j)
                                    "pink"
                                    "green")
                         (fmt "~@R" (1+ j))))))))))

Do you know any libraries like this for other languages? The one I know about (that mimics CL-WHO) is Brevé for Python. I'm particularly interested in Perl flavour, but it's interesting how other languages handle integrating HTML into their syntax.

like image 490
Nikolai Prokoschenko Avatar asked Mar 22 '09 20:03

Nikolai Prokoschenko


1 Answers

For CPAN offerings have a look at the following (in alphabetical order)...

  • Builder
  • HTML::AsSubs
  • HTML::Tiny
  • Markapl
  • Template::Declare
  • XML::Generator

Using the table part of the CL-WHO example provided (minus Roman numerals and s/background-color/color/ to squeeze code into screen width here!)....


Builder

use Builder;
my $builder = Builder->new;
my $h = $builder->block( 'Builder::XML' );

$h->table( { border => 0, cellpadding => 4 }, sub {
   for ( my $i = 1; $i < 25; $i += 5 ) {
       $h->tr( { align => 'right' }, sub {
           for my $j (0..4) {
               $h->td( { color => $j % 2 ? 'pink' : 'green' }, $i + $j );
           }
       });
   } 
});

say $builder->render;


HTML::AsSubs

use HTML::AsSubs;

my $td = sub {
    my $i = shift;
    return map { 
        td( { color => $_ % 2 ? 'pink' : 'green' }, $i + $_ )
    } 0..4;
};

say table( { border => 0, cellpadding => 4 },
    map { 
        &tr( { align => 'right' }, $td->( $_ ) ) 
    } loop( below => 25, by => 5 )
)->as_HTML;


HTML::Tiny

use HTML::Tiny;
my $h = HTML::Tiny->new;

my $td = sub {
    my $i = shift;
    return map { 
        $h->td( { 'color' => $_ % 2 ? 'pink' : 'green' }, $i + $_ )
    } 0..4;
};

say $h->table(
    { border => 0, cellpadding => 4 },
    [
        map { 
            $h->tr( { align => 'right' }, [ $td->( $_ ) ] )  
        } loop( below => 25, by => 5 )    
    ]
);


Markapl

use Markapl;

template 'MyTable' => sub {
    table ( border => 0, cellpadding => 4 ) {
       for ( my $i = 1; $i < 25; $i += 5 ) {
           row ( align => 'right' ) {
               for my $j ( 0.. 4 ) {
                   td ( color => $j % 2 ? 'pink' : 'green' ) { $i + $j }
               }
           }
       } 
    }
};

print main->render( 'MyTable' );


Template::Declare

package MyTemplates;
use Template::Declare::Tags;
use base 'Template::Declare';

template 'MyTable' => sub {
    table {
        attr { border => 0, cellpadding => 4 };
        for ( my $i = 1; $i < 25; $i += 5 ) {
            row  {
                attr { align => 'right' };
                    for my $j ( 0..4 ) {
                        cell {
                            attr { color => $j % 2 ? 'pink' : 'green' } 
                            outs $i + $j;
                        }
                    }
            }
        } 
    }
};

package main;
use Template::Declare;
Template::Declare->init( roots => ['MyTemplates'] );
print Template::Declare->show( 'MyTable' );


XML::Generator

use XML::Generator;
my $x = XML::Generator->new( pretty => 2 );

my $td = sub {
    my $i = shift;
    return map { 
        $x->td( { 'color' => $_ % 2 ? 'pink' : 'green' }, $i + $_ )
    } 0..4;
};

say $x->table(
    { border => 0, cellpadding => 4 },
    map { 
        $x->tr( { align => 'right' }, $td->( $_ ) )  
    } loop( below => 25, by => 5 )    
);


And the following can be used to produce the "loop" in HTML::AsSubs / HTML::Tiny / XML::Generator examples....

sub loop {
    my ( %p ) = @_;
    my @list;

    for ( my $i = $p{start} || 1; $i < $p{below}; $i += $p{by} ) {
        push @list, $i;
    }

    return @list;
}
like image 151
12 revs, 2 users 99% Avatar answered Nov 07 '22 05:11

12 revs, 2 users 99%