package HTML::ERuby;
# $Id: ERuby.pm,v 1.5 2002/04/14 01:04:49 ikechin Exp $
use strict;
use vars qw($VERSION $ERUBY_TAG_RE);
use IO::File;
use Carp ();
use Inline::Ruby qw(rb_eval);
use Data::Dumper;
$ERUBY_TAG_RE = qr/(<%%|%%>|<%=|<%#|<%|%>|\n)/so;
$VERSION = '0.02';
sub new {
my $class = shift;
my $self = bless {
}, $class;
$self;
}
sub compile {
my ($self, %args) = @_;
my $data;
if ($args{filename}) {
$data = $self->_open_file($args{filename});
}
elsif ($args{scalarref}) {
$data = ${$args{scalarref}};
}
elsif ($args{arrayref}) {
$data = join('', @{$args{arrayref}});
}
else {
Carp::croak("please specify ERuby document");
}
my $vars = '';
if ($args{vars}) {
$vars = $self->_convert_vars($args{vars});
}
my $src = $self->_parse(\$data);
return rb_eval($vars. $src);
}
sub _open_file {
my ($self, $filename) = @_;
local $/ = undef;
my $f = IO::File->new($filename, "r") or Carp::croak("can not open eruby file: $filename");
my $data = $f->getline;
$f->close;
return $data;
}
sub _convert_vars {
my ($self, $vars) = @_;
my $code = '';
local $Data::Dumper::Deepcopy = 1;
while(my ($name, $value) = each %$vars) {
if (my $type = ref($value)) {
Carp::croak(__PACKAGE__. " supports String, Hash and Array only")
if $type ne 'ARRAY' && $type ne 'HASH';
}
my $dumped = Dumper $value;
$dumped =~ s/\$VAR1 =//; # strip Data::Dumper '$VAR1 =' string.
$code .= "$name = $dumped\n";
}
return $code;
}
# copy from erb/compile.rb and Perlize :)
sub _parse {
my($self, $scalarref) = @_;
my $src = q/_erb_out = '';/;
my @text = split($ERUBY_TAG_RE, $$scalarref);
my @content = ();
my @cmd = ("_erb_out = ''\n");
my $stag = '';
my $token = '';
for my $token(@text) {
if ($token eq '<%%') {
push @content, '<%';
next;
}
if ($token eq '%%>') {
push @content, '%>';
next;
}
unless ($stag) {
if ($token eq '<%' || $token eq '<%=' || $token eq '<%#') {
$stag = $token;
my $str = join('', @content);
if ($str) {
push @cmd, qq/_erb_out.concat '$str';/;
}
@content = ();
}
elsif($token eq "\n") {
push @content, "\n";
my $str = join('', @content);
push @cmd, qq/_erb_out.concat '$str';/ if $str;
@content = ();
}
else {
push @content, $token;
}
}
else {
if ($token eq '%>') {
my $str = join('', @content);
if ($stag eq '<%') {
push @cmd, $str, "\n";
}
elsif ($stag eq '<%=') {
push @cmd, qq/_erb_out.concat( ($str).to_s );/;
}
elsif ($stag eq '<%#') {
# comment out SKIP!
}
@content = ();
$stag = undef;
}
else {
push @content, $token;
}
}
}
if (@content) {
my $str = join('', @content);
push @cmd, qq/_erb_out.concat '$str';/;
}
push @cmd, '_erb_out;';
return join('', @cmd);
}
1;
__END__
=pod
=head1 NAME
HTML::ERuby - ERuby processor for Perl.
=head1 SYNOPSIS
use HTML::ERuby;
my $compiler = HTML::ERuby->new;
my $result = $compiler->compile(filename => './foo.rhtml');
print $result;
=head1 DESCRIPTION
HTML::ERuby is a ERuby processor written in Perl.
parse ERuby document by Perl and evaluate by Ruby.
=head1 METHODS
=over 4
=item $compiler = HTML::ERuby->new
constructs HTML::ERuby object.
=item $result = $compiler->compile(\%option)
compile ERuby document and return result.
you can specify ERuby document as filename, scalarref or arrayref.
$result = $compiler->compile(filename => $filename);
$result = $compiler->compile(scalarref => \$rhtml);
$result = $compiler->compile(arrayref => \@rhtml);
you can use the Perl variables in the ERuby document.
supported types are String, Hash and Array only. NO Objects.
See the simple example.
Perl code
my %vars = (
'@var' => 'foo', # Ruby instance variable
'ARRAY_REF' => [qw(a b c)], # Ruby constant
'hash_ref' => {foo => 'bar', 'bar' => 'baz'} # Ruby local variable
);
my $compiler = HTML::ERuby->new;
print $compiler->compile(filename => './foo.rhtml', vars => \%vars);
ERuby document
instance variable <%= @var %>
<% ARRAY_REF.each do |v| %>
<%= v %>
<% end %>
foo: <%= hash_ref['foo'] %>
bar: <%= hash_ref['baz'] %>
Result
instance variable foo
a
b
c
foo: bar
bar: baz
=back
=head1 CAVEATS
this module is experimental.
=head1 AUTHOR
Author Eikebe@edge.co.jpE
This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself.
=head1 SEE ALSO
L L
http://www2a.biglobe.ne.jp/~seki/ruby/erb.html
http://www.modruby.net/
=cut