#!/usr/bin/perl -w #################### main pod documentation begin ################### =head1 NAME Zymonic - Static Content Combining script =head1 SYNOPSIS =head1 DESCRIPTION This script will take the request XSL file and combined it with its included/imported files into a single XSL file. It will also combine all JS required by the XSL and zymonic into a single, minified JS file. =head1 SUPPORT As in the license, Zymonic is provided without warranty or support unless purchased separately, however... If you email zymonic-support@zednax.com your issue will be noted and may receive a response. For security issues, please contact zymonic-security@zednax.com and someone will respond within 8 working hours. =head1 AUTHOR Alex Masidlover et al. CPAN ID: MODAUTHOR Zednax Limited alex.masidlover@zednax.com http://www.zednax.com =head1 COPYRIGHT This program is free software licensed under the... Zymonic Public License 1.0 The full text of the license can be found in the LICENSE file included with this module. Other licenses may be acceptable if including parts of Zymonic in larger projects, please contact Zednax for details. =head1 SEE ALSO perl(1). =cut #################### main pod documentation end ################### use Zymonic::Client; use Cwd qw(cwd abs_path); use Data::Dumper; use File::Basename; use File::Slurp; use Getopt::Long; use JavaScript::Minifier qw(minify); # Globals my $saxon_bin = '/usr/local/bin/saxon'; my $no_min_suffix = 'nomin'; my $zymonic_dir; my %js_ordering = ( 'default' => 10, 'MiscFunctions.js' => 99 ); # Call main() main(); exit(0); #################### subroutine header begin #################### =head2 main Usage : main(); Purpose : Main loop for handling DDI/DDC files Returns : nothing Argument : nothing Throws : nothing Comment : nothing See Also : =cut #################### subroutine header end ################### sub main { # Deal with options my ( $xsl_file, $xsl_out_file, $js_out_file, $use_no_min_js ); usage() if ( !GetOptions( 'xsl_file=s' => \$xsl_file, 'xsl_out_file=s' => \$xsl_out_file, 'js_out_file=s' => \$js_out_file, 'zymonic_dir=s' => \$zymonic_dir, 'use_no_min_js' => \$use_no_min_js ) ); # Require all args usage('xsl_file') unless $xsl_file; usage('xsl_out_file') unless $xsl_out_file; usage('js_out_file') unless $js_out_file; usage('zymonic_dir') unless $zymonic_dir; $zymonic_dir = abs_path($zymonic_dir); # generate the combined xsl my $xsl = get_combined_xsl($xsl_file); # get all js needed for xsl, plus the default, preserver order from xsl my @xsl_js = get_xsl_js($xsl); my @default_js = get_default_js( \@xsl_js ); my @js = ( @xsl_js, @default_js ); # make sure misc functions is at the end (otherwise get IE JS error) my @misc_functions_js = grep { $_ =~ /MiscFunctions/ } @js; @js = grep { $_ !~ /MiscFunctions/ } @js; push( @js, @misc_functions_js ); # combine and write out js combined_js_file( $js_out_file, \@js ); print "Generated JS $js_out_file\n"; # put the combined js into xsl file and write it out $xsl = set_xsl_js( $xsl, ( $use_no_min_js ? "$js_out_file.$no_min_suffix" : $js_out_file ) ); combined_xsl_file( $xsl_out_file, $xsl ); print "Generated XSL $xsl_out_file\n"; print "Verifying XSL\n"; verify_xsl($xsl_out_file); print "Done.\n"; } #################### subroutine header begin #################### =head2 get_combined_xsl Usage : get_combined_xsl($xsl); Purpose : Combines all imported/inluded XSL into a single XSL fragment. Returns : Fragment of XSL containing all imported/included XSL from the incoming file. Argument : XSL file to start from Throws : nothing Comment : See Also : =cut #################### subroutine header end ################### sub get_combined_xsl { my $xsl = shift; die "Unable to find XSL: $xsl" unless $xsl && -f $xsl; my $combiner = 'static_content_combiner.xsl'; die "Unable to find combiner XSL: $combiner (perhaps you are not in the web server dir?)" unless -f $combiner; my $cwd = cwd(); my ( $xsl_name, $xsl_path, $xsl_suffix ) = fileparse($xsl); chdir $xsl_path or die "Cannot cd to $xsl_path - $!\n"; # use saxon to generate the combined XSL my $tmp_xsl_1 = 'tmp1-' . time() . '.xsl'; my $tmp_xsl_2 = 'tmp2-' . time() . '.xsl'; system("$saxon_bin $xsl_name $cwd/$combiner > $tmp_xsl_1"); system("$saxon_bin $tmp_xsl_1 $cwd/$combiner > $tmp_xsl_2"); my $combined_xsl = `$saxon_bin $tmp_xsl_2 $cwd/$combiner`; unlink $tmp_xsl_1, $tmp_xsl_2; chdir $cwd or die "Cannot cd back to $cwd - $!\n"; return $combined_xsl; } #################### subroutine header begin #################### =head2 get_xsl_js Usage : get_xsl_js($xsl); Purpose : Returns a list of all the JS included by the xsl. Returns : List of js files. Argument : XSL contents to search through Throws : nothing Comment : See Also : =cut #################### subroutine header end ################### sub get_xsl_js { my $xsl = shift; return () unless $xsl; # find all js hrefs my @js = map { ".$_" } grep { $_ =~ /\.js$/ } $xsl =~ m/ 'quiet' ) or die "Unable to read JS file: $_ (perhaps you are not in the web server dir?) - $!\n"; $combined_js .= "\n/*\n * START\n * $_\n */\n\n$js\n\n/*\n * END\n * $_\n */\n\n"; } @{$js_list}; write_file( "$js_file.$no_min_suffix", { err_mode => 'quiet' }, $combined_js ) or die "Unable to write JS file: $js_file.$no_min_suffix - $!\n"; my $minified_js = minify( input => $combined_js ); write_file( $js_file, { err_mode => 'quiet' }, $minified_js ) or die "Unable to write JS file: $js_file - $!\n"; chmod 0755, "$js_file.$no_min_suffix", $js_file; } #################### subroutine header begin #################### =head2 combined_xsl_file Usage : combined_xsl_file($xsl_file, $xsl); Purpose : Writes the XSL to file. Returns : nothing Argument : Name of the combined file, and xsl to write to it. Throws : nothing Comment : See Also : File::Slurp =cut #################### subroutine header end ################### sub combined_xsl_file { my $xsl_file = shift; my $xsl = shift; write_file( $xsl_file, { err_mode => 'quiet' }, $xsl ) or die "Unable to write XSL file: $xsl_file - $!\n"; chmod 0755, $xsl_file; } #################### subroutine header begin #################### =head2 set_xsl_js Usage : get_xsl_js($xsl, $js); Purpose : Remove existing JS from xsl and replaces it with incoming one. Returns : XSL with onlly incoming js Argument : XSL contents to alter, js file to use Throws : nothing Comment : See Also : =cut #################### subroutine header end ################### sub set_xsl_js { my $xsl = shift; my $js_file = shift; # remove all js scripts $xsl =~ s/.*|<\/script>).*//g; # remove script includes $xsl =~ s/.*?<\/xsl:for-each>//msg; # add single script for incoming js $xsl =~ s/<\/head>/