Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/perl -w
- #!perl.exe -w
- ##-----------------------------------#
- ## JuntBuild #
- ## Simple script to automate the #
- ## process of minifying/combining #
- ## multiple assets, organizing #
- ## the project tree, and #
- ## refactoring as necessary. #
- ###-----------------------------------#
- ## Native Modules
- use File::Copy;
- use File::Find;
- ## Third Party Modules
- use XML::LibXML;
- use JavaScript::Minifier;
- use CSS::Minifier;
- # <Print Functions>
- ## Prints error messages and exits.
- sub PrintError {
- my($error, $errcode) = @_;
- print "Error: $error\n\n";
- PrintUsage();
- exit($errcode);
- }
- ## Prints the script usage.
- sub PrintUsage {
- print "Usage:\n$^X $0 [filename]\n\tfilename\tOptional argument for specifying the xml build file.\n\t\t\tIf none specified, will use build.xml\n";
- }
- # </Print Functions>
- # <Compressors>
- ## Javascript Compressor
- sub JsMinCompress {
- my $file = $_[0];
- my $sRet = "";
- if (-s $file) {
- open(INFILE, '<' . $file);
- $sRet = JavaScript::Minifier::minify(input => *INFILE);
- close(INFILE);
- }
- return $sRet;
- }
- ## CSS Compressor
- sub CssMinCompress {
- my $file = $_[0];
- my $sRet = "";
- if (-s $file) {
- open(INFILE, '<' . $file);
- $sRet = CSS::Minifier::minify(input => *INFILE);
- close(INFILE);
- }
- return $sRet;
- }
- ## Png Compressor
- sub PngCrushCompress {
- my($file,$output) = @_;
- if (-s $file) {
- if(-e $output) {
- unlink($output);
- }
- my $prog = "utils\\pngcrush.exe -brute \"" . $file . "\" \"" . $output . "\"";
- $prog = `$prog`;
- if(!-e $output) {
- copy($file, $output);
- }
- }
- }
- #</Compressors>
- # Recursively create directories
- sub CreateFolders {
- my $path = $_[0];
- my @folders = split(m!/!, $path);
- pop(@folders);
- my $buffer = "";
- my $iswitch = 0;
- foreach $folder (@folders) {
- if($folder ne "") {
- if ($iswitch == 0) {
- $buffer = $folder;
- $iswitch = 1;
- } else {
- $buffer = $buffer . "/" . $folder;
- }
- if(!-d $buffer) {
- mkdir($buffer);
- }
- }
- }
- }
- # <Entry Handlers>
- ## <Group Handlers>
- ### Javascript Groups
- sub JavascriptGroup {
- # Get arguments.
- my ($root, $files_ref, $output, $compress) = @_;
- my @files = @{$files_ref};
- my $buffer = "/* Packaged by JuntBuild v1.0 */";
- # Print output file.
- if ($output =~ m!^(?:.*?)[/\\]([^/:*?<>"|]*?\.?[a-z\-_]{0,8})$!i) {
- my $tmpout = $1;
- print "----------\n$tmpout\n----------\n";
- }
- # Cycle through files.
- foreach my $file (@files) {
- my $nfile = $root . $file->getAttribute("path");
- print "Compressing $nfile...\n";
- if ($compress eq "jsmin") {
- # Compress with JSMin
- $buffer = $buffer . "\n" . JsMinCompress($nfile);
- } elsif ($compress eq "none") {
- open(INFILE, '<' . $nfile) or PrintError("Could not open file $file.\n$!\n", 1);
- my $sContents = do{local $/; <INFILE>};
- close(INFILE);
- $buffer = $buffer . "\n" . $sContents;
- }
- }
- # Write output to file.
- CreateFolders($output);
- open(OUTFILE, '>' . $output);
- print OUTFILE $buffer;
- close(OUTFILE);
- }
- ### CSS Groups
- sub CssGroup {
- # Get arguments.
- my ($root, $files_ref, $output, $compress) = @_;
- my @files = @{$files_ref};
- my $buffer = "/* Packaged by JuntBuild v1.0 */";
- # Print output file.
- if ($output =~ m!^(?:.*?)[/\\]([^/:*?<>"|]*?\.?[a-z\-_]{0,8})$!i) {
- my $tmpout = $1;
- print "----------\n$tmpout\n----------\n";
- }
- # Cycle through files.
- foreach my $file (@files) {
- my $nfile = $root . $file->getAttribute("path");
- print "Compressing $nfile...\n";
- if ($compress eq "cssmin") {
- # Compress with JSMin
- $buffer = $buffer . "\n" . CssMinCompress($nfile);
- } elsif ($compress eq "none") {
- open(INFILE, '<' . $nfile) or PrintError("Could not open file $file.\n$!\n", 1);
- my $sContents = do{local $/; <INFILE>};
- close(INFILE);
- $buffer = $buffer . "\n" . $sContents;
- }
- }
- # Write output to file.
- CreateFolders($output);
- open(OUTFILE, '>' . $output);
- print OUTFILE $buffer;
- close(OUTFILE);
- }
- ## </Group Handlers>
- ## <Single Handlers>
- ### Javascript Single
- sub JavascriptSingle {
- my($file, $output, $compress) = @_;
- if ($compress eq "jsmin") {
- # Compress with JSMin
- CreateFolders($output);
- open(OUTFILE, '>' . $output);
- print OUTFILE JsMinCompress($file);
- close(OUTFILE);
- } elsif ($compress eq "none") {
- if(-e $output) {
- unlink($output);
- }
- copy($file, $output);
- }
- }
- ### Css Single
- sub CssSingle {
- my($file, $output, $compress) = @_;
- CreateFolders($output);
- if ($compress eq "cssmin") {
- # Compress with JSMin
- open(OUTFILE, '>' . $output);
- print OUTFILE CssMinCompress($file);
- close(OUTFILE);
- } elsif ($compress eq "none") {
- if(-e $output) {
- unlink($output);
- }
- copy($file, $output);
- }
- }
- ### Png Single
- sub PngSingle {
- my($file, $output, $compress) = @_;
- CreateFolders($output);
- if($compress eq "pngcrush") {
- # Compress with pngcrush.
- PngCrushCompress($file,$output);
- } elsif ($compress eq "none") {
- if(-e $output) {
- unlink($output);
- }
- copy($file, $output);
- }
- }
- ### Generic File Single
- sub FileSingle {
- my($file, $output, $compress) = @_;
- CreateFolders($output);
- if(-e $output) {
- unlink($output);
- }
- copy($file, $output);
- }
- ## </Single Handlers>
- ## <Container Handlers>
- ### Html Container
- sub HtmlContainer {
- my($file, $output, $scripts_ref, $styles_ref) = @_;
- my @styles = @{$styles_ref};
- my @scripts = @{$scripts_ref};
- # Open the original file.
- open(INFILE, '<' . $file) or PrintError("Could not open file $file.\n$!\n", 1);
- my $sContents = do{local $/; <INFILE>};
- close(INFILE);
- # Remove all script and style references.
- $sContents =~ s!(<script.*?>.*?</script>)|(<link.*?type="text/css".*?>)!!img;
- # Cycle through styles
- foreach my $style (@styles) {
- my $style_path = $style->getAttribute("path");
- $sContents =~ s!^(.*?)</head>(.*?)$!\t\t<link href=\"$style_path\" rel=\"stylesheet\" type=\"text/css\" />\n$1</head>$2!img;
- }
- # Cycle through scripts
- foreach my $script (@scripts) {
- my $script_path = $script->getAttribute("path");
- my $script_type = $script->getAttribute("type");
- $sContents =~ s!^(.*?)</head>(.*?)$!\t\t<script type=\"$script_type\" src=\"$script_path\"></script>\n$1</head>$2!img;
- }
- # Open the output file.
- CreateFolders($output);
- open(OUTFILE, '>' . $output) or PrintError("Could not open/create file $output.\n$!\n", 1);
- print OUTFILE $sContents;
- close(OUTFILE);
- }
- ## </Container Handlers>
- ## <Refactor Handlers>
- ## Text Refactoring
- my $val_old; my $val_new; my $find_scope;
- sub textRefacFound {
- $file = $_;
- if(($File::Find::name =~ m/$find_scope/im)&&(!-d $File::Find::name)) {
- print "Refactoring $_...\n";
- } else {
- return;
- }
- # Open the original file.
- open(INFILE, '<' . $file) or PrintError("Could not open file $file.\n$!\n", 1);
- my $sContents = do{local $/; <INFILE>};
- close(INFILE);
- # Make changes.
- $sContents =~ s/\Q$val_old\E/$val_new/img;
- # Reopen and apply changes.
- open(OUTFILE, '>' . $file) or PrintError("Could not open/create file $file.\n$!\n", 1);
- print OUTFILE $sContents;
- close(OUTFILE);
- }
- sub TextRefactor {
- my($scope, $output, $old, $new) = @_;
- # Fix regex.
- $scope = quotemeta($scope);
- $charLast = substr $scope, -2, 2;
- if($charLast ne "\\\$") {
- $scope = $scope . "\$";
- }
- $charFirst = substr $scope, 0, 1;
- if($charFirst ne "/") {
- $scope = "/" . $scope;
- }
- # Check for wildcard.
- $scope =~ s/\\\*/[^\/:*?<>"|]*?/img;
- # Set the global variables.
- $val_old = $old; $val_new = $new;
- $find_scope = $scope;
- # Search
- find(\&textRefacFound, $output);
- }
- ##</Refactor Handlers>
- # </Entry Handlers>
- # Script Entry Point.
- # Header
- print "=============\n+ JuntBuild\n- Version 1.0\n=============\n";
- # Argument handling
- $numArgs = $#ARGV + 1;
- $sFile = "build.xml";
- if ($numArgs == 0) {
- if (!(-s $sFile)||!(-r $sFile)) {
- PrintError("File $sFile did not exist or was empty.", 1);
- }
- } elsif ($numArgs == 1) {
- if ((-s $ARGV[0])&&(-r $ARGV[0])) {
- $sFile = $ARGV[0];
- } else {
- $sFile = $ARGV[0];
- PrintError("File $sFile did not exist or was empty.", 1);
- }
- }
- # Parse xml document.
- print "Parsing $sFile..\n";
- my $xmlParser = XML::LibXML->new();
- my $xmlTree = $xmlParser->parse_file($sFile);
- my $xmlRoot = $xmlTree->getDocumentElement;
- # Get output path.
- @BuildConfig = $xmlRoot->getElementsByTagName("buildconfig");
- @pathRoot = $BuildConfig[0]->getElementsByTagName("root");
- $pathRoot = $pathRoot[0]->getAttribute("path");
- @pathOut = $BuildConfig[0]->getElementsByTagName("output");
- $pathOut = $pathOut[0]->getAttribute("path");
- # Fix output path
- $charLast = substr $pathOut, -1, 1;
- if($charLast eq "/") {
- chop($pathOut);
- }
- # Create output directory if it doesn't exist.
- if(!-d $pathOut) {
- # Directory does not exist.
- print "Creating $pathOut..";
- mkdir($pathOut) or PrintError("Could not create output folder.\n$!", 3);
- }
- # Add / to output path
- $pathOut = $pathOut . "/";
- # Actions to do beforehand.
- print "\n==============================\nProcessing Pre-Build Actions..\n==============================\n";
- my @Pres = $xmlRoot->getElementsByTagName("pre-actions");
- if (@Pres) {
- @Pres = $Pres[0]->getElementsByTagName("pre");
- foreach $pre (@Pres) {
- my $action = $pre->getAttribute("action");
- print "Processing pre-action: $action\n";
- $trash = `$action`;
- }
- }
- # Cycle through groups.
- print "\n===================\nProcessing Groups..\n===================\n";
- my @BuildGroups = $xmlRoot->getElementsByTagName("buildgroups");
- @BuildGroups = $BuildGroups[0]->getElementsByTagName("group");
- foreach $group (@BuildGroups) {
- # Get output path.
- my @buildOut = $group->getElementsByTagName("output");
- $buildOut = $buildOut[0]->getAttribute("path");
- $buildOut = $pathOut . $buildOut;
- # Group files
- my @files = $group->getElementsByTagName("files");
- @files = $files[0]->getElementsByTagName("file");
- # Compression method
- my $buildCompress = $group->getAttribute("compress");
- # Work on type.
- my $attr = $group->getAttribute("type");
- if ($attr eq "js") {
- # Javascript Group
- JavascriptGroup($pathRoot, \@files, $buildOut, $buildCompress);
- } elsif ($attr eq "css") {
- # CSS Group
- CssGroup($pathRoot, \@files, $buildOut, $buildCompress);
- }
- }
- # Cycle through singles.
- print "\n====================\nProcessing Singles..\n====================\n";
- my @Singles = $xmlRoot->getElementsByTagName("singles");
- @Singles = $Singles[0]->getElementsByTagName("single");
- foreach $single (@Singles) {
- # Get output path.
- my @buildOut = $single->getElementsByTagName("output");
- $buildOut = $buildOut[0]->getAttribute("path");
- print "Generating $buildOut..\n";
- $buildOut = $pathOut . $buildOut;
- # Single file
- my @file = $single->getElementsByTagName("file");
- $file = $pathRoot . $file[0]->getAttribute("path");
- # Compression method
- my $buildCompress = $single->getAttribute("compress");
- # Work on type.
- my $attr = $single->getAttribute("type");
- if ($attr eq "js") {
- # Javascript Single
- JavascriptSingle($file, $buildOut, $buildCompress);
- } elsif ($attr eq "css") {
- # CSS Single
- CssSingle($file, $buildOut, $buildCompress);
- } elsif ($attr eq "png") {
- # CSS Single
- PngSingle($file, $buildOut, $buildCompress);
- } elsif ($attr eq "file") {
- # CSS Single
- FileSingle($file, $buildOut, $buildCompress);
- }
- }
- # Cycle through containers.
- print "\n======================\nProcessing Containers..\n======================\n";
- my @Containers = $xmlRoot->getElementsByTagName("containers");
- @Containers = $Containers[0]->getElementsByTagName("container");
- foreach $container (@Containers) {
- # Get output path.
- my @buildOut = $container->getElementsByTagName("output");
- $buildOut = $buildOut[0]->getAttribute("path");
- print "Generating container: $buildOut..\n";
- $buildOut = $pathOut . $buildOut;
- # Single file
- my $file = $pathRoot . $container->getAttribute("file");
- # Stylesheets
- my @stylesheets = $container->getElementsByTagName("stylesheets");
- @stylesheets = $stylesheets[0]->getElementsByTagName("stylesheet");
- # Scripts
- my @scripts = $container->getElementsByTagName("scripts");
- @scripts = $scripts[0]->getElementsByTagName("script");
- # Work on type.
- my $attr = $container->getAttribute("type");
- if ($attr eq "html") {
- # Html Container
- HtmlContainer($file, $buildOut, \@scripts, \@stylesheets);
- }
- }
- # Cycle through containers.
- print "\n======================\nProcessing Refactors..\n======================\n";
- my @Refactors = $xmlRoot->getElementsByTagName("refactors");
- @Refactors = $Refactors[0]->getElementsByTagName("refactor");
- foreach $refactor (@Refactors) {
- # Single file
- my $scope = $refactor->getAttribute("scope");
- # Get output path.
- @Values = $refactor->getElementsByTagName("value");
- my $valOld = $Values[0]->getAttribute("old");
- my $valNew = $Values[0]->getAttribute("new");
- # Work on type.
- my $attr = $refactor->getAttribute("type");
- if ($attr eq "text") {
- # Text refactoring
- TextRefactor($scope, $pathOut, $valOld, $valNew);
- }
- }
- # Actions to do afterwards.
- print "\n===============================\nProcessing Post-Build Actions..\n===============================\n";
- my @Posts = $xmlRoot->getElementsByTagName("post-actions");
- if (@Posts) {
- @Posts = $Posts[0]->getElementsByTagName("post");
- foreach $post (@Posts) {
- my $action = $post->getAttribute("action");
- print "Processing post-action: $action\n";
- $trash = `$action`;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement