[Jifty-commit] r2167 - in Template-Declare: . lib lib/Template lib/Template/Declare lib/Wifty t

jifty-commit at lists.jifty.org jifty-commit at lists.jifty.org
Wed Nov 15 21:42:11 EST 2006


Author: jesse
Date: Wed Nov 15 21:42:11 2006
New Revision: 2167

Added:
   Template-Declare/Makefile.PL
   Template-Declare/lib/
   Template-Declare/lib/MyApp/
   Template-Declare/lib/Template/
   Template-Declare/lib/Template/Declare/
   Template-Declare/lib/Template/Declare.pm
   Template-Declare/lib/Template/Declare/Tags.pm
   Template-Declare/lib/Wifty/
   Template-Declare/mycode
   Template-Declare/pl
   Template-Declare/t/
   Template-Declare/t/trivial.t
Modified:
   Template-Declare/   (props changed)

Log:
  * Initial version of Template::Declare


Added: Template-Declare/Makefile.PL
==============================================================================
--- (empty file)
+++ Template-Declare/Makefile.PL	Wed Nov 15 21:42:11 2006
@@ -0,0 +1,6 @@
+use inc::Module::Install;
+name('Template-Declare');
+license('Pelr');
+author('Jesse Vincent <jesse at bestpractical.com>');
+version_from('lib/Template/Declare.pm');
+WriteAll;

Added: Template-Declare/lib/Template/Declare.pm
==============================================================================
--- (empty file)
+++ Template-Declare/lib/Template/Declare.pm	Wed Nov 15 21:42:11 2006
@@ -0,0 +1,41 @@
+use warnings;
+use strict;
+
+package Template::Declare;
+
+$Template::Declare::VERSION = "-1.00_01";
+
+=head1 NAME
+
+Template::Declare
+
+=head1 DESCRIPTION
+
+C<Template::Declare> is a prototype declarative code-based HTML
+templating system. Yes. Another one. There are many others like it,
+but this one is ours. It's designed to allow template libraries to be
+composed, mixed in and inherited. The code isn't (yet) pretty nor is 
+it in any way optimized. It's not well enough tested, either.
+
+In the coming weeks, months and years, Template::Declare we will extend it
+to support all the things we've designed it to do. 
+
+=head1 BUGS
+
+Crawling all over, baby. Be very, very careful. This code is so cutting edge, it can only be fashioned from carbon nanotubes.
+
+The only real documentation is in t/trivial.t
+
+=cut
+
+
+sub has_template {
+    my $pkg = shift;
+    my $templatename = shift;
+
+    my $callable = "_jifty_template_".$templatename;
+    return $pkg->can($callable);
+
+}
+
+1;

Added: Template-Declare/lib/Template/Declare/Tags.pm
==============================================================================
--- (empty file)
+++ Template-Declare/lib/Template/Declare/Tags.pm	Wed Nov 15 21:42:11 2006
@@ -0,0 +1,114 @@
+use warnings;
+use strict;
+
+package Template::Declare::Tags;
+use vars qw/@EXPORT @EXPORT_OK $self/;
+use base 'Exporter';
+ at EXPORT_OK = (qw(with));
+ at EXPORT = (qw(with template private show outs  outs in_isolation));
+
+our $DEPTH = 0;
+our %ATTRIBUTES = ();
+our $BUFFER = '';
+
+sub outs { $BUFFER .= join('',grep { defined } @_); return ''; }
+sub template ($$) {
+    my $templatename = shift;
+    my $coderef = shift;
+    no strict 'refs';
+    *{(caller(0))[0]."::_jifty_template_$templatename"} = sub { my $self = shift; $coderef->(@_) } ;
+
+}
+sub private ($){}
+
+sub install_tag {
+    my $tag = shift;
+    { no strict 'refs';
+      *{$tag} = sub (&) {local *__ANON__ = $tag; _tag(@_)};
+    }
+      push @EXPORT_OK, $tag;
+      push @EXPORT, $tag;
+}
+
+
+our %TAGS = ( html => {}, head => {}, title => {}, meta => {}, body => {}, p => {}, hr => {}, br => {}, ul => {}, dl => {}, dt=> {}, dd => {}, ol => {}, li => {}, b => {}, i => {}, em => {}, div => {}, span => {}, form => {}, input => {}, textarea => {}, select => {}, option => {}, a => {}, pre => {}, code => {}, address => {}, iframe => {}, script => {}, h1 => {}, h2=> {}, h3 => {}, h4 => {}, h5 => {}, ); install_tag($_) for(keys %TAGS);
+
+
+
+
+sub with (@) {
+    %ATTRIBUTES = ();
+    while (@_) {
+        my $key = shift || '';
+        my $val = shift || '';
+        $ATTRIBUTES{$key} = $val;
+    }
+}
+
+sub _tag {
+    my $code = shift;
+    my ($package,   $filename, $line,       $subroutine, $hasargs,
+        $wantarray, $evaltext, $is_require, $hints,      $bitmask
+        )
+        = caller(1);
+
+    # This is the hash of attributes filled in by attr() calls in the code;
+
+    my $tag = $subroutine;
+    $tag =~ s/^.*\:\://;
+    $BUFFER .= "\n" . ( " " x $DEPTH ) . "<$tag"
+        . join( '',
+        map { qq{ $_="} . ( $ATTRIBUTES{$_} || '' ) . qq{"} }
+            keys %ATTRIBUTES );
+    %ATTRIBUTES = ();
+
+    my $buf;
+    {
+        local $BUFFER = '';
+        local $DEPTH  = $DEPTH + 1;
+        my $last = $code->() || '';
+
+        $buf = $BUFFER;
+
+# We concatenate "" to force scalarization when $last or $BUFFER is solely a Jifty::Web::Link
+        $buf .= $last unless ($BUFFER);    # HACK WRONG;
+    }
+
+    # default to <tag/> rather than <tag></tag> if there's no content
+    if ($buf) {
+        $BUFFER .= ( ">" . $buf );
+        $BUFFER .= "\n" . ( " " x $DEPTH ) if ( $buf =~ /\n/ );
+        $BUFFER .= "</$tag>";
+    } else {
+        $BUFFER .= "/>";
+    }
+    return '';
+}
+
+=head2 show [$class or $object] templatename
+
+show can either be called with a template name or a package/object and 
+a template.  (It's both functional and OO.)
+
+Displays that template, if it exists. 
+
+
+=cut
+
+sub show {
+    $self = shift if ( $_[0]->isa('Template::Declare') );
+    my $templatename = shift;
+    my $buf;
+    {
+        local $BUFFER = '';
+        my $callable = "_jifty_template_" . $templatename;
+
+        # may want to just use the return value of has_template eventuall
+        my $ret = $self->$callable(@_) if $self->has_template($templatename);
+        $buf = $BUFFER;
+    }
+    $BUFFER .= $buf;
+    return $buf;
+}
+
+1;

Added: Template-Declare/mycode
==============================================================================
--- (empty file)
+++ Template-Declare/mycode	Wed Nov 15 21:42:11 2006
@@ -0,0 +1,24 @@
+use warnings;
+use strict;
+
+use Wifty::Widgets;
+use Template::Declare::Tags;
+
+
+print html {
+
+    head {
+        attr id   => 5;
+        attr name => "I hate you";
+    };
+    body {
+        for ( 1 .. 5 ) {
+            span { attr class => "bozo"; 'yyy' };
+        }
+        attr bgcolor => "#ffffff";
+        p {'xxx'};
+        Wifty::Widgets->login_widget();
+        }
+};
+
+1;

Added: Template-Declare/pl
==============================================================================
--- (empty file)
+++ Template-Declare/pl	Wed Nov 15 21:42:11 2006
@@ -0,0 +1,63 @@
+use warnings; use strict;
+use vars qw'%ATTRIBUTES $BUFFER $DEPTH';
+sub html (&) { _element(@_); }
+sub head (&) { _element(@_); }
+sub body (&) { _element(@_); }
+sub p (&)    { _element(@_); }
+sub br (&)   { _element(@_); }
+sub ul (&)   { _element(@_); }
+sub li (&)   { _element(@_); }
+sub dl (&)   { _element(@_); }
+sub ol (&)   { _element(@_); }
+sub b (&)    { _element(@_); }
+sub i (&)    { _element(@_); }
+sub em (&)   { _element(@_); }
+sub div (&)  { _element(@_); }
+sub span (&) { _element(@_); }
+sub attr ($$) {my ($key,$val)=(@_); $ATTRIBUTES{$key} = $val; }
+
+sub _element {
+    my $code = shift;
+    my ($package,   $filename, $line,       $subroutine, $hasargs,
+        $wantarray, $evaltext, $is_require, $hints,      $bitmask
+        )
+        = caller(1);
+
+    local %ATTRIBUTES = ();
+
+    my $tag = $subroutine;
+    $tag =~ s/^$package\:\://;
+
+my $buf;
+    {
+    local $BUFFER = '';
+    local $DEPTH = $DEPTH +1;
+
+    $code->();
+     $buf = $BUFFER;
+}
+    $BUFFER .= "\n".(" " x $DEPTH). "<$tag"
+        . join( '', map {qq{ $_="$ATTRIBUTES{$_}"}} keys %ATTRIBUTES ) . ">"
+        . ($buf ? ($buf . "\n" . (" " x $DEPTH) ) : '')
+        ."</$tag>";
+
+    return $BUFFER;
+}
+
+
+print html {
+
+    head {
+        attr id   => 5;
+        attr name => "I hate you";
+    };
+    body {
+        for ( 1 .. 5 ) {
+            span { attr class => "bozo"; 'yyy' };
+        }
+        attr bgcolor => "#ffffff";
+        p {'xxx'};
+        }
+};
+
+

Added: Template-Declare/t/trivial.t
==============================================================================
--- (empty file)
+++ Template-Declare/t/trivial.t	Wed Nov 15 21:42:11 2006
@@ -0,0 +1,184 @@
+use warnings;
+use strict;
+
+
+package Wifty::UI;
+use base qw/Template::Declare/;
+use Template::Declare::Tags;
+use Test::More;
+
+template simple => sub {
+
+html { 
+    head { };
+        body {
+            show 'content';
+        }
+}
+
+};
+
+template content => sub {
+        with( id => 'body' ), div {
+            outs('This is my content');
+        };
+
+};
+
+
+template wrapper => sub {
+    my ( $title, $coderef) = (@_);
+    outs('<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">');
+        with ( xmlns      => "http://www.w3.org/1999/xhtml", 'xml:lang' => "en"), 
+    html {
+        head {
+            with ( 'http-equiv' => "content-type", 'content'    => "text/html; charset=utf-8"),
+            meta { };
+            with ( name    => "robots", content => "all"), meta { };
+            title { outs($title) };
+            };
+        body {
+            $coderef->(); 
+        }
+            
+        }
+};
+
+template markup => sub {
+    my $self = shift;
+
+    show(
+        'wrapper',
+        'My page!',
+        sub {
+
+            with( id => 'syntax' ), div {
+                div {
+                    with(
+                        href    => "#",
+                        onclick =>
+                            "Element.toggle('syntax_content');return(false);"
+                        ),
+                        a {
+                        b {'Wiki Syntax Help'};
+                        }
+                };
+                with( id => 'syntax_content' ), div {
+                    h3   {'Phrase Emphasis'};
+                    code {
+                        b { '**bold**'; };
+                        i {'_italic_'};
+                    };
+
+                    h3 {'Links'};
+
+                    code {'Show me a [wiki page](WikiPage)'};
+                    code {'An [example](http://url.com/ "Title")'};
+                    h3   {'Headers'};
+                    pre  {
+                        code {
+                            join( "\n",
+                                '# Header 1',
+                                '## Header 2',
+                                '###### Header 6' );
+                            }
+                    };
+                    h3  {'Lists'};
+                    p   {'Ordered, without paragraphs:'};
+                    pre {
+                        code { join( "\n", '1.  Foo', '2.  Bar' ); };
+                    };
+                    p   {' Unordered, with paragraphs:'};
+                    pre {
+                        code {
+                            join( "\n",
+                                '*   A list item.',
+                                'With multiple paragraphs.',
+                                '*   Bar' );
+                            }
+                    };
+                    h3 {'Code Spans'};
+
+                    p {
+                        code {'`&lt;code&gt;`'}
+                            . 'spans are delimited by backticks.';
+                    };
+
+                    h3 {'Preformatted Code Blocks'};
+
+                    p {
+                        'Indent every line of a code block by at least 4 spaces.';
+                    };
+
+                    pre {
+                        code {
+                            'This is a normal paragraph.' . "\n\n" . "\n"
+                                . '    This is a preformatted' . "\n"
+                                . '    code block.';
+                        };
+                    };
+
+                    h3 {'Horizontal Rules'};
+
+                    p {
+                        'Three or more dashes: ' . code {'---'};
+                    };
+
+                    address {
+                        '(Thanks to <a href="http://daringfireball.net/projects/markdown/dingus">Daring Fireball</a>)';
+                        }
+                    }
+            };
+            script {
+                qq{
+   // javascript flyout by Eric Wilhelm
+   // TODO use images for minimize/maximize button
+   // Is there a way to add a callback?
+   Element.toggle('syntax_content');
+   };
+            };
+        }
+    );
+};
+
+package Template::Declare::Tags;
+
+use Test::More qw/no_plan/;
+use HTML::Lint;
+
+our $self;
+local $self = {};
+bless $self, 'Wifty::UI';
+{
+local $Template::Declare::Tags::BUFFER;
+my $simple =(show('simple'));
+ok($simple =~ 'This is my content');
+#diag ($simple);
+ok_lint($simple);
+}
+{local $Template::Declare::Tags::BUFFER;
+my $out =  (show('markup'));
+#diag($out);
+my @lines = split("\n",$out);
+
+ok($out =~ /Fireball/, "We found fireball in the output");
+my $count = grep { /Fireball/} @lines;
+is($count, 1, "Only found one");
+ok_lint($out);
+
+}
+sub ok_lint {
+    my $html = shift;
+
+    my $lint = HTML::Lint->new;
+
+    $lint->parse($html);
+    is( $lint->errors, 0, "Lint checked clean" );
+    foreach my $error ( $lint->errors ) {
+        diag( $error->as_string );
+    }
+
+}
+
+
+1;


More information about the Jifty-commit mailing list