diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..fabf26c --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +tests/tjs/var +Makefile +Makefile.old +Makefile.js +t/a.js +t/b.js +t/check.js +t? diff --git a/Changes b/Changes index d5e6f25..6de2d40 100644 --- a/Changes +++ b/Changes @@ -1,3 +1,75 @@ +--- +version: 0.261 +date: Tuesday April 27 09:35:06 PDT 2010 +changes: +- Fixed rt56956 with test case - DIV operator broken (Agent Zhang) + +--- +version: 0.260 +date: Monday April 26 12:03:40 PDT 2010 + +--- +version: 0.25_2 +date: Saturday April 24 18:48:53 PDT 2010 +changes: +- Implemented rt4308 - Capture implementation (Tom Molesworth) +- Added test for rt37570 - List method for lists (fixed in 5eaf340da...) + +--- +version: 0.25_1 +date: Thursday April 22 17:58:53 PDT 2010 +changes: +- Fixed rt53454 with test case - Support rudimentary array range operator +- Fixed rt53453 with test case - Make Jemplate slice like TT slice +- Fixed rt53967 with test case - Compiler double-dot path fail +- Added test case for rt37539 - Intermediate instantiation +- Added test case for rt37540 - Iterate over empty object +- Added test case for rt37895 - Inconsistent jemplate version + +--- +version: 0.25 +date: Wednesday April 21 13:44:19 PDT 2010 +changes: +- release + +--- +version: 0.24_4 +date: Saturday January 09 17:06:40 PST 2010 +changes: +- added .pairs (VMethod) functionality with tests +- fixed quoted.t failing test + +--- +version: 0.24_3 +date: Mon Jun 8 2009 +changes: +- fixed bug, related to empty template body (http://rt.cpan.org/Public/Bug/Display.html?id=37061) +- fixed bug in Parser.yp, which produced compilation error for macroses +- fixed "intermediate instantiation" issue (http://rt.cpan.org/Public/Bug/Display.html?id=37539) +- fixed "iteration over empty object" issue (http://rt.cpan.org/Public/Bug/Display.html?id=37540) +- added and tested MACRO directive +- added PRE_PROCESS and POST_PROCESS configuration options +- added and tested global scope access via GLOBAL modifier (GLOBAL.jQeuery etc) +- added dummy LOCAL modifier, for symmetry +- added "init" method for Jemplate singleton +- added experimental RAW directive (RAW jQuery, equivalent of jQuery = GLOBAL.jQuery) + +VMethods: +- added "list" for lists (http://rt.cpan.org/Public/Bug/Display.html?id=37570) +- added "item" for hashes +- fixed "import" for hashes + +Test suite: +- combined back to a single copy + +Patches: +- Integrated patch from RT#37895 + +version: 0.24_2 +date: Monday June 08 10:37:54 PDT 2009 +changes: +- Fix to get tests working on MSWin32 (rt23883) + --- version: 0.24 date: Fri Sep 19 15:09:35 PDT 2008 diff --git a/MANIFEST b/MANIFEST new file mode 100644 index 0000000..3ae43b0 --- /dev/null +++ b/MANIFEST @@ -0,0 +1,147 @@ +bin/jemplate +bin/README +Changes +ToDo +DESIGN +doc/html/Jemplate.html +doc/Makefile +doc/text/Jemplate.text +examples/ajax/data.json +examples/ajax/index.html +examples/ajax/template/body.html +examples/features/index.html +examples/features/templates/body.html +examples/features/templates/footer.html +examples/features/templates/hacker.html +examples/features/templates/header.html +examples/features/templates/wrapper.html +examples/features/templates/wrapper2.html +examples/hello/index.html +examples/hello/templates/hello.html +examples/index.html +examples/js/ajax.js +examples/js/features.js +examples/js/hello.js +examples/Makefile +inc/Module/Install.pm +inc/Module/Install/Base.pm +inc/Module/Install/Can.pm +inc/Module/Install/Fetch.pm +inc/Module/Install/Include.pm +inc/Module/Install/Makefile.pm +inc/Module/Install/Metadata.pm +inc/Module/Install/TestBase.pm +inc/Module/Install/Win32.pm +inc/Module/Install/WriteAll.pm +inc/Module/Install/Scripts.pm +inc/Spiffy.pm +inc/Test/Base.pm +inc/Test/Base/Filter.pm +inc/Test/Builder.pm +inc/Test/Builder/Module.pm +inc/Test/More.pm +jemplate +lib/Jemplate.pm +lib/Jemplate/Directive.pm +lib/Jemplate/Grammar.pm +lib/Jemplate/Parser.pm +lib/Jemplate/Runtime.pm +lib/Jemplate/Runtime/Compact.pm +LICENSE +Makefile.PL +MANIFEST This list of files +META.yml +README +t/a.js +t/assets/jt/hello +t/assets/jt/a/.hidden/apple +t/assets/jt/a/b/c/.hidden +t/assets/jt/a/b/cherry +t/b.js +t/block.t +t/call.t +t/check.js +t/clear.t +t/for.t +t/get-set.t +t/hello.t +t/if-else.t +t/if-variations.t +t/javascript.t +t/list.t +t/list/bar/one +t/list/bar/two +t/list/foo/one +t/list/foo/two +t/list/one +t/list/three +t/list/two +t/macro.t +t/process.t +t/quoted.t +t/runtime.t +t/stash.t +t/switch.t +t/tags.t +t/test.t +t/TestJemplate.pm +t/throw.t +t/while.t +t/wrapper.t +t/pairs.t +t/9bug/37539-intermediate-instantiation.t +t/9bug/37540-iterate-over-empty-object.t +t/9bug/37895-inconsistent-jemplate-version.t +t/9bug/53967-compiler-double-dot-path-fail.t +t/9bug/53453-make-Jemplate-slice-like-TT-slice.t +t/9bug/53454-array-range-operator.t +t/9bug/37570-list-for-lists.t +t/9bug/43809-capture-implementation.t +t/9bug/56965-DIV-operator-broken.t +tests/Makefile +tests/README +tests/bin/daemon +tests/bin/prepare-var-jt +tests/bin/pull-jemplates +tests/bin/render-template +tests/bin/test-run +tests/config.yaml +tests/jemplate2/greeting/english +tests/jemplate2/greeting/spanish +tests/jemplate2/greetings +tests/jemplate2/hello +tests/js/Subclass.js +tests/js/Test/Base.js +tests/js/Test/Builder.js +tests/js/Test/Harness/Browser.js +tests/js/Test/Harness.js +tests/js/Test/Jemplate.js +tests/js/jemplate_dummy_plugin.js +tests/js/jquery-1.2.3.js +tests/old/Makefile +tests/old/mangler/README +tests/old/mangler/ctx.tst +tests/old/mangler/mangle.pl +tests/old/mangler/test-data.tmpl.tt +tests/t/basics.t.js +tests/t/bugs.t.js +tests/t/default.t.js +tests/t/directives.t.js +tests/t/filters.t.js +tests/t/greetings.t.js +tests/t/hash.t.js +tests/t/hello.t.js +tests/t/join.t.js +tests/t/list.t.js +tests/t/localise.t.js +tests/t/loop.t.js +tests/t/objects.t.js +tests/t/plugins.t.js +tests/t/set.t.js +tests/t/stash.t.js +tests/t/string.t.js +tests/t/test.html +tests/template/index.html +tests/template/test.html +tests/tjs/Makefile +tests/tjs/config.yaml diff --git a/MANIFEST.SKIP b/MANIFEST.SKIP index 4b836f9..1f0d415 100644 --- a/MANIFEST.SKIP +++ b/MANIFEST.SKIP @@ -7,3 +7,8 @@ ^t/Jemplate.js$ ^src/ ^tests/tjs/var/ +^tmp.* +^tests/ +Makefile.old +t[0-9] +Template-TT3 diff --git a/Makefile.PL b/Makefile.PL index a1b54ad..efe038a 100644 --- a/Makefile.PL +++ b/Makefile.PL @@ -18,11 +18,18 @@ all_from 'lib/Jemplate.pm'; #build_requires 'Directory::Scratch'; +if (-e 'inc/.author') { + my $all_from = join '/', 'lib', split m/-/, name . '.pm'; + `perldoc -tF $all_from > README` if ! -e 'README' || (stat $all_from)[9] > (stat 'README')[9]; +} + requires 'Template' => '2.19'; requires 'File::Find::Rule' => '0.30'; use_test_base; +tests_recursive; + no_index directory => 'examples'; clean_files 't/Jemplate.js t/a.js t/b.js t/check.js'; diff --git a/README b/README index c4e7eda..aaa9f3b 100644 --- a/README +++ b/README @@ -1,3 +1,6 @@ +VERSION + Version 0.261 + NAME Jemplate - JavaScript Templating with Template Toolkit @@ -22,6 +25,10 @@ SYNOPSIS Jemplate.process('my-template.html', data, '#some-div'); }); + From the commandline: + + jemplate --runtime --compile path/to/jemplate/directory/ > jemplate.js + DESCRIPTION Jemplate is a templating framework for JavaScript that is built over Perl's Template Toolkit (TT2). @@ -161,12 +168,13 @@ CURRENT SUPPORT * [% LAST %] * [% CLEAR %] * [%# this is a comment %] + * [% MACRO name(param1, param2) BLOCK %] ... [% END %] ALL of the string virtual functions are supported. ALL of the array virtual functions are supported: - ALL of the hash virtual functions are supported (except for import): + ALL of the hash virtual functions are supported: MANY of the standard filters are implemented. @@ -185,8 +193,8 @@ BROWSER SUPPORT All tests run 100% successful in the above browsers. DEVELOPMENT - The bleeding edge code is available via Subversion at - http://svn.jemplate.net/repo/trunk/ + The bleeding edge code is available via Git at + git://github.com/ingydotnet/jemplate.git You can run the runtime tests directly from http://svn.jemplate.net/repo/trunk/tests/run/index.html or from the @@ -229,6 +237,8 @@ AUTHORS Robert Krimen + Nickolay Platonov + COPYRIGHT Copyright (c) 2006-2008. Ingy döt Net. diff --git a/ToDo b/ToDo index 37e246c..8512133 100644 --- a/ToDo +++ b/ToDo @@ -9,6 +9,10 @@ === 0.23 +Add note about commit 3c4d9 referring to wrong rt, should refer to 23883 + +TODO: Does use_test_base not work? make test compains that Test::Base is not installed -rokr + FUTURE: 09:55 < nkuttler_> apparently firefox sets the accept header to request xml rather than json, which obviously is incompatible with later JSON.parse calls. I have added a diff --git a/bin/jemplate b/bin/jemplate index 7ab5414..98ca86a 100755 --- a/bin/jemplate +++ b/bin/jemplate @@ -10300,6 +10300,16 @@ $block ... } +sub _attempt_range_expand_val ($) { + my $val = shift; + return $val unless + my ( $from, $to ) = $val =~ m/\s*\[\s*(\S+)\s*\.\.\s*(\S+)\s*\]/; + + die "Range expansion is current supported for positive/negative integer values only (e.g. [ 1 .. 10 ])\nCannot expand: $val" unless $from =~ m/^-?\d+$/ && $to =~ m/^-?\d+$/; + + return join '', '[', join( ',', $from .. $to ), ']'; +} + sub textblock { my ($class, $text) = @_; @@ -10356,6 +10366,7 @@ sub assign { $var = '[' . join(', ', @$var) . ']'; } } + $val = _attempt_range_expand_val $val; $val .= ', 1' if $default; return "stash.set($var, $val)"; } @@ -10494,6 +10505,8 @@ sub foreach { $loop_restore = 'stash = context.delocalise()'; } + $list = _attempt_range_expand_val $list; + return <[1]) { + $name = $name->[0]; + } + else { + $name = '[' . join(', ', @$name) . ']'; + } + } + + return </g,">");text=text.replace(/"/g,""");return text};proto.filters.html_para=function(text){var lines=text.split(/(?:\r?\n){2,}/);return"

\n"+lines.join("\n

\n\n

\n")+"

\n"};proto.filters.html_break=function(text){return text.replace(/(\r?\n){2,}/g,"$1
$1
$1")};proto.filters.html_line_break=function(text){return text.replace(/(\r?\n)/g,"$1
$1")};proto.filters.uri=function(text){return encodeURIComponent(text)};proto.filters.url=function(text){return encodeURI(text)};proto.filters.indent=function(text,args){var pad=args[0];if(!text){return null}if(typeof pad=="undefined"){pad=4}var finalpad="";if(typeof pad=="number"||String(pad).match(/^\d$/)){for(var i=0;i=0;i=i-size){list.unshift(string.substr(i,size))}if(string.length%size){list.unshift(string.substr(0,string.length%size))}}else{for(i=0;i=0)?1:0};proto.string_functions.size=function(string){return 1};proto.string_functions.split=function(string,re){var regexp=new RegExp(re);var list=string.split(regexp);return list};proto.list_functions={};proto.list_functions["typeof"]=function(list){return"array"};proto.list_functions.list=function(list){return list};proto.list_functions.join=function(list,str){return list.join(str)};proto.list_functions.sort=function(list,key){if(typeof (key)!="undefined"&&key!=""){return list.sort(function(a,b){if(a[key]==b[key]){return 0}else{if(a[key]>b[key]){return 1}else{return -1}}})}return list.sort()};proto.list_functions.nsort=function(list){return list.sort(function(a,b){return(a-b)})};proto.list_functions.grep=function(list,re){var regexp=new RegExp(re);var result=[];for(var i=0;i=0;i--){result.push(list[i])}return result};proto.list_functions.merge=function(list){var result=[];var push_all=function(elem){if(elem instanceof Array){for(var j=0;j0?this.object_keys[index-1]:"";this.next=index0?object[index-1]:"";this.next=index/g,">");text=text.replace(/"/g,""");return text};proto.filters.html_para=function(text){var lines=text.split(/(?:\r?\n){2,}/);return"

\n"+lines.join("\n

\n\n

\n")+"

\n"};proto.filters.html_break=function(text){return text.replace(/(\r?\n){2,}/g,"$1
$1
$1")};proto.filters.html_line_break=function(text){return text.replace(/(\r?\n)/g,"$1
$1")};proto.filters.uri=function(text){return encodeURIComponent(text)};proto.filters.url=function(text){return encodeURI(text)};proto.filters.indent=function(text,args){var pad=args[0];if(!text){return null}if(typeof pad=="undefined"){pad=4}var finalpad="";if(typeof pad=="number"||String(pad).match(/^\d$/)){for(var i=0;i=0;i=i-size){list.unshift(string.substr(i,size))}if(string.length%size){list.unshift(string.substr(0,string.length%size))}}else{for(i=0;i=0)?1:0};proto.string_functions.size=function(string){return 1};proto.string_functions.split=function(string,re){var regexp=new RegExp(re);var list=string.split(regexp);return list};proto.list_functions={};proto.list_functions["typeof"]=function(list){return"array"};proto.list_functions.list=function(list){return list};proto.list_functions.join=function(list,str){return list.join(str)};proto.list_functions.sort=function(list,key){if(typeof (key)!="undefined"&&key!=""){return list.sort(function(a,b){if(a[key]==b[key]){return 0}else{if(a[key]>b[key]){return 1}else{return -1}}})}return list.sort()};proto.list_functions.nsort=function(list){return list.sort(function(a,b){return(a-b)})};proto.list_functions.grep=function(list,re){var regexp=new RegExp(re);var result=[];for(var i=0;i=0;i--){result.push(list[i])}return result};proto.list_functions.merge=function(list){var result=[];var push_all=function(elem){if(elem instanceof Array){for(var j=0;j0?this.object_keys[index-1]:"";this.next=index0?object[index-1]:"";this.next=indexfile->in( $dir ) ) { - # don't include .hidden files - unless ($_ =~ '\/\.') { push(@files, $_); } + if ( m{/\.[^\.]+} ) {} # Skip ".hidden" files or directories + else { + push @files, $_; + } } return @files; } @@ -20017,7 +20104,7 @@ sub make_file_list { foreach my $arg (@args) { unless (-e $arg) { next; } # file exists - unless (-s $arg) { next; } # file size > 0 + unless (-s $arg or -d $arg) { next; } # file size > 0 or directory (for Win platform) if (-d $arg) { foreach my $full ( recurse_dir($arg) ) { diff --git a/js b/js new file mode 120000 index 0000000..e831038 --- /dev/null +++ b/js @@ -0,0 +1 @@ +src \ No newline at end of file diff --git a/lib/Jemplate.pm b/lib/Jemplate.pm index 24958ef..288d9ee 100644 --- a/lib/Jemplate.pm +++ b/lib/Jemplate.pm @@ -5,7 +5,13 @@ use warnings; use Template 2.14; use Getopt::Long; -our $VERSION = '0.23_1'; +=head1 VERSION + +Version 0.261 + +=cut + +our $VERSION = '0.261'; use Jemplate::Parser; @@ -219,8 +225,10 @@ sub recurse_dir { my $dir = shift; my @files; foreach ( File::Find::Rule->file->in( $dir ) ) { - # don't include .hidden files - unless ($_ =~ '\/\.') { push(@files, $_); } + if ( m{/\.[^\.]+} ) {} # Skip ".hidden" files or directories + else { + push @files, $_; + } } return @files; } @@ -232,7 +240,7 @@ sub make_file_list { foreach my $arg (@args) { unless (-e $arg) { next; } # file exists - unless (-s $arg) { next; } # file size > 0 + unless (-s $arg or -d $arg) { next; } # file size > 0 or directory (for Win platform) if (-d $arg) { foreach my $full ( recurse_dir($arg) ) { @@ -422,6 +430,10 @@ or, with jQuery.js: Jemplate.process('my-template.html', data, '#some-div'); }); +From the commandline: + + jemplate --runtime --compile path/to/jemplate/directory/ > jemplate.js + =head1 DESCRIPTION Jemplate is a templating framework for JavaScript that is built over @@ -587,12 +599,13 @@ Jemplate now supports almost all the TT directives, including: * [% LAST %] * [% CLEAR %] * [%# this is a comment %] + * [% MACRO name(param1, param2) BLOCK %] ... [% END %] ALL of the string virtual functions are supported. ALL of the array virtual functions are supported: -ALL of the hash virtual functions are supported (except for import): +ALL of the hash virtual functions are supported: MANY of the standard filters are implemented. @@ -613,8 +626,8 @@ All tests run 100% successful in the above browsers. =head1 DEVELOPMENT -The bleeding edge code is available via Subversion at -http://svn.jemplate.net/repo/trunk/ +The bleeding edge code is available via Git at +git://github.com/ingydotnet/jemplate.git You can run the runtime tests directly from http://svn.jemplate.net/repo/trunk/tests/run/index.html or from the @@ -657,6 +670,8 @@ David A. Coffey Robert Krimen +Nickolay Platonov + =head1 COPYRIGHT Copyright (c) 2006-2008. Ingy döt Net. diff --git a/lib/Jemplate/Directive.pm b/lib/Jemplate/Directive.pm index d0fe4c4..c576b65 100644 --- a/lib/Jemplate/Directive.pm +++ b/lib/Jemplate/Directive.pm @@ -33,6 +33,17 @@ $block ... } +# Try to do 1 .. 10 expansions +sub _attempt_range_expand_val ($) { + my $val = shift; + return $val unless + my ( $from, $to ) = $val =~ m/\s*\[\s*(\S+)\s*\.\.\s*(\S+)\s*\]/; + + die "Range expansion is current supported for positive/negative integer values only (e.g. [ 1 .. 10 ])\nCannot expand: $val" unless $from =~ m/^-?\d+$/ && $to =~ m/^-?\d+$/; + + return join '', '[', join( ',', $from .. $to ), ']'; +} + #------------------------------------------------------------------------ # textblock($text) #------------------------------------------------------------------------ @@ -101,6 +112,7 @@ sub assign { $var = '[' . join(', ', @$var) . ']'; } } + $val = _attempt_range_expand_val $val; $val .= ', 1' if $default; return "stash.set($var, $val)"; } @@ -277,6 +289,8 @@ sub foreach { $loop_restore = 'stash = context.delocalise()'; } + $list = _attempt_range_expand_val $list; + return <[1]) { + $name = $name->[0]; + } + else { + $name = '[' . join(', ', @$name) . ']'; + } + } + + return </g,">");text=text.replace(/"/g,""");return text};proto.filters.html_para=function(text){var lines=text.split(/(?:\r?\n){2,}/);return"

\n"+lines.join("\n

\n\n

\n")+"

\n"};proto.filters.html_break=function(text){return text.replace(/(\r?\n){2,}/g,"$1
$1
$1")};proto.filters.html_line_break=function(text){return text.replace(/(\r?\n)/g,"$1
$1")};proto.filters.uri=function(text){return encodeURIComponent(text)};proto.filters.url=function(text){return encodeURI(text)};proto.filters.indent=function(text,args){var pad=args[0];if(!text){return null}if(typeof pad=="undefined"){pad=4}var finalpad="";if(typeof pad=="number"||String(pad).match(/^\d$/)){for(var i=0;i=0;i=i-size){list.unshift(string.substr(i,size))}if(string.length%size){list.unshift(string.substr(0,string.length%size))}}else{for(i=0;i=0)?1:0};proto.string_functions.size=function(string){return 1};proto.string_functions.split=function(string,re){var regexp=new RegExp(re);var list=string.split(regexp);return list};proto.list_functions={};proto.list_functions["typeof"]=function(list){return"array"};proto.list_functions.list=function(list){return list};proto.list_functions.join=function(list,str){return list.join(str)};proto.list_functions.sort=function(list,key){if(typeof (key)!="undefined"&&key!=""){return list.sort(function(a,b){if(a[key]==b[key]){return 0}else{if(a[key]>b[key]){return 1}else{return -1}}})}return list.sort()};proto.list_functions.nsort=function(list){return list.sort(function(a,b){return(a-b)})};proto.list_functions.grep=function(list,re){var regexp=new RegExp(re);var result=[];for(var i=0;i=0;i--){result.push(list[i])}return result};proto.list_functions.merge=function(list){var result=[];var push_all=function(elem){if(elem instanceof Array){for(var j=0;j0?this.object_keys[index-1]:"";this.next=index0?object[index-1]:"";this.next=index/g,">");text=text.replace(/"/g,""");return text};proto.filters.html_para=function(text){var lines=text.split(/(?:\r?\n){2,}/);return"

\n"+lines.join("\n

\n\n

\n")+"

\n"};proto.filters.html_break=function(text){return text.replace(/(\r?\n){2,}/g,"$1
$1
$1")};proto.filters.html_line_break=function(text){return text.replace(/(\r?\n)/g,"$1
$1")};proto.filters.uri=function(text){return encodeURIComponent(text)};proto.filters.url=function(text){return encodeURI(text)};proto.filters.indent=function(text,args){var pad=args[0];if(!text){return null}if(typeof pad=="undefined"){pad=4}var finalpad="";if(typeof pad=="number"||String(pad).match(/^\d$/)){for(var i=0;i=0;i=i-size){list.unshift(string.substr(i,size))}if(string.length%size){list.unshift(string.substr(0,string.length%size))}}else{for(i=0;i=0)?1:0};proto.string_functions.size=function(string){return 1};proto.string_functions.split=function(string,re){var regexp=new RegExp(re);var list=string.split(regexp);return list};proto.list_functions={};proto.list_functions["typeof"]=function(list){return"array"};proto.list_functions.list=function(list){return list};proto.list_functions.join=function(list,str){return list.join(str)};proto.list_functions.sort=function(list,key){if(typeof (key)!="undefined"&&key!=""){return list.sort(function(a,b){if(a[key]==b[key]){return 0}else{if(a[key]>b[key]){return 1}else{return -1}}})}return list.sort()};proto.list_functions.nsort=function(list){return list.sort(function(a,b){return(a-b)})};proto.list_functions.grep=function(list,re){var regexp=new RegExp(re);var result=[];for(var i=0;i=0;i--){result.push(list[i])}return result};proto.list_functions.merge=function(list){var result=[];var push_all=function(elem){if(elem instanceof Array){for(var j=0;j0?this.object_keys[index-1]:"";this.next=index0?object[index-1]:"";this.next=index/g,">");text=text.replace(/"/g,""");return text};proto.filters.html_para=function(text){var lines=text.split(/(?:\r?\n){2,}/);return"

\n"+lines.join("\n

\n\n

\n")+"

\n"};proto.filters.html_break=function(text){return text.replace(/(\r?\n){2,}/g,"$1
$1
$1")};proto.filters.html_line_break=function(text){return text.replace(/(\r?\n)/g,"$1
$1")};proto.filters.uri=function(text){return encodeURIComponent(text)};proto.filters.url=function(text){return encodeURI(text)};proto.filters.indent=function(text,args){var pad=args[0];if(!text){return null}if(typeof pad=="undefined"){pad=4}var finalpad="";if(typeof pad=="number"||String(pad).match(/^\d$/)){for(var i=0;i=0;i=i-size){list.unshift(string.substr(i,size))}if(string.length%size){list.unshift(string.substr(0,string.length%size))}}else{for(i=0;i=0)?1:0};proto.string_functions.size=function(string){return 1};proto.string_functions.split=function(string,re){var regexp=new RegExp(re);var list=string.split(regexp);return list};proto.list_functions={};proto.list_functions["typeof"]=function(list){return"array"};proto.list_functions.list=function(list){return list};proto.list_functions.join=function(list,str){return list.join(str)};proto.list_functions.sort=function(list,key){if(typeof (key)!="undefined"&&key!=""){return list.sort(function(a,b){if(a[key]==b[key]){return 0}else{if(a[key]>b[key]){return 1}else{return -1}}})}return list.sort()};proto.list_functions.nsort=function(list){return list.sort(function(a,b){return(a-b)})};proto.list_functions.grep=function(list,re){var regexp=new RegExp(re);var result=[];for(var i=0;i=0;i--){result.push(list[i])}return result};proto.list_functions.merge=function(list){var result=[];var push_all=function(elem){if(elem instanceof Array){for(var j=0;j0?this.object_keys[index-1]:"";this.next=index0?object[index-1]:"";this.next=index/g,">");text=text.replace(/"/g,""");return text};proto.filters.html_para=function(text){var lines=text.split(/(?:\r?\n){2,}/);return"

\n"+lines.join("\n

\n\n

\n")+"

\n"};proto.filters.html_break=function(text){return text.replace(/(\r?\n){2,}/g,"$1
$1
$1")};proto.filters.html_line_break=function(text){return text.replace(/(\r?\n)/g,"$1
$1")};proto.filters.uri=function(text){return encodeURIComponent(text)};proto.filters.url=function(text){return encodeURI(text)};proto.filters.indent=function(text,args){var pad=args[0];if(!text){return null}if(typeof pad=="undefined"){pad=4}var finalpad="";if(typeof pad=="number"||String(pad).match(/^\d$/)){for(var i=0;i=0;i=i-size){list.unshift(string.substr(i,size))}if(string.length%size){list.unshift(string.substr(0,string.length%size))}}else{for(i=0;i=0)?1:0};proto.string_functions.size=function(string){return 1};proto.string_functions.split=function(string,re){var regexp=new RegExp(re);var list=string.split(regexp);return list};proto.list_functions={};proto.list_functions["typeof"]=function(list){return"array"};proto.list_functions.list=function(list){return list};proto.list_functions.join=function(list,str){return list.join(str)};proto.list_functions.sort=function(list,key){if(typeof (key)!="undefined"&&key!=""){return list.sort(function(a,b){if(a[key]==b[key]){return 0}else{if(a[key]>b[key]){return 1}else{return -1}}})}return list.sort()};proto.list_functions.nsort=function(list){return list.sort(function(a,b){return(a-b)})};proto.list_functions.grep=function(list,re){var regexp=new RegExp(re);var result=[];for(var i=0;i=0;i--){result.push(list[i])}return result};proto.list_functions.merge=function(list){var result=[];var push_all=function(elem){if(elem instanceof Array){for(var j=0;j0?this.object_keys[index-1]:"";this.next=index0?object[index-1]:"";this.next=index "JavaScript::V8x::TestMoreish not available" unless eval { require JavaScript::V8x::TestMoreish }; +} + +plan qw/no_plan/; + +use Jemplate; +use Jemplate::Runtime; + +use JavaScript::V8x::TestMoreish; + +my $jemplate = Jemplate->new; +my @js; + +push @js, $jemplate->compile_template_content( <<_END_, 't0' ); +[% BLOCK t1 %] +[% a.b.c = 1 %] +[% a.b.c %] +[% END %] +_END_ + +test_js_eval( Jemplate::Runtime->kernel ); +test_js_eval( join "\n", @js, "1;" ); +test_js <<'_END_'; +result = Jemplate.process( 't1', {} ) +areEqual( result, 1 ); +_END_ diff --git a/t/9bug/37540-iterate-over-empty-object.t b/t/9bug/37540-iterate-over-empty-object.t new file mode 100644 index 0000000..e53d287 --- /dev/null +++ b/t/9bug/37540-iterate-over-empty-object.t @@ -0,0 +1,35 @@ +#!/usr/bin/env perl + +use strict; +use warnings; + +use Test::More; + +BEGIN { + plan skip_all => "JavaScript::V8x::TestMoreish not available" unless eval { require JavaScript::V8x::TestMoreish }; +} + +plan qw/no_plan/; + +use Jemplate; +use Jemplate::Runtime; + +use JavaScript::V8x::TestMoreish; + +my $jemplate = Jemplate->new; +my @js; + +push @js, $jemplate->compile_template_content( <<_END_, 't0' ); +[% BLOCK t1 %] +[% FOREACH a = empty %] +[% END %] +1 +[% END %] +_END_ + +test_js_eval( Jemplate::Runtime->kernel ); +test_js_eval( join "\n", @js, "1;" ); +test_js <<'_END_'; +result = Jemplate.process( 't1', { empty: [] } ) +areEqual( result, 1 ); +_END_ diff --git a/t/9bug/37570-list-for-lists.t b/t/9bug/37570-list-for-lists.t new file mode 100644 index 0000000..bc1fdd3 --- /dev/null +++ b/t/9bug/37570-list-for-lists.t @@ -0,0 +1,32 @@ +#!/usr/bin/env perl + +use strict; +use warnings; + +use Test::More; + +BEGIN { + plan skip_all => "JavaScript::V8x::TestMoreish not available" unless eval { require JavaScript::V8x::TestMoreish }; +} + +plan qw/no_plan/; + +use Jemplate; +use Jemplate::Runtime; + +use JavaScript::V8x::TestMoreish; + +my $jemplate = Jemplate->new; +my @js; + +push @js, $jemplate->compile_template_content( <<_END_, 't0' ); +[% BLOCK t1 %][% apple %] [% apple.list %][% END %] +_END_ + +test_js_eval( Jemplate::Runtime->kernel ); +test_js_eval( join "\n", @js, "1;" ); +test_js <<'_END_'; +apple = [ 1, 2, 3, 4, 5 ] +result = Jemplate.process( 't1', { apple: apple } ) +areEqual( result, "1,2,3,4,5 1,2,3,4,5" ); +_END_ diff --git a/t/9bug/37895-inconsistent-jemplate-version.t b/t/9bug/37895-inconsistent-jemplate-version.t new file mode 100644 index 0000000..598f7ac --- /dev/null +++ b/t/9bug/37895-inconsistent-jemplate-version.t @@ -0,0 +1,12 @@ +#!/usr/bin/env perl + +use strict; +use warnings; + +use Test::More; + +plan qw/no_plan/; + +system( $^X, 'jemplate' ); + +ok( ! $? ); diff --git a/t/9bug/43809-capture-implementation.t b/t/9bug/43809-capture-implementation.t new file mode 100644 index 0000000..037ecba --- /dev/null +++ b/t/9bug/43809-capture-implementation.t @@ -0,0 +1,34 @@ +#!/usr/bin/env perl + +use strict; +use warnings; + +use Test::More; + +BEGIN { + plan skip_all => "JavaScript::V8x::TestMoreish not available" unless eval { require JavaScript::V8x::TestMoreish }; +} + +plan qw/no_plan/; + +use Jemplate; +use Jemplate::Runtime; + +use JavaScript::V8x::TestMoreish; + +my $jemplate = Jemplate->new; +my @js; + +push @js, $jemplate->compile_template_content( <<_END_, 't0' ); +[% BLOCK t1 %][% result = BLOCK %]Hello, World![% END %][% result %][% END %] +_END_ + +test_js_eval( Jemplate::Runtime->kernel ); +test_js_eval( join "\n", @js, "1;" ); +test_js <<'_END_'; +var result + +result = Jemplate.process( 't1', { } ) +areEqual( result, "Hello, World!" ) +_END_ + diff --git a/t/9bug/53453-make-Jemplate-slice-like-TT-slice.t b/t/9bug/53453-make-Jemplate-slice-like-TT-slice.t new file mode 100644 index 0000000..b0203db --- /dev/null +++ b/t/9bug/53453-make-Jemplate-slice-like-TT-slice.t @@ -0,0 +1,51 @@ +#!/usr/bin/env perl + +use strict; +use warnings; + +use Test::More; + +BEGIN { + plan skip_all => "JavaScript::V8x::TestMoreish not available" unless eval { require JavaScript::V8x::TestMoreish }; +} + +plan qw/no_plan/; + +use Jemplate; +use Jemplate::Runtime; + +use JavaScript::V8x::TestMoreish; + +my $jemplate = Jemplate->new; +my @js; + +push @js, $jemplate->compile_template_content( <<_END_, 't0' ); +[% BLOCK t1 %][% apple.slice( 0, 2 ).join(' - ') %][% END %] +[% BLOCK t2 %][% apple.slice( -3, -1 ).join(' - ') %][% END %] +[% BLOCK t3 %][% apple.slice( -3, -2 ).join(' - ') %][% END %] +[% BLOCK t4 %][% apple.slice( 3, -2 ).join(' - ') %][% END %] +[% BLOCK t5 %][% apple.slice( 3, -1 ).join(' - ') %][% END %] +_END_ + +test_js_eval( Jemplate::Runtime->kernel ); +test_js_eval( join "\n", @js, "1;" ); +test_js <<'_END_'; +var result +var apple = [ 1, 2, 3, 4, 5, 6, 7 ] + +result = Jemplate.process( 't1', { apple: apple } ) +areEqual( result, "1 - 2 - 3" ); + +result = Jemplate.process( 't2', { apple: apple } ) +areEqual( result, "5 - 6 - 7" ); + +result = Jemplate.process( 't3', { apple: apple } ) +areEqual( result, "5 - 6" ); + +result = Jemplate.process( 't4', { apple: apple } ) +areEqual( result, "4 - 5 - 6" ); + +result = Jemplate.process( 't5', { apple: apple } ) +areEqual( result, "4 - 5 - 6 - 7" ); +_END_ + diff --git a/t/9bug/53454-array-range-operator.t b/t/9bug/53454-array-range-operator.t new file mode 100644 index 0000000..b494ae3 --- /dev/null +++ b/t/9bug/53454-array-range-operator.t @@ -0,0 +1,52 @@ +#!/usr/bin/env perl + +use strict; +use warnings; + +use Test::More; + +BEGIN { + plan skip_all => "JavaScript::V8x::TestMoreish not available" unless eval { require JavaScript::V8x::TestMoreish }; +} + +plan qw/no_plan/; + +use Jemplate; +use Jemplate::Runtime; + +use JavaScript::V8x::TestMoreish; + +my $jemplate = Jemplate->new; +my @js; + +push @js, $jemplate->compile_template_content( <<_END_, 't0' ); +[% BLOCK t1 %][% list = [ 1 .. 10 ] %][% list.join(', ') %][% END %] +[% BLOCK t2 %][% FOREACH ii = [ 1 .. 4 ] %][% ii %] [% END %][% END %] +[% BLOCK t3 %][% FOREACH ii = [ -1 .. -4 ] %][% ii %] [% END %][% END %] +[% BLOCK t4 %][% FOREACH ii = [ -4 .. -1 ] %][% ii %] [% END %][% END %] +_END_ + +eval { +$jemplate->compile_template_content( <<_END_, 't0' ); +[% BLOCK t1 %][% broken = [ 1 .. end ] %][% list.join(', ') %][% END %] +_END_ +}; +like $@, qr{Range expansion is current supported for positive/negative integer values only}; + +test_js_eval( Jemplate::Runtime->kernel ); +test_js_eval( join "\n", @js, "1;" ); +test_js <<'_END_'; +var result + +result = Jemplate.process( 't1', { } ) +areEqual( result, "1, 2, 3, 4, 5, 6, 7, 8, 9, 10" ); + +result = Jemplate.process( 't2', { } ) +areEqual( result, "1 2 3 4 " ); + +result = Jemplate.process( 't3', { } ) +areEqual( result, "" ); + +result = Jemplate.process( 't4', { } ) +areEqual( result, "-4 -3 -2 -1 " ); +_END_ diff --git a/t/9bug/53967-compiler-double-dot-path-fail.t b/t/9bug/53967-compiler-double-dot-path-fail.t new file mode 100644 index 0000000..ea3e509 --- /dev/null +++ b/t/9bug/53967-compiler-double-dot-path-fail.t @@ -0,0 +1,12 @@ +#!/usr/bin/env perl + +use strict; +use warnings; + +use Test::More; + +plan qw/no_plan/; + +use Jemplate; + +is( scalar Jemplate::recurse_dir( 't/../t/assets/jt/a' ), 1, 'Only find one file, the rest should be hidden' ); diff --git a/t/9bug/56965-DIV-operator-broken.t b/t/9bug/56965-DIV-operator-broken.t new file mode 100644 index 0000000..715ed27 --- /dev/null +++ b/t/9bug/56965-DIV-operator-broken.t @@ -0,0 +1,36 @@ +#!/usr/bin/env perl + +use strict; +use warnings; + +use Test::More; + +BEGIN { + plan skip_all => "JavaScript::V8x::TestMoreish not available" unless eval { require JavaScript::V8x::TestMoreish }; +} + +plan qw/no_plan/; + +use Jemplate; +use Jemplate::Runtime; + +use JavaScript::V8x::TestMoreish; + +my $jemplate = Jemplate->new; +my @js; + +push @js, $jemplate->compile_template_content( <<_END_, 't0' ); +[% BLOCK t1 %][% 3 DIV 2 %][% END %] +[% BLOCK t2 %][% 4 DIV 2 %][% END %] +[% BLOCK t3 %][% 5 DIV 2 %][% END %] +_END_ + +test_js_eval( Jemplate::Runtime->kernel ); +test_js_eval( join "\n", @js, "1;" ); +test_js <<'_END_'; + +areEqual( Jemplate.process( 't1' ), 1 ); +areEqual( Jemplate.process( 't2' ), 2 ); +areEqual( Jemplate.process( 't3' ), 2 ); + +_END_ diff --git a/t/assets/jt/a/.hidden/apple b/t/assets/jt/a/.hidden/apple new file mode 100644 index 0000000..e69de29 diff --git a/t/assets/jt/a/b/c/.hidden b/t/assets/jt/a/b/c/.hidden new file mode 100644 index 0000000..e69de29 diff --git a/t/assets/jt/a/b/cherry b/t/assets/jt/a/b/cherry new file mode 100644 index 0000000..00b9489 --- /dev/null +++ b/t/assets/jt/a/b/cherry @@ -0,0 +1,3 @@ +[% BLOCK cherry %] +apple +[% END %] diff --git a/t/pairs.t b/t/pairs.t new file mode 100644 index 0000000..3bcb3a1 --- /dev/null +++ b/t/pairs.t @@ -0,0 +1,38 @@ +use Test::More; + +BEGIN { + plan skip_all => "JavaScript::V8x::TestMoreish not available" unless eval { require JavaScript::V8x::TestMoreish }; +} + +plan qw/no_plan/; + +use Jemplate; +use Jemplate::Runtime; + +use JavaScript::V8x::TestMoreish; + +my $jemplate = Jemplate->new; +my @templates; +push @templates, $jemplate->compile_template_content( <<_END_, 't0' ); +Hello, World. +_END_ +push @templates, $jemplate->compile_template_content( <<_END_, 't1' ); +[% FOREACH pair = hash.pairs %] +[% pair.key %] = [% pair.value %] +[% END %] +_END_ +push @templates, $jemplate->compile_template_content( <<_END_, 't2' ); +[% FOREACH key = hash.keys %] +[% key %] = [% hash.\$key %] +[% END %] +_END_ + +test_js_eval( Jemplate::Runtime->kernel ); +test_js_eval( join "\n", @templates, "1;" ); + +test_js <<'_END_'; +result = Jemplate.process( 't1', { hash: { c: 1, a: 2, b: 3 } } ); +like( result, /a = 2\s+b = 3\s+c = 1/ ) +_END_ + +1; diff --git a/tests/index.html b/tests/index.html index efa87f7..e69de29 100644 --- a/tests/index.html +++ b/tests/index.html @@ -1,32 +0,0 @@ - - - Jemplate Testing - - - - - - - diff --git a/tests/t/list.t.js b/tests/t/list.t.js index dfbaee4..7084c7b 100644 --- a/tests/t/list.t.js +++ b/tests/t/list.t.js @@ -19,7 +19,7 @@ list.html [% a1.max() %]+[% a1.size() %] [% SET a2 = a1.reverse -%] [% a2.join('^') %] -[% a2.slice(1, 3).join('*') %] +[% a2.slice(1, 2).join('*') %] [% SET a3 = [ 5, 9, 'x', 17, 9, 33, 12, 'x', 5] -%] [% a3.unique().join(',') %] [% a1.unshift('zero').sort().join('!') %] diff --git a/tests/t/string.t.js b/tests/t/string.t.js index 146a850..c5023a2 100644 --- a/tests/t/string.t.js +++ b/tests/t/string.t.js @@ -63,7 +63,7 @@ Hi --- jemplate string_match.html [% SET a = 'aaa12aaa34aaa56' -%] -[% a.match('\\\d\\\d','g').join(' ') %] +[% a.match('\\\d\\\d').join(' ') %] --- output 12 34 56 @@ -81,8 +81,8 @@ aaa --- jemplate string_replace.html [% SET a = 'aaa12aaa34aaa56' -%] -[% a.replace('\\\d\\\d', 'bb', 'g') %] -[% a.replace('\\\d\\\d', '', 'g') %] +[% a.replace('\\\d\\\d', 'bb') %] +[% a.replace('\\\d\\\d') %] --- output aaabbaaabbaaabb aaaaaaaaa