JavaScript, Json minimizator

jsmin – is a JavaScript, Json minimizator which removes comments and unnecessary whitespace from JS, JSON files

6 Commits   0 Branches   1 Tag
     5         kx #!/usr/bin/perl -w
     5         kx 
     5         kx use strict;
     5         kx use Getopt::Long qw(:config no_ignore_case bundling);
     5         kx use File::Basename;
     5         kx use utf8;
     5         kx 
     5         kx my $ifname = '';
     5         kx my $ofname = '';
     5         kx my $stdio  = '';
     5         kx my $last   = '';
     5         kx 
     5         kx my $version = "@VERSION@";
     5         kx 
     5         kx my ( $if, $of );
     5         kx 
     5         kx sub usage
     5         kx {
     5         kx   my $p = basename( $0 );
     5         kx 
     5         kx   print <<EOF;
     5         kx 
     5         kx Usage: $p [options] [input_file_name]
     5         kx Options:
     5         kx    --output | -o       - output file name;
     5         kx    --version | -v      - print version numver;
     5         kx    --help | -h | -?    - print this message;
     5         kx    --                  - an option terminator;
     5         kx    -                   - use std{io|out} instead of files.
     5         kx 
     5         kx Examples:
     5         kx 
     5         kx   Input file is 'full.json', output file is 'min.json':
     5         kx 
     5         kx     \$ $p -o min.json full.json
     5         kx 
     5         kx   Input file is 'STDIN', output file is 'min.json':
     5         kx 
     5         kx     \$ $p -o min.json -
     5         kx 
     5         kx     Please note that to terminate your input by keyboard you have to use
     5         kx     <Ctrl>+d combination;
     5         kx 
     5         kx   Input file is 'full.json', output file is 'STDOUT':
     5         kx 
     5         kx     \$ $p -- full.json
     5         kx 
     5         kx   Use stdin, stdout:
     5         kx 
     5         kx     \$ $p - < full.json > min.json
     5         kx 
     5         kx Enjoj.
     5         kx 
     5         kx EOF
     5         kx   exit;
     5         kx }
     5         kx 
     5         kx sub version
     5         kx {
     5         kx   print <<EOF;
     5         kx $version
     5         kx EOF
     5         kx   exit;
     5         kx }
     5         kx 
     5         kx 
     5         kx my $a = '';
     5         kx my $b = '';
     5         kx my $x = '';
     5         kx my $y = '';
     5         kx 
     5         kx my $lookahead = 0;
     5         kx 
     5         kx 
     5         kx sub get
     5         kx {
     5         kx   my $c = 0;
     5         kx 
     5         kx   $c = $lookahead;
     5         kx   $lookahead = 0;
     5         kx 
     5         kx   if( $c == 0 )
     5         kx   {
     5         kx     if( ! eof( $if ) )
     5         kx     {
     5         kx       my $ch = getc( $if );
     5         kx       $c = ord( $ch );
     5         kx     }
     5         kx     else
     5         kx     {
     5         kx       $c = 0;
     5         kx     }
     5         kx   }
     5         kx   if( $c >= ord(" ") || $c == ord("\n") || $c == 0 )
     5         kx   {
     5         kx     return $c;
     5         kx   }
     5         kx   if( $c == ord("\r") )
     5         kx   {
     5         kx     return ord("\n");
     5         kx   }
     5         kx   return ord(" ");
     5         kx }
     5         kx 
     5         kx sub peek
     5         kx {
     5         kx   $lookahead = get();
     5         kx   return $lookahead;
     5         kx }
     5         kx 
     5         kx sub next_cn
     5         kx {
     5         kx   my $c = get();
     5         kx 
     5         kx   if( $c == ord("/") )
     5         kx   {
     5         kx     my $char = chr( peek() );
     5         kx     if( $char eq "/" )
     5         kx     {
     5         kx       for(;;) { $c = get(); if( $c <= ord("\n") ) { last; } }
     5         kx     }
     5         kx     elsif( $char eq "*" )
     5         kx     {
     5         kx       get();
     5         kx       while( $c != ord(" ") )
     5         kx       {
     5         kx         my $cn = get();
     5         kx         if( chr( $cn ) eq "*" )
     5         kx         {
     5         kx           if( chr( peek() ) eq "/" ) { get(); $c = ord(" "); }
     5         kx         }
     5         kx         elsif( $cn == 0 )
     5         kx         {
     5         kx           print STDERR "Unterminated comment.\n"; exit 1;
     5         kx         }
     5         kx       }
     5         kx     }
     5         kx   }
     5         kx   $y = $x;
     5         kx   $x = chr( $c );
     5         kx 
     5         kx   return $c;
     5         kx }
     5         kx 
     5         kx sub action
     5         kx {
     5         kx   my $d = $_[0];
     5         kx 
     5         kx   if( $d == 1 )
     5         kx   {
     5         kx     print $of $a;
     5         kx     if(
     5         kx         ( $y eq "\n" || $y eq " " ) &&
     5         kx         ( $a eq "+" || $a eq "-" || $a eq "*" || $a eq "/" ) &&
     5         kx         ( $b eq "+" || $b eq "-" || $b eq "*" || $b eq "/" )
     5         kx       )
     5         kx     {
     5         kx       print $of $y;
     5         kx     }
     5         kx     $d = 2;
     5         kx   }
     5         kx 
     5         kx   if( $d == 2 )
     5         kx   {
     5         kx     $a = $b;
     5         kx     if( $a eq "\'" || $a eq "\"" || $a eq "`" )
     5         kx     {
     5         kx       for(;;)
     5         kx       {
     5         kx         my $c;
     5         kx 
     5         kx         print $of $a;
     5         kx         $c = get(); $a = chr( $c );
     5         kx         if( $a eq $b ) { last; }
     5         kx         if( $a eq "\\" )
     5         kx         {
     5         kx           print $of $a;
     5         kx           $c = get(); $a = chr( $c );
     5         kx         }
     5         kx         if( $c == 0 )
     5         kx         {
     5         kx           print STDERR "Unterminated string literal.\n"; exit 1;
     5         kx         }
     5         kx       }
     5         kx     }
     5         kx     $d = 3;
     5         kx   }
     5         kx 
     5         kx   if( $d == 3 )
     5         kx   {
     5         kx     $b = chr( next_cn() );
     5         kx     if( $b eq "/" &&
     5         kx         ( $a eq "(" || $a eq "," || $a eq "=" || $a eq ":" ||
     5         kx           $a eq "[" || $a eq "!" || $a eq "&" || $a eq "|" ||
     5         kx           $a eq "?" || $a eq "+" || $a eq "-" || $a eq "~" ||
     5         kx           $a eq "*" || $a eq "/" || $a eq "{" || $a eq "\n"
     5         kx         )
     5         kx       )
     5         kx     {
     5         kx       print $of $a;
     5         kx       if( $a eq "/" || $a eq "*" ) { print $of " "; }
     5         kx       print $of $b;
     5         kx       for(;;)
     5         kx       {
     5         kx         my $c;
     5         kx 
     5         kx         $c = get(); $a = chr( $c );
     5         kx         if( $a eq "[" )
     5         kx         {
     5         kx           for(;;)
     5         kx           {
     5         kx             print $of $a;
     5         kx             $c = get(); $a = chr( $c );
     5         kx             if( $a eq "]" )
     5         kx             {
     5         kx               last;
     5         kx             }
     5         kx             if( $a eq "\\" )
     5         kx             {
     5         kx               print $of $a;
     5         kx               $c = get(); $a = chr( $c );
     5         kx             }
     5         kx             if( $c == 0 )
     5         kx             {
     5         kx               print STDERR "Unterminated regular expression literal.\n"; exit 1;
     5         kx             }
     5         kx           }
     5         kx         }
     5         kx         elsif( $a eq "/" )
     5         kx         {
     5         kx           my $ch = chr( peek() );
     5         kx           if( $ch eq "/" || $ch eq "*" )
     5         kx           {
     5         kx             print STDERR "Unterminated regular expression literal.\n"; exit 1;
     5         kx           }
     5         kx           last;
     5         kx         }
     5         kx         elsif( $a eq "\\" )
     5         kx         {
     5         kx           print $of $a;
     5         kx           $c = get(); $a = chr( $c );
     5         kx         }
     5         kx         elsif( $c == 0 )
     5         kx         {
     5         kx           print STDERR "Unterminated regular expression literal.\n"; exit 1;
     5         kx         }
     5         kx         print $of $a;
     5         kx       }
     5         kx       $b = chr( next_cn() );
     5         kx     }
     5         kx   }
     5         kx }
     5         kx 
     5         kx 
     5         kx sub isalnum
     5         kx {
     5         kx   my $ch = $_[0];
     5         kx 
     5         kx   if( ($ch ge "a" && $ch le "z") || ($ch ge "0" && $ch le "9") ||
     5         kx       ($ch ge "A" && $ch le "Z") ||  $ch eq "_" || $ch eq "\$" ||
     5         kx       $ch eq "\\" || $ch gt "~"
     5         kx     ) { return 1; } else { return 0; }
     5         kx }
     5         kx 
     5         kx 
     5         kx sub jsmin
     5         kx {
     5         kx   if( peek() == 0xEF ) { get(); get(); get(); }
     5         kx   $a = "\n";
     5         kx   action( 3 );
     5         kx   while( $a ne "" && $a ne "\0" )
     5         kx   {
     5         kx     if( $a eq " " )
     5         kx     {
     5         kx       action( isalnum( $b ) ? 1 : 2 );
     5         kx     }
     5         kx     elsif( $a eq "\n" )
     5         kx     {
     5         kx       if( $b eq "{" || $b eq "[" || $b eq "(" || $b eq "+" ||
     5         kx           $b eq "-" || $b eq "!" || $b eq "~"
     5         kx         )
     5         kx       {
     5         kx         action( 1 );
     5         kx       }
     5         kx       elsif( $b eq " " )
     5         kx       {
     5         kx         action( 3 );
     5         kx       }
     5         kx       else
     5         kx       {
     5         kx         action( isalnum( $b ) ? 1 : 2 );
     5         kx       }
     5         kx     }
     5         kx     else
     5         kx     {
     5         kx       if( $b eq " " )
     5         kx       {
     5         kx         action( isalnum( $a ) ? 1 : 3 );
     5         kx       }
     5         kx       elsif( $b eq "\n" )
     5         kx       {
     5         kx         if( $a eq "}" || $a eq "]" || $a eq ")" || $a eq "+" ||
     5         kx             $a eq "-" || $a eq "\"" || $a eq "\'" || $a eq "`"
     5         kx           )
     5         kx         {
     5         kx           action( 1 );
     5         kx         }
     5         kx         else
     5         kx         {
     5         kx           action( isalnum( $a ) ? 1 : 3 );
     5         kx         }
     5         kx       }
     5         kx       else
     5         kx       {
     5         kx         action( 1 );
     5         kx       }
     5         kx     }
     5         kx   }
     5         kx   #lats carriage return
     5         kx   print $of "\n";
     5         kx }
     5         kx 
     5         kx 
     5         kx local $SIG{__WARN__} = sub {
     5         kx   my $message = shift;
     5         kx   print STDERR "ERROR: " . $message;
     5         kx   usage();
     5         kx };
     5         kx 
     5         kx if( ! GetOptions( 'o=s'       => \$ofname,
     5         kx                   'output=s'  => \$ofname,
     5         kx                   ''          => \$stdio,
     5         kx                   'help|h|?'  => sub { usage() },
     5         kx                   'version|v' => sub { version() }
     5         kx                 )
     5         kx   )
     5         kx {
     5         kx   usage();
     5         kx }
     5         kx 
     5         kx foreach( @ARGV )
     5         kx {
     5         kx   $last = $_;
     5         kx 
     5         kx   if( $#ARGV )
     5         kx   {
     5         kx     usage();
     5         kx   }
     5         kx 
     5         kx # NOTE: The '--' is an option terminator!
     5         kx #       So ./script -- - returns last equal to '-'.
     5         kx #
     5         kx # The $last argument is a ifname by default;
     5         kx #
     5         kx }
     5         kx 
     5         kx 
     5         kx if( $ifname eq '' && $ofname eq '' && ! $stdio )
     5         kx {
     5         kx   usage();
     5         kx }
     5         kx 
     5         kx if( $ofname ne '' && $stdio && $last ne '' )
     5         kx {
     5         kx  # like that:
     5         kx  #   ./script -o min.json full.json -
     5         kx  #   ./script -o min.json - full.json
     5         kx  #
     5         kx   print "ERROR: Input file defined twice: as 'stdin' and as a orfinary file '$last'\n";
     5         kx   usage();
     5         kx }
     5         kx else
     5         kx {
     5         kx   $ifname = $last; $last = '';
     5         kx }
     5         kx 
     5         kx if( $ofname eq '' ) { $ofname = '-'; }
     5         kx if( $ifname eq '' ) { $ifname = '-'; }
     5         kx if( $ifname eq '-' ) { $if = *STDIN; }  else { open( $if, "< $ifname" ); }
     5         kx if( $ofname eq '-' ) { $of = *STDOUT; } else { open( $of, "> $ofname" ); }
     5         kx 
     5         kx 
     5         kx jsmin();
     5         kx 
     5         kx 
     5         kx close $if;
     5         kx close $of;
     5         kx 
     5         kx exit 0;