Data-JavaScript-1.13/0000700001753500001450000000000011051045771014671 5ustar belg4mitmit00000000000000Data-JavaScript-1.13/Makefile.PL0000600001753500001450000000040610336433516016650 0ustar belg4mitmit00000000000000use ExtUtils::MakeMaker; # See lib/ExtUtils/MakeMaker.pm for details of how to influence # the contents of the Makefile that is written. WriteMakefile( 'NAME' => 'Data::JavaScript', 'VERSION_FROM' => 'JavaScript.pm', # finds $VERSION ); Data-JavaScript-1.13/example.pl0000600001753500001450000000071710336433516016673 0ustar belg4mitmit00000000000000use Data::JavaScript; $hash = {'string' => 'Joseph', 'array' => [qw(0 1 2 3 4 5 6 7 8 9 a b c d e f)], 'capitals' => {'Sverige' => 'Stockholm', 'Norge' => 'Oslo', 'Danmark' => 'Koebenhavn'}, 'and' => [[0, 0], [0, 1]], 'or' => [[0, 1], [1, 1]], 'xor' => [[0, 1], [1, 0]]}; $hash->{'ref'} = $hash; print scalar(jsdump("facts", $hash, 31.4e-1)); Data-JavaScript-1.13/README0000600001753500001450000000331310336433516015556 0ustar belg4mitmit00000000000000Dump perl structures to JavaScript code. example.pl: use Data::JavaScript; $hash = {'string' => 'Joseph', 'array' => [qw(0 1 2 3 4 5 6 7 8 9 a b c d e f)], 'capitals' => {'Sverige' => 'Stockholm', 'Norge' => 'Oslo', 'Danmark' => 'Koebenhavn'}, 'and' => [[0, 0], [0, 1]], 'or' => [[0, 1], [1, 1]], 'xor' => [[0, 1], [1, 0]]}; $hash->{'ref'} = $hash; print scalar(jsdump("facts", $hash, 31.4e-1)); Output: var facts = new Array; facts[0] = new Object; facts[0].xor = new Array; facts[0].xor[0] = new Array; facts[0].xor[0][0] = 0; facts[0].xor[0][1] = 1; facts[0].xor[1] = new Array; facts[0].xor[1][0] = 1; facts[0].xor[1][1] = 0; facts[0].or = new Array; facts[0].or[0] = new Array; facts[0].or[0][0] = 0; facts[0].or[0][1] = 1; facts[0].or[1] = new Array; facts[0].or[1][0] = 1; facts[0].or[1][1] = 1; facts[0].capitals = new Object; facts[0].capitals.Norge = 'Oslo'; facts[0].capitals.Sverige = 'Stockholm'; facts[0].capitals.Danmark = 'Koebenhavn'; facts[0].and = new Array; facts[0].and[0] = new Array; facts[0].and[0][0] = 0; facts[0].and[0][1] = 0; facts[0].and[1] = new Array; facts[0].and[1][0] = 0; facts[0].and[1][1] = 1; facts[0].ref = facts[0]; facts[0].array = new Array; facts[0].array[0] = 0; facts[0].array[1] = 1; facts[0].array[2] = 2; facts[0].array[3] = 3; facts[0].array[4] = 4; facts[0].array[5] = 5; facts[0].array[6] = 6; facts[0].array[7] = 7; facts[0].array[8] = 8; facts[0].array[9] = 9; facts[0].array[10] = 'a'; facts[0].array[11] = 'b'; facts[0].array[12] = 'c'; facts[0].array[13] = 'd'; facts[0].array[14] = 'e'; facts[0].array[15] = 'f'; facts[0].string = 'Joseph'; facts[1] = 3.14; Data-JavaScript-1.13/t/0000700001753500001450000000000011051045765015137 5ustar belg4mitmit00000000000000Data-JavaScript-1.13/t/3-undef.t0000600001753500001450000000120510336433516016565 0ustar belg4mitmit00000000000000BEGIN { $| = 1; print "1..3\n"; } use Data::JavaScript {UNDEF=>0}; #Test undef value overloading $_ = join('', jsdump('foo', [1,undef,1])); print 'not ' unless $_ eq 'var foo = new Array;foo[0] = 1;foo[1] = undefined;foo[2] = 1;'; print "ok 1 #$_\n"; $_ = join('', jsdump('bar', [1,undef,1], 'null')); print 'not ' unless $_ eq 'var bar = new Array;bar[0] = 1;bar[1] = null;bar[2] = 1;'; print "ok 2 #$_\n"; #Test hashes $_ = join('', jsdump('qux', {color=>'monkey', age=>2, eyes=>'blue'})); print 'not ' unless $_ eq 'var qux = new Object;qux["age"] = 2;qux["color"] = "monkey";qux["eyes"] = "blue";'; print "ok 3 #$_\n"; Data-JavaScript-1.13/t/3-js12.t0000600001753500001450000000171510336433516016251 0ustar belg4mitmit00000000000000#Lame switch because old Test::Harness does not support trailing test count BEGIN { $| = 1; print "1..4\n" } use Data::JavaScript {JS=>1.2}; #No Unicode, undef yields empty strings #Test undef default $_ = join('', jsdump('foo', [1,undef,1])); print 'not ' unless $_ eq "var foo = new Array;foo[0] = 1;foo[1] = '';foo[2] = 1;"; print "ok 1 #$_\n"; #Test alphanumeric string output: quoting, ASCII/ANSI escaping, Unicode $_ = join('', jsdump("ANSI", "M\xF6tley Cr\xFce")); print 'not ' unless $_ eq 'var ANSI = "M\xF6tley Cr\xFCe";'; print "ok 2 #$_\n"; if( $] >= 5.006 ){ $_ = join('', jsdump("unicode", "Euros (\x{20ac}) aren't Ecus (\x{20a0})")); print 'not ' unless $_ eq q(var unicode = "Euros (\xE2\x82\xAC) aren't Ecus (\xE2\x82\xA0)";); print "ok 3 #$_\n"; } else{ print "ok 3 # Skipped: No real Unicode\n"; } $_ = join('', jsdump('thang', qq(' "\n\\\xa0) )); print 'not ' unless $_ eq q(var thang = "'\t\"\n\\\\\xA0";); print "ok 4 #$_\n"; Data-JavaScript-1.13/t/4-escape.t0000600001753500001450000000142711050453715016730 0ustar belg4mitmit00000000000000BEGIN { $| = 1; print "1..6\n"; } use Data::JavaScript; #Test numbers: negative, real, engineering, octal/zipcode $_ = join('', jsdump('ixi', -1)); print 'not ' unless $_ eq 'var ixi = -1;'; print "ok 1 #$_\n"; $_ = join('', jsdump('pi', 3.14159)); print 'not ' unless $_ eq 'var pi = 3.14159;'; print "ok 2 #$_\n"; $_ = join('', jsdump('c', '3E8')); print 'not ' unless $_ eq 'var c = "3E8";'; print "ok 3 #$_\n"; $_ = join('', jsdump('zipcode', '02139')); print 'not ' unless $_ eq 'var zipcode = "02139";'; print "ok 4 #$_\n"; $_ = join('', jsdump('hex', '0xdeadbeef')); print 'not ' unless $_ eq 'var hex = "0xdeadbeef";'; print "ok 5 #$_\n"; $_ = join('', jsdump("IEsux", "DoS!")); print 'not ' unless $_ eq 'var IEsux = "\x3C\x2Fscript\x3EDoS!";'; print "ok 6 #$_\n"; Data-JavaScript-1.13/t/1-load.t0000600001753500001450000000021310336433516016377 0ustar belg4mitmit00000000000000BEGIN { $| = 1; print "1..1\n"; } END {print "not ok 1\n" unless $loaded;} use Data::JavaScript; $loaded = 1; print "ok 1 #Loads fine\n"; Data-JavaScript-1.13/t/3-noArgs.t0000600001753500001450000000152411050426154016713 0ustar belg4mitmit00000000000000BEGIN { $| = 1; $] < 5.007 ? do{ print "1..0 # Skipped: No real Unicode\n"; exit} : print "1..4\n"; } use Data::JavaScript; #Test undef default $_ = join('', jsdump('foo', [1,undef,1])); print 'not ' unless $_ eq 'var foo = new Array;foo[0] = 1;foo[1] = undefined;foo[2] = 1;'; print "ok 1 #$_\n"; #Test alphanumeric string output: quoting, ASCII/ANSI escaping, Unicode $_ = join('', jsdump("ANSI", "M\xF6tley Cr\xFce")); print 'not ' unless $_ eq 'var ANSI = "M\xF6tley Cr\xFCe";'; print "ok 2 #$_\n"; $_ = join('', jsdump("unicode", "Euros (\x{20ac}) aren't Ecus (\x{20a0})")); print 'not ' unless $_ eq q(var unicode = "Euros (\u20AC) aren't Ecus (\u20A0)";); print "ok 3 #$_\n"; $_ = join('', jsdump("Cherokee", "\x{13E3}\x{13E3}\x{13E3}")); print 'not ' unless $_ eq q(var Cherokee = "\u13E3\u13E3\u13E3";); print "ok 4 #$_\n"; Data-JavaScript-1.13/t/2-import.t0000600001753500001450000000077711051045557017011 0ustar belg4mitmit00000000000000BEGIN { $| = 1; print "1..3\n"; } #Test imports { package Fred; use Data::JavaScript qw(:all); $_ = eval{ __quotemeta("Hello World\n") }; print 'not ' unless $_ eq 'Hello World\n'; print "ok 1 #$_\n"; } { package Barney; use Data::JavaScript qw(jsdump); $_ = eval{ __quotemeta("Hello World\n") } || ''; print 'not ' if $_ eq 'Hello World\n'; print "ok 2 #$_\n"; $_ = join('', jsdump('narf', 'Troz!')); print 'not ' unless $_ eq 'var narf = "Troz!";'; print "ok 3 #$_\n"; } Data-JavaScript-1.13/CHANGES0000600001753500001450000000540211051044304015656 0ustar belg4mitmit00000000000000Revision history for Perl extension Data::JavaScript. 1.13 Thu Aug 14 11:01:10 EDT 2008 - Finished implementing import - "Simplified"/unified __quotemeta code forks 1.12 Wed Aug 13 22:48:12 EDT 2008 - Some minor refactoring, including the removal of a dependency on Exporter - Fixed a misnumbered test in 1_11, which was intended to be a development release. - Escape based on reports of certain stupid browsers ceasing to parse JavaScript upon encountering this string, even in strings. - Added explicit license 1_11 Tue Nov 15 14:30:22 EST 2005 - Touched up documentation - Fixed syntax errors for hash key names that are also JS keywords Reported by Kevin J. of Activestate - Hash keys are now dumped in alphabetical order, this makes code easier to debug (as suggested by Scott Wessels) and is necessary for thorough testing. - Special characters tab, newline, carriage return, ", and \ are now escaped in place instead of as hex: \t, \n, \r, \", \\ 1.10 Sun Nov 13 03:50 EST 2005 - Touched up documentation - Explicitly requires Perl 5 - Previously undocumented, "private", quotemeta is now __quotemeta though you may still import and use it - Defaults to JavaScript1.3 compatible code with Unicode and undefined support, specifc JS=>1.2 on the use line for backwards compatbility. - Removed unnecessary evaluation of numeric elements, this fixes octal interpretation of zipcodes, etc. Still, zipcodes such as 02137 would be *correctly* evaluated by the client as 1119. However, in keeping with the principle of least surprise any purely numeric string with a leading zero will be treated as a string and quoted. If you really meant to send a literal octal value, you can always eval the var Similarly, engineering and hex notations are passed through to strings as well. Thanks for reports from Javier Arturo Rodriguez, Marius Feraru, Joseph Annino, Alan Fairless, Kevin J. - quotemeta has been completely rewritten with support for Unicode Thanks for reports from Slaven Rezic, Marius Feraru, Sean Burke 1.08 Thu Feb 13 09:04:27 EST 2003 - Touched up the documentation 1.07 Sat Feb 8 12:40:16 EST 2003 - Added means to control how undef is dumped, suggested by Slaven Rezic In doing so I have removed the undocumented feature that a list was silently transformed into a list reference. - Touched up the documentation **** Ariel Brosh passed away a few months ago. I volunteered to maintain this module as it was the inspiration for my own Data::JavaScript::LiteObject http://use.perl.org/article.pl?sid=03/01/12/226258&mode=nested **** 1.04 Thu Jul 19 2001 - Fixed quoting back, thanks to Garick Hamlin 1.00 Mon Jun 12 21:03:29 2000 - original version; created by h2xs 1.19 Data-JavaScript-1.13/JavaScript.pm0000600001753500001450000001671311051045325017302 0ustar belg4mitmit00000000000000package Data::JavaScript; require 5; use vars qw(@EXPORT @EXPORT_OK %OPT $VERSION); %OPT = (JS=>1.3); $VERSION = 1.13; @EXPORT = qw(jsdump hjsdump); @EXPORT_OK = '__quotemeta'; use strict; require Encode unless $] < 5.007; sub import{ my $package = shift; foreach( @_ ){ if(ref($_) eq 'HASH'){ $OPT{JS} = $$_{JS} if exists($$_{JS}); $OPT{UNDEF} = $$_{UNDEF} if exists($$_{UNDEF}); } } $OPT{UNDEF} ||= $OPT{JS} > 1.2 ? 'undefined' : q(''); #use (); #imports nothing, as package is not supplied if( defined $package ){ no strict 'refs'; #Remove options hash my @import = grep { ! length ref } @_; if( scalar @import ){ if( grep {/^:all$/} @import ){ @import = (@EXPORT, @EXPORT_OK) } else{ #only user-specfied subset of @EXPORT, @EXPORT_OK my $q = qr/@{[join('|', @EXPORT, @EXPORT_OK)]}/; @import = grep { $_ =~ /$q/ } @import; } } else{ @import = @EXPORT; } my $caller = caller; for my $func (@import) { *{"$caller\::$func"} = \&$func; } } } sub hjsdump { my @res = (qq('); wantarray ? @res : join("\n", @res, ""); } sub jsdump { my $sym = shift; return "var $sym;\n" unless (@_); my $elem = shift; my $undef = shift; my %dict; my @res = __jsdump($sym, $elem, \%dict, $undef); $res[0] = "var " . $res[0]; wantarray ? @res : join("\n", @res, ""); } my $QMver; if( $] < 5.007 ){ $QMver=<<'EO5'; s<([^ \x21-\x5B\x5D-\x7E]+)>{sprintf(join('', '\x%02X' x length$1), unpack'C*',$1)}ge; EO5 } else{ $QMver=<<'EO58'; if( $OPT{JS} >= 1.3 && Encode::is_utf8($_) ){ s<([\x{0080}-\x{fffd}]+)>{sprintf '\u%0*v4X', '\u', $1}ge; } { use bytes; s<((?:[^ \x21-\x7E]|(?:\\(?!u)))+)>{sprintf '\x%0*v2X', '\x', $1}ge; } EO58 } eval 'sub __quotemeta {local $_ = shift;' . $QMver . <<'EOQM'; #This is kind of ugly/inconsistent output for munged UTF-8 #tr won't work because we need the escaped \ for JS output s/\\x09/\\t/g; s/\\x0A/\\n/g; s/\\x0D/\\r/g; s/"/\\"/g; s/\\x5C/\\\\/g; #Escape for stupid browsers that stop parsing s%%\\x3C\\x2Fscript\\x3E%g; return $_; } EOQM sub __jsdump { my ($sym, $elem, $dict, $undef) = @_; my $ref; unless( $ref = ref($elem) ){ unless( defined($elem) ){ return "$sym = @{[defined($undef) ? $undef : $OPT{UNDEF}]};"; } #Translated from $Regexp::Common::RE{num}{real} if( $elem =~ /^[+-]?(?:(?=\d|\.)\d*(?:\.\d{0,})?)$/ ){ # (?:[eE][+-]?\d+)? return qq($sym = "$elem";) if $elem =~ /^0\d+$/; return "$sym = $elem;"; } #Fall-back to quoted string return qq($sym = ") . __quotemeta($elem) . '";'; } #Circular references if ($dict->{$elem}) { return "$sym = " . $dict->{$elem} . ";"; } $dict->{$elem} = $sym; #isa over ref in case we're given objects if( $ref eq 'ARRAY' || UNIVERSAL::isa($elem, 'ARRAY') ){ my @list = ("$sym = new Array;"); my $n = 0; foreach (@$elem) { my $newsym = "$sym\[$n]"; push(@list, __jsdump($newsym, $_, $dict, $undef)); $n++; } return @list; } elsif( $ref eq 'HASH' || UNIVERSAL::isa($elem, 'HASH') ){ my @list = ("$sym = new Object;"); my ($k, $old_k, $v); foreach $k (sort keys %$elem) { $k = __quotemeta($old_k=$k); my $newsym = qq($sym\["$k"]); push(@list, __jsdump($newsym, $elem->{$old_k}, $dict, $undef)); } return @list; } else{ return "//Unknown reference: $sym=$ref"; } } 1; __END__ =head1 NAME Data::JavaScript - Dump perl data structures into JavaScript code =head1 SYNOPSIS use Data::JavaScript; # Use defaults @code = jsdump('my_array', $array_ref); # Return array for formatting $code = jsdump('my_object', $hash_ref); # Return convenient string $html = hjsdump('my_stuff', $reference); # Convenience wrapper =head1 DESCRIPTION This module is mainly intended for CGI programming, when a perl script generates a page with client side JavaScript code that needs access to structures created on the server. It works by creating one line of JavaScript code per datum. Therefore, structures cannot be created anonymously and need to be assigned to variables. However, this format enables dumping large structures. The module can output code for different versions of JavaScript. It currently supports 1.1, 1.3 and you specify the version on the C line like so: use Data::JavaScript {JS=>1.3}; # The new default use Data::JavaScript {JS=>1.1}; # Old (pre module v1.10) format JavaScript 1.3 contains support for UTF-8 and a native C datatype. Earlier versions support neither, and will default to an empty string C<''> for undefined values. You may define your own default--for either version--at compile time by supplying the default value on the C line: use Data::JavaScript {JS=>1.1, UNDEF=>'null'}; Other useful values might be C<0>, C, or C. =head1 EXPORT In addition, althought the module no longer uses Exporter, it heeds its import conventions; C), C<()>, etc. =over =item jsdump('name', \$reference, [$undef]); The first argument is required, the name of JavaScript object to create. The second argument is required, a hashref or arrayref. Structures can be nested, circular referrencing is supported (experimentally). The third argument is optional, a scalar whose value is to be used en lieu of undefined values when dumping a structure. When called in list context, the function returns a list of lines. In scalar context, it returns a string. =item hjsdump('name', \$reference, [$undef]); hjsdump is identical to jsdump except that it wraps the content in script tags. =back =head1 EXPORTABLE =over =item __quotemeta($str) This function escapes non-printable and Unicode characters (where possible) to promote playing nice with others. =back =head1 CAVEATS Previously, the module eval'd any data it received that looked like a number; read: real, hexadecimal, octal, or engineering notations. It now passes all non-decimal values through as strings. You will need to C on the client or server side if you wish to use other notations as numbers. This is meant to protect people who store ZIP codes with leading 0's. Unicode support requires perl 5.8 or later. Older perls will gleefully escape the non-printable portions of any UTF-8 they are fed, likely munging it in the process as far as JavaScript is concerned. If this turns out to be a problem and there is sufficient interest it may be possible to hack-in UTF-8 escaping for older perls. =head1 LICENSE =over =item * Thou shalt not claim ownership of unmodified materials. =item * Thou shalt not claim whole ownership of modified materials. =item * Thou shalt grant the indemnity of the provider of materials. =item * Thou shalt use and dispense freely without other restrictions. =back Or if you truly insist, you may use and distribute this under ther terms of Perl itself (GPL and/or Artistic License). =head1 SEE ALSO L, L, L =head1 AUTHOR Maintained by Jerrad Pierce Created by Ariel Brosh . Inspired by WDDX.pm JavaScript support. =cut Data-JavaScript-1.13/TODO0000600001753500001450000000217011051043025015351 0ustar belg4mitmit00000000000000ECMAScript and charset support for hjsdump Encoding, escape [^[:print:]] Doesn't seem to include Unicode in 5.8.4... Numbers Infinity NaN const (check attribute?) Lightweight (object initializer) output for 1.2+ JavaScript 1.2 and later support a compact object notation known as object literals. We probably want to walk depth first if using this notation. HASH = {key:val} ARRAY= [0, 1, 2] See nuclear wessels, wait for Anon/Lite merger because it requires inline dumping More robust var naming (get & use perl names?) Unify: How to scan & determine which format is best? constructor, flat, literal, class/prototype Data::JavaScript Data::JavaScript::LiteObject allow objects to be stuffed into an array and use the key names as var names? to what end, would have to know var names Data::JavaScript::Anon (Perl : anonymous :: JS : literal) jsdump takes undef as name worries too much about valid numbers but not strings, validation belongs elsewhere Template::Plugin::JavaScript __quotemeta JSON why oh why is it a top-level name? didn't he look around first? XML feed, Atom feed? Data-JavaScript-1.13/MANIFEST0000600001753500001450000000021311051044040016004 0ustar belg4mitmit00000000000000CHANGES MANIFEST README TODO JavaScript.pm Makefile.PL t/1-load.t t/2-import.t t/3-js12.t t/3-noArgs.t t/3-undef.t t/4-escape.t example.pl