htmlcompressor-1.5.3

16:36:29.179 INFO  jd.cli.Main - Decompiling htmlcompressor-1.5.3.jar
package com.googlecode.htmlcompressor.analyzer;

import com.googlecode.htmlcompressor.compressor.ClosureJavaScriptCompressor;
import com.googlecode.htmlcompressor.compressor.HtmlCompressor;
import java.io.PrintStream;
import java.text.NumberFormat;
import java.util.Formatter;

public class HtmlAnalyzer
{
  private String jsCompressor = "yui";
  
  public HtmlAnalyzer() {}
  
  public HtmlAnalyzer(String jsCompressor)
  {
    this.jsCompressor = jsCompressor;
  }
  
  public void analyze(String source)
  {
    int originalSize = source.length();
    
    HtmlCompressor compressor = getCleanCompressor();
    String compResult = compressor.compress(source);
    
    printHeader();
    
    System.out.println(formatLine("Compression disabled", originalSize, originalSize, originalSize));
    int prevSize = originalSize;
    
    System.out.println(formatLine("All settings disabled", originalSize, compResult.length(), prevSize));
    prevSize = compResult.length();
    
    compressor.setRemoveComments(true);
    compResult = compressor.compress(source);
    System.out.println(formatLine("Comments removed", originalSize, compResult.length(), prevSize));
    prevSize = compResult.length();
    
    compressor.setRemoveMultiSpaces(true);
    compResult = compressor.compress(source);
    System.out.println(formatLine("Multiple spaces removed", originalSize, compResult.length(), prevSize));
    prevSize = compResult.length();
    
    compressor.setRemoveIntertagSpaces(true);
    compResult = compressor.compress(source);
    System.out.println(formatLine("No spaces between tags", originalSize, compResult.length(), prevSize));
    prevSize = compResult.length();
    
    compressor.setRemoveSurroundingSpaces("html,head,body,br,p");
    compResult = compressor.compress(source);
    System.out.println(formatLine("No surround spaces (min)", originalSize, compResult.length(), prevSize));
    prevSize = compResult.length();
    
    compressor.setRemoveSurroundingSpaces("html,head,body,br,p,h1,h2,h3,h4,h5,h6,blockquote,center,dl,fieldset,form,frame,frameset,hr,noframes,ol,table,tbody,tr,td,th,tfoot,thead,ul");
    compResult = compressor.compress(source);
    System.out.println(formatLine("No surround spaces (max)", originalSize, compResult.length(), prevSize));
    prevSize = compResult.length();
    
    compressor.setRemoveSurroundingSpaces("all");
    compResult = compressor.compress(source);
    System.out.println(formatLine("No surround spaces (all)", originalSize, compResult.length(), prevSize));
    prevSize = compResult.length();
    
    compressor.setRemoveQuotes(true);
    compResult = compressor.compress(source);
    System.out.println(formatLine("Quotes removed from tags", originalSize, compResult.length(), prevSize));
    prevSize = compResult.length();
    
    compressor.setRemoveLinkAttributes(true);
    compResult = compressor.compress(source);
    System.out.println(formatLine("<link> attr. removed", originalSize, compResult.length(), prevSize));
    prevSize = compResult.length();
    
    compressor.setRemoveStyleAttributes(true);
    compResult = compressor.compress(source);
    System.out.println(formatLine("<style> attr. removed", originalSize, compResult.length(), prevSize));
    prevSize = compResult.length();
    
    compressor.setRemoveScriptAttributes(true);
    compResult = compressor.compress(source);
    System.out.println(formatLine("<script> attr. removed", originalSize, compResult.length(), prevSize));
    prevSize = compResult.length();
    
    compressor.setRemoveFormAttributes(true);
    compResult = compressor.compress(source);
    System.out.println(formatLine("<form> attr. removed", originalSize, compResult.length(), prevSize));
    prevSize = compResult.length();
    
    compressor.setRemoveInputAttributes(true);
    compResult = compressor.compress(source);
    System.out.println(formatLine("<input> attr. removed", originalSize, compResult.length(), prevSize));
    prevSize = compResult.length();
    
    compressor.setSimpleBooleanAttributes(true);
    compResult = compressor.compress(source);
    System.out.println(formatLine("Simple boolean attributes", originalSize, compResult.length(), prevSize));
    prevSize = compResult.length();
    
    compressor.setSimpleDoctype(true);
    compResult = compressor.compress(source);
    System.out.println(formatLine("Simple doctype", originalSize, compResult.length(), prevSize));
    prevSize = compResult.length();
    
    compressor.setRemoveJavaScriptProtocol(true);
    compResult = compressor.compress(source);
    System.out.println(formatLine("Remove js pseudo-protocol", originalSize, compResult.length(), prevSize));
    prevSize = compResult.length();
    
    compressor.setRemoveHttpProtocol(true);
    compResult = compressor.compress(source);
    System.out.println(formatLine("Remove http protocol", originalSize, compResult.length(), prevSize));
    prevSize = compResult.length();
    
    compressor.setRemoveHttpsProtocol(true);
    compResult = compressor.compress(source);
    System.out.println(formatLine("Remove https protocol", originalSize, compResult.length(), prevSize));
    prevSize = compResult.length();
    try
    {
      compressor.setCompressCss(true);
      compResult = compressor.compress(source);
      System.out.println(formatLine("Compress inline CSS (YUI)", originalSize, compResult.length(), prevSize));
      prevSize = compResult.length();
    }
    catch (NoClassDefFoundError e)
    {
      System.out.println(formatEmptyLine("Compress inline CSS (YUI)"));
    }
    if (jsCompressor.equals("yui")) {
      try
      {
        compressor.setCompressJavaScript(true);
        compResult = compressor.compress(source);
        System.out.println(formatLine("Compress inline JS (YUI)", originalSize, compResult.length(), prevSize));
        prevSize = compResult.length();
      }
      catch (NoClassDefFoundError e)
      {
        System.out.println(formatEmptyLine("Compress inline JS (YUI)"));
      }
    } else {
      try
      {
        compressor.setCompressJavaScript(true);
        compressor.setJavaScriptCompressor(new ClosureJavaScriptCompressor());
        compResult = compressor.compress(source);
        System.out.println(formatLine("Compress JS (Closure)", originalSize, compResult.length(), prevSize));
        prevSize = compResult.length();
      }
      catch (NoClassDefFoundError e)
      {
        System.out.println(formatEmptyLine("Compress JS (Closure)"));
      }
    }
    printFooter();
  }
  
  private HtmlCompressor getCleanCompressor()
  {
    HtmlCompressor compressor = new HtmlCompressor();
    compressor.setRemoveComments(false);
    compressor.setRemoveMultiSpaces(false);
    
    return compressor;
  }
  
  private String formatLine(String descr, int originalSize, int compressedSize, int prevSize)
  {
    Formatter fmt = new Formatter();
    fmt.format("%-25s | %16s | %16s | %12s |", new Object[] { descr, formatDecrease(prevSize, compressedSize), formatDecrease(originalSize, compressedSize), formatSize(compressedSize) });
    return fmt.toString();
  }
  
  private String formatEmptyLine(String descr)
  {
    Formatter fmt = new Formatter();
    fmt.format("%-25s | %16s | %16s | %12s |", new Object[] { descr, "-", "-", "-" });
    return fmt.toString();
  }
  
  private void printHeader()
  {
    System.out.println();
    System.out.println("================================================================================");
    System.out.format("%-25s | %-16s | %-16s | %-12s |", new Object[] { "         Setting", "Incremental Gain", "   Total Gain", " Page Size" });
    System.out.println();
    System.out.println("================================================================================");
  }
  
  private void printFooter()
  {
    System.out.println("================================================================================");
    System.out.println();
    System.out.println("Each consecutive compressor setting is applied on top of previous ones.");
    System.out.println("In order to see JS and CSS compression results, YUI jar file must be present.");
    System.out.println("All sizes are in bytes.");
  }
  
  private String formatDecrease(int originalSize, int compressedSize)
  {
    NumberFormat nf = NumberFormat.getPercentInstance();
    nf.setGroupingUsed(true);
    nf.setMinimumFractionDigits(1);
    nf.setMaximumFractionDigits(1);
    
    return formatSize(originalSize - compressedSize) + " (" + nf.format(1.0D - compressedSize / originalSize) + ")";
  }
  
  private String formatSize(int size)
  {
    NumberFormat nf = NumberFormat.getInstance();
    nf.setGroupingUsed(true);
    nf.setParseIntegerOnly(true);
    return nf.format(size);
  }
}

/* Location:
 * Qualified Name:     com.googlecode.htmlcompressor.analyzer.HtmlAnalyzer
 * Java Class Version: 5 (49.0)
 * JD-Core Version:    0.7.1
 */
package com.googlecode.htmlcompressor;

import java.io.File;
import java.io.FileFilter;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

class CmdLineCompressor$CompressorFileFilter
  implements FileFilter
{
  private Pattern filemaskPattern;
  private boolean withDirs;
  
  public CmdLineCompressor$CompressorFileFilter(CmdLineCompressor paramCmdLineCompressor, String type, String filemask, boolean withDirs)
  {
    this.withDirs = withDirs;
    if (filemask == null)
    {
      if ((type != null) && (type.equals("xml"))) {
        filemaskPattern = Pattern.compile("^.*\\.xml$", 2);
      } else {
        filemaskPattern = Pattern.compile("^.*\\.html?$", 2);
      }
    }
    else
    {
      filemask = filemask.replaceAll(CmdLineCompressor.access$000(paramCmdLineCompressor, "."), Matcher.quoteReplacement("\\."));
      filemask = filemask.replaceAll(CmdLineCompressor.access$000(paramCmdLineCompressor, "*"), Matcher.quoteReplacement(".*"));
      filemask = filemask.replaceAll(CmdLineCompressor.access$000(paramCmdLineCompressor, "?"), Matcher.quoteReplacement("."));
      filemask = filemask.replaceAll(CmdLineCompressor.access$000(paramCmdLineCompressor, ";"), Matcher.quoteReplacement("$|^"));
      filemask = "^" + filemask + "$";
      
      filemaskPattern = Pattern.compile(filemask, 2);
    }
  }
  
  public boolean accept(File file)
  {
    if (!withDirs)
    {
      if (!file.isDirectory()) {
        return filemaskPattern.matcher(file.getName()).matches();
      }
    }
    else {
      return (file.isDirectory()) || (filemaskPattern.matcher(file.getName()).matches());
    }
    return false;
  }
}

/* Location:
 * Qualified Name:     com.googlecode.htmlcompressor.CmdLineCompressor.CompressorFileFilter
 * Java Class Version: 5 (49.0)
 * JD-Core Version:    0.7.1
 */
package com.googlecode.htmlcompressor;

import com.google.javascript.jscomp.CompilationLevel;
import com.google.javascript.jscomp.JSSourceFile;
import com.googlecode.htmlcompressor.analyzer.HtmlAnalyzer;
import com.googlecode.htmlcompressor.compressor.ClosureJavaScriptCompressor;
import com.googlecode.htmlcompressor.compressor.Compressor;
import com.googlecode.htmlcompressor.compressor.HtmlCompressor;
import com.googlecode.htmlcompressor.compressor.XmlCompressor;
import jargs.gnu.CmdLineParser;
import jargs.gnu.CmdLineParser.Option;
import jargs.gnu.CmdLineParser.OptionException;
import java.io.BufferedReader;
import java.io.Closeable;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintStream;
import java.io.Writer;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Stack;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;

public class CmdLineCompressor
{
  private static final Pattern urlPattern = Pattern.compile("^https?://.*$", 2);
  private boolean helpOpt;
  private boolean analyzeOpt;
  private String charsetOpt;
  private String outputFilenameOpt;
  private String patternsFilenameOpt;
  private String typeOpt;
  private String filemaskOpt;
  private boolean recursiveOpt;
  private boolean preserveCommentsOpt;
  private boolean preserveIntertagSpacesOpt;
  private boolean preserveMultiSpacesOpt;
  private boolean removeIntertagSpacesOpt;
  private boolean removeQuotesOpt;
  private String removeSurroundingSpacesOpt;
  private boolean preserveLineBreaksOpt;
  private boolean preservePhpTagsOpt;
  private boolean preserveServerScriptTagsOpt;
  private boolean preserveSsiTagsOpt;
  private boolean compressJsOpt;
  private boolean compressCssOpt;
  private String jsCompressorOpt;
  private boolean simpleDoctypeOpt;
  private boolean removeScriptAttributesOpt;
  private boolean removeStyleAttributesOpt;
  private boolean removeLinkAttributesOpt;
  private boolean removeFormAttributesOpt;
  private boolean removeInputAttributesOpt;
  private boolean simpleBooleanAttributesOpt;
  private boolean removeJavaScriptProtocolOpt;
  private boolean removeHttpProtocolOpt;
  private boolean removeHttpsProtocolOpt;
  private boolean nomungeOpt;
  private int linebreakOpt;
  private boolean preserveSemiOpt;
  private boolean disableOptimizationsOpt;
  private String closureOptLevelOpt;
  private boolean closureCustomExternsOnlyOpt;
  private List<String> closureExternsOpt;
  private String[] fileArgsOpt;
  
  public static void main(String[] args)
  {
    CmdLineCompressor cmdLineCompressor = new CmdLineCompressor(args);
    cmdLineCompressor.process(args);
  }
  
  public CmdLineCompressor(String[] args)
  {
    CmdLineParser parser = new CmdLineParser();
    
    CmdLineParser.Option helpOpt = parser.addBooleanOption('h', "help");
    CmdLineParser.Option helpOptAlt = parser.addBooleanOption('?', "help_alt");
    CmdLineParser.Option analyzeOpt = parser.addBooleanOption('a', "analyze");
    CmdLineParser.Option recursiveOpt = parser.addBooleanOption('r', "recursive");
    CmdLineParser.Option charsetOpt = parser.addStringOption('c', "charset");
    CmdLineParser.Option outputFilenameOpt = parser.addStringOption('o', "output");
    CmdLineParser.Option patternsFilenameOpt = parser.addStringOption('p', "preserve");
    CmdLineParser.Option typeOpt = parser.addStringOption('t', "type");
    CmdLineParser.Option filemaskOpt = parser.addStringOption('m', "mask");
    CmdLineParser.Option preserveCommentsOpt = parser.addBooleanOption("preserve-comments");
    CmdLineParser.Option preserveIntertagSpacesOpt = parser.addBooleanOption("preserve-intertag-spaces");
    CmdLineParser.Option preserveMultiSpacesOpt = parser.addBooleanOption("preserve-multi-spaces");
    CmdLineParser.Option removeIntertagSpacesOpt = parser.addBooleanOption("remove-intertag-spaces");
    CmdLineParser.Option removeSurroundingSpacesOpt = parser.addStringOption("remove-surrounding-spaces");
    CmdLineParser.Option removeQuotesOpt = parser.addBooleanOption("remove-quotes");
    CmdLineParser.Option preserveLineBreaksOpt = parser.addBooleanOption("preserve-line-breaks");
    CmdLineParser.Option preservePhpTagsOpt = parser.addBooleanOption("preserve-php");
    CmdLineParser.Option preserveServerScriptTagsOpt = parser.addBooleanOption("preserve-server-script");
    CmdLineParser.Option preserveSsiTagsOpt = parser.addBooleanOption("preserve-ssi");
    CmdLineParser.Option compressJsOpt = parser.addBooleanOption("compress-js");
    CmdLineParser.Option compressCssOpt = parser.addBooleanOption("compress-css");
    CmdLineParser.Option jsCompressorOpt = parser.addStringOption("js-compressor");
    
    CmdLineParser.Option simpleDoctypeOpt = parser.addBooleanOption("simple-doctype");
    CmdLineParser.Option removeScriptAttributesOpt = parser.addBooleanOption("remove-script-attr");
    CmdLineParser.Option removeStyleAttributesOpt = parser.addBooleanOption("remove-style-attr");
    CmdLineParser.Option removeLinkAttributesOpt = parser.addBooleanOption("remove-link-attr");
    CmdLineParser.Option removeFormAttributesOpt = parser.addBooleanOption("remove-form-attr");
    CmdLineParser.Option removeInputAttributesOpt = parser.addBooleanOption("remove-input-attr");
    CmdLineParser.Option simpleBooleanAttributesOpt = parser.addBooleanOption("simple-bool-attr");
    CmdLineParser.Option removeJavaScriptProtocolOpt = parser.addBooleanOption("remove-js-protocol");
    CmdLineParser.Option removeHttpProtocolOpt = parser.addBooleanOption("remove-http-protocol");
    CmdLineParser.Option removeHttpsProtocolOpt = parser.addBooleanOption("remove-https-protocol");
    
    CmdLineParser.Option nomungeOpt = parser.addBooleanOption("nomunge");
    CmdLineParser.Option linebreakOpt = parser.addStringOption("line-break");
    CmdLineParser.Option preserveSemiOpt = parser.addBooleanOption("preserve-semi");
    CmdLineParser.Option disableOptimizationsOpt = parser.addBooleanOption("disable-optimizations");
    
    CmdLineParser.Option closureOptLevelOpt = parser.addStringOption("closure-opt-level");
    CmdLineParser.Option closureCustomExternsOnlyOpt = parser.addBooleanOption("closure-custom-externs-only");
    CmdLineParser.Option closureExternsOpt = parser.addStringOption("closure-externs");
    try
    {
      parser.parse(args);
      
      this.helpOpt = ((((Boolean)parser.getOptionValue(helpOpt, Boolean.valueOf(false))).booleanValue()) || (((Boolean)parser.getOptionValue(helpOptAlt, Boolean.valueOf(false))).booleanValue()));
      this.analyzeOpt = ((Boolean)parser.getOptionValue(analyzeOpt, Boolean.valueOf(false))).booleanValue();
      this.recursiveOpt = ((Boolean)parser.getOptionValue(recursiveOpt, Boolean.valueOf(false))).booleanValue();
      this.charsetOpt = ((String)parser.getOptionValue(charsetOpt, "UTF-8"));
      this.outputFilenameOpt = ((String)parser.getOptionValue(outputFilenameOpt));
      this.patternsFilenameOpt = ((String)parser.getOptionValue(patternsFilenameOpt));
      this.typeOpt = ((String)parser.getOptionValue(typeOpt));
      this.filemaskOpt = ((String)parser.getOptionValue(filemaskOpt));
      this.preserveCommentsOpt = ((Boolean)parser.getOptionValue(preserveCommentsOpt, Boolean.valueOf(false))).booleanValue();
      this.preserveIntertagSpacesOpt = ((Boolean)parser.getOptionValue(preserveIntertagSpacesOpt, Boolean.valueOf(false))).booleanValue();
      this.preserveMultiSpacesOpt = ((Boolean)parser.getOptionValue(preserveMultiSpacesOpt, Boolean.valueOf(false))).booleanValue();
      this.removeIntertagSpacesOpt = ((Boolean)parser.getOptionValue(removeIntertagSpacesOpt, Boolean.valueOf(false))).booleanValue();
      this.removeQuotesOpt = ((Boolean)parser.getOptionValue(removeQuotesOpt, Boolean.valueOf(false))).booleanValue();
      this.preserveLineBreaksOpt = ((Boolean)parser.getOptionValue(preserveLineBreaksOpt, Boolean.valueOf(false))).booleanValue();
      this.preservePhpTagsOpt = ((Boolean)parser.getOptionValue(preservePhpTagsOpt, Boolean.valueOf(false))).booleanValue();
      this.preserveServerScriptTagsOpt = ((Boolean)parser.getOptionValue(preserveServerScriptTagsOpt, Boolean.valueOf(false))).booleanValue();
      this.preserveSsiTagsOpt = ((Boolean)parser.getOptionValue(preserveSsiTagsOpt, Boolean.valueOf(false))).booleanValue();
      this.compressJsOpt = ((Boolean)parser.getOptionValue(compressJsOpt, Boolean.valueOf(false))).booleanValue();
      this.compressCssOpt = ((Boolean)parser.getOptionValue(compressCssOpt, Boolean.valueOf(false))).booleanValue();
      this.jsCompressorOpt = ((String)parser.getOptionValue(jsCompressorOpt, "yui"));
      
      this.simpleDoctypeOpt = ((Boolean)parser.getOptionValue(simpleDoctypeOpt, Boolean.valueOf(false))).booleanValue();
      this.removeScriptAttributesOpt = ((Boolean)parser.getOptionValue(removeScriptAttributesOpt, Boolean.valueOf(false))).booleanValue();
      this.removeStyleAttributesOpt = ((Boolean)parser.getOptionValue(removeStyleAttributesOpt, Boolean.valueOf(false))).booleanValue();
      this.removeLinkAttributesOpt = ((Boolean)parser.getOptionValue(removeLinkAttributesOpt, Boolean.valueOf(false))).booleanValue();
      this.removeFormAttributesOpt = ((Boolean)parser.getOptionValue(removeFormAttributesOpt, Boolean.valueOf(false))).booleanValue();
      this.removeInputAttributesOpt = ((Boolean)parser.getOptionValue(removeInputAttributesOpt, Boolean.valueOf(false))).booleanValue();
      this.simpleBooleanAttributesOpt = ((Boolean)parser.getOptionValue(simpleBooleanAttributesOpt, Boolean.valueOf(false))).booleanValue();
      this.removeJavaScriptProtocolOpt = ((Boolean)parser.getOptionValue(removeJavaScriptProtocolOpt, Boolean.valueOf(false))).booleanValue();
      this.removeHttpProtocolOpt = ((Boolean)parser.getOptionValue(removeHttpProtocolOpt, Boolean.valueOf(false))).booleanValue();
      this.removeHttpsProtocolOpt = ((Boolean)parser.getOptionValue(removeHttpsProtocolOpt, Boolean.valueOf(false))).booleanValue();
      
      this.nomungeOpt = ((Boolean)parser.getOptionValue(nomungeOpt, Boolean.valueOf(false))).booleanValue();
      this.linebreakOpt = ((Integer)parser.getOptionValue(linebreakOpt, Integer.valueOf(-1))).intValue();
      this.preserveSemiOpt = ((Boolean)parser.getOptionValue(preserveSemiOpt, Boolean.valueOf(false))).booleanValue();
      this.disableOptimizationsOpt = ((Boolean)parser.getOptionValue(disableOptimizationsOpt, Boolean.valueOf(false))).booleanValue();
      
      this.closureOptLevelOpt = ((String)parser.getOptionValue(closureOptLevelOpt, "simple"));
      this.closureCustomExternsOnlyOpt = ((Boolean)parser.getOptionValue(closureCustomExternsOnlyOpt, Boolean.valueOf(false))).booleanValue();
      
      this.closureExternsOpt = parser.getOptionValues(closureExternsOpt);
      
      this.removeSurroundingSpacesOpt = ((String)parser.getOptionValue(removeSurroundingSpacesOpt));
      if (this.removeSurroundingSpacesOpt != null) {
        if (this.removeSurroundingSpacesOpt.equalsIgnoreCase("min")) {
          this.removeSurroundingSpacesOpt = "html,head,body,br,p";
        } else if (this.removeSurroundingSpacesOpt.equalsIgnoreCase("max")) {
          this.removeSurroundingSpacesOpt = "html,head,body,br,p,h1,h2,h3,h4,h5,h6,blockquote,center,dl,fieldset,form,frame,frameset,hr,noframes,ol,table,tbody,tr,td,th,tfoot,thead,ul";
        } else if (this.removeSurroundingSpacesOpt.equalsIgnoreCase("all")) {
          this.removeSurroundingSpacesOpt = "all";
        }
      }
      fileArgsOpt = parser.getRemainingArgs();
      
      this.charsetOpt = (Charset.isSupported(this.charsetOpt) ? this.charsetOpt : "UTF-8");
      for (int i = 0; i < args.length; i++) {
        if (args[i].equals("/?"))
        {
          this.helpOpt = true;
          break;
        }
      }
    }
    catch (CmdLineParser.OptionException e)
    {
      System.out.println("ERROR: " + e.getMessage());
      printUsage();
    }
  }
  
  public void process(String[] args)
  {
    try
    {
      if (helpOpt)
      {
        printUsage();
        return;
      }
      String type = typeOpt;
      if ((type != null) && (!type.equalsIgnoreCase("html")) && (!type.equalsIgnoreCase("xml"))) {
        throw new IllegalArgumentException("Unknown type: " + type);
      }
      if (fileArgsOpt.length == 0)
      {
        if (type == null) {
          type = "html";
        }
      }
      else if (type == null) {
        if (fileArgsOpt[0].toLowerCase().endsWith(".xml")) {
          type = "xml";
        } else {
          type = "html";
        }
      }
      if (analyzeOpt)
      {
        HtmlAnalyzer analyzer = new HtmlAnalyzer("closure".equalsIgnoreCase(jsCompressorOpt) ? "closure" : "yui");
        analyzer.analyze(readResource(buildReader(fileArgsOpt.length > 0 ? fileArgsOpt[0] : null)));
      }
      else
      {
        compressor = type.equals("xml") ? createXmlCompressor() : createHtmlCompressor();
        Map<String, String> ioMap = buildInputOutputMap();
        for (Map.Entry<String, String> entry : ioMap.entrySet()) {
          writeResource(compressor.compress(readResource(buildReader((String)entry.getKey()))), buildWriter((String)entry.getValue()));
        }
      }
    }
    catch (NoClassDefFoundError e)
    {
      Compressor compressor;
      if ("closure".equalsIgnoreCase(jsCompressorOpt)) {
        System.out.println("ERROR: For JavaScript compression using Google Closure Compiler\nadditional jar file called compiler.jar must be present\nin the same directory as HtmlCompressor jar");
      } else {
        System.out.println("ERROR: For CSS or JavaScript compression using YUICompressor additional jar file \ncalled yuicompressor.jar must be present\nin the same directory as HtmlCompressor jar");
      }
    }
    catch (CmdLineParser.OptionException e)
    {
      System.out.println("ERROR: " + e.getMessage());
      printUsage();
    }
    catch (IOException e)
    {
      System.out.println("ERROR: " + e.getMessage());
    }
    catch (IllegalArgumentException e)
    {
      System.out.println("ERROR: " + e.getMessage());
    }
  }
  
  private Compressor createHtmlCompressor()
    throws IllegalArgumentException, CmdLineParser.OptionException
  {
    boolean useClosureCompressor = "closure".equalsIgnoreCase(jsCompressorOpt);
    
    List<Pattern> preservePatterns = new ArrayList();
    if (preservePhpTagsOpt) {
      preservePatterns.add(HtmlCompressor.PHP_TAG_PATTERN);
    }
    if (preserveServerScriptTagsOpt) {
      preservePatterns.add(HtmlCompressor.SERVER_SCRIPT_TAG_PATTERN);
    }
    if (preserveSsiTagsOpt) {
      preservePatterns.add(HtmlCompressor.SERVER_SIDE_INCLUDE_PATTERN);
    }
    if (patternsFilenameOpt != null)
    {
      BufferedReader patternsIn = null;
      try
      {
        patternsIn = new BufferedReader(new InputStreamReader(new FileInputStream(patternsFilenameOpt), charsetOpt));
        
        String line = null;
        while ((line = patternsIn.readLine()) != null) {
          if (line.length() > 0) {
            try
            {
              preservePatterns.add(Pattern.compile(line));
            }
            catch (PatternSyntaxException e)
            {
              throw new IllegalArgumentException("Regular expression compilation error: " + e.getMessage());
            }
          }
        }
      }
      catch (IOException e)
      {
        throw new IllegalArgumentException("Unable to read custom pattern definitions file: " + e.getMessage());
      }
      finally
      {
        closeStream(patternsIn);
      }
    }
    HtmlCompressor htmlCompressor = new HtmlCompressor();
    
    htmlCompressor.setRemoveComments(!preserveCommentsOpt);
    htmlCompressor.setRemoveMultiSpaces(!preserveMultiSpacesOpt);
    htmlCompressor.setRemoveIntertagSpaces(removeIntertagSpacesOpt);
    htmlCompressor.setRemoveQuotes(removeQuotesOpt);
    htmlCompressor.setPreserveLineBreaks(preserveLineBreaksOpt);
    htmlCompressor.setCompressJavaScript(compressJsOpt);
    htmlCompressor.setCompressCss(compressCssOpt);
    
    htmlCompressor.setSimpleDoctype(simpleDoctypeOpt);
    htmlCompressor.setRemoveScriptAttributes(removeScriptAttributesOpt);
    htmlCompressor.setRemoveStyleAttributes(removeStyleAttributesOpt);
    htmlCompressor.setRemoveLinkAttributes(removeLinkAttributesOpt);
    htmlCompressor.setRemoveFormAttributes(removeFormAttributesOpt);
    htmlCompressor.setRemoveInputAttributes(removeInputAttributesOpt);
    htmlCompressor.setSimpleBooleanAttributes(simpleBooleanAttributesOpt);
    htmlCompressor.setRemoveJavaScriptProtocol(removeJavaScriptProtocolOpt);
    htmlCompressor.setRemoveHttpProtocol(removeHttpProtocolOpt);
    htmlCompressor.setRemoveHttpsProtocol(removeHttpsProtocolOpt);
    htmlCompressor.setRemoveSurroundingSpaces(removeSurroundingSpacesOpt);
    
    htmlCompressor.setPreservePatterns(preservePatterns);
    
    htmlCompressor.setYuiJsNoMunge(nomungeOpt);
    htmlCompressor.setYuiJsPreserveAllSemiColons(preserveSemiOpt);
    htmlCompressor.setYuiJsDisableOptimizations(disableOptimizationsOpt);
    htmlCompressor.setYuiJsLineBreak(linebreakOpt);
    htmlCompressor.setYuiCssLineBreak(linebreakOpt);
    if ((compressJsOpt) && (useClosureCompressor))
    {
      ClosureJavaScriptCompressor closureCompressor = new ClosureJavaScriptCompressor();
      if (closureOptLevelOpt.equalsIgnoreCase("advanced"))
      {
        closureCompressor.setCompilationLevel(CompilationLevel.ADVANCED_OPTIMIZATIONS);
        closureCompressor.setCustomExternsOnly(closureCustomExternsOnlyOpt);
        if (closureExternsOpt.size() > 0)
        {
          List<JSSourceFile> externs = new ArrayList();
          for (String externFile : closureExternsOpt) {
            externs.add(JSSourceFile.fromFile(externFile));
          }
          closureCompressor.setExterns(externs);
        }
      }
      else if (closureOptLevelOpt.equalsIgnoreCase("whitespace"))
      {
        closureCompressor.setCompilationLevel(CompilationLevel.WHITESPACE_ONLY);
      }
      else
      {
        closureCompressor.setCompilationLevel(CompilationLevel.SIMPLE_OPTIMIZATIONS);
      }
      htmlCompressor.setJavaScriptCompressor(closureCompressor);
    }
    return htmlCompressor;
  }
  
  private Compressor createXmlCompressor()
    throws IllegalArgumentException, CmdLineParser.OptionException
  {
    XmlCompressor xmlCompressor = new XmlCompressor();
    xmlCompressor.setRemoveComments(!preserveCommentsOpt);
    xmlCompressor.setRemoveIntertagSpaces(!preserveIntertagSpacesOpt);
    
    return xmlCompressor;
  }
  
  private Map<String, String> buildInputOutputMap()
    throws IllegalArgumentException, IOException
  {
    Map<String, String> map = new HashMap();
    
    File outpuFile = null;
    if (outputFilenameOpt != null)
    {
      outpuFile = new File(outputFilenameOpt);
      if ((outputFilenameOpt.endsWith("/")) || (outputFilenameOpt.endsWith("\\"))) {
        outpuFile.mkdirs();
      } else {
        new File(outpuFile.getCanonicalFile().getParent()).mkdirs();
      }
    }
    if ((fileArgsOpt.length > 1) && ((outpuFile == null) || (!outpuFile.isDirectory()))) {
      throw new IllegalArgumentException("Output must be a directory and end with a slash (/)");
    }
    if (fileArgsOpt.length == 0) {
      map.put(null, outputFilenameOpt);
    } else {
      for (int i = 0; i < fileArgsOpt.length; i++) {
        if (!urlPattern.matcher(fileArgsOpt[i]).matches())
        {
          File inputFile = new File(fileArgsOpt[i]);
          if (inputFile.isDirectory())
          {
            if ((outpuFile != null) && (outpuFile.isDirectory()))
            {
              if (!recursiveOpt)
              {
                for (File file : inputFile.listFiles(new CompressorFileFilter(typeOpt, filemaskOpt, false))) {
                  if (!file.isDirectory())
                  {
                    String from = file.getCanonicalPath();
                    String to = from.replaceFirst(escRegEx(inputFile.getCanonicalPath()), Matcher.quoteReplacement(outpuFile.getCanonicalPath()));
                    map.put(from, to);
                  }
                }
              }
              else
              {
                Stack<File> fileStack = new Stack();
                fileStack.push(inputFile);
                while (!fileStack.isEmpty())
                {
                  File child = (File)fileStack.pop();
                  if (child.isDirectory())
                  {
                    for (File f : child.listFiles(new CompressorFileFilter(typeOpt, filemaskOpt, true))) {
                      fileStack.push(f);
                    }
                  }
                  else if (child.isFile())
                  {
                    String from = child.getCanonicalPath();
                    String to = from.replaceFirst(escRegEx(inputFile.getCanonicalPath()), Matcher.quoteReplacement(outpuFile.getCanonicalPath()));
                    map.put(from, to);
                    
                    new File(new File(to).getCanonicalFile().getParent()).mkdirs();
                  }
                }
              }
            }
            else {
              throw new IllegalArgumentException("Output must be a directory and end with a slash (/)");
            }
          }
          else if ((outpuFile != null) && (outpuFile.isDirectory()))
          {
            String from = inputFile.getCanonicalPath();
            String to = from.replaceFirst(escRegEx(inputFile.getCanonicalFile().getParentFile().getCanonicalPath()), Matcher.quoteReplacement(outpuFile.getCanonicalPath()));
            map.put(fileArgsOpt[i], to);
          }
          else
          {
            map.put(fileArgsOpt[i], outputFilenameOpt);
          }
        }
        else if ((fileArgsOpt.length == 1) && ((outpuFile == null) || (!outpuFile.isDirectory())))
        {
          map.put(fileArgsOpt[i], outputFilenameOpt);
        }
        else
        {
          throw new IllegalArgumentException("Input URL should be single and cannot have directory as output");
        }
      }
    }
    return map;
  }
  
  private BufferedReader buildReader(String filename)
    throws IOException
  {
    if (filename == null) {
      return new BufferedReader(new InputStreamReader(System.in, charsetOpt));
    }
    if (urlPattern.matcher(filename).matches()) {
      return new BufferedReader(new InputStreamReader(new URL(filename).openConnection().getInputStream()));
    }
    return new BufferedReader(new InputStreamReader(new FileInputStream(filename), charsetOpt));
  }
  
  private Writer buildWriter(String filename)
    throws IOException
  {
    if (filename == null) {
      return new OutputStreamWriter(System.out, charsetOpt);
    }
    return new OutputStreamWriter(new FileOutputStream(filename), charsetOpt);
  }
  
  private String readResource(BufferedReader input)
    throws IOException
  {
    StringBuilder source = new StringBuilder();
    try
    {
      String line = null;
      while ((line = input.readLine()) != null)
      {
        source.append(line);
        source.append(System.getProperty("line.separator"));
      }
    }
    finally
    {
      closeStream(input);
    }
    return source.toString();
  }
  
  private void writeResource(String content, Writer output)
    throws IOException
  {
    try
    {
      output.write(content);
    }
    finally
    {
      closeStream(output);
    }
  }
  
  private void closeStream(Closeable stream)
  {
    if (stream != null) {
      try
      {
        stream.close();
      }
      catch (IOException ignore) {}
    }
  }
  
  private String escRegEx(String inStr)
  {
    return inStr.replaceAll("([\\\\*+\\[\\](){}\\$.?\\^|])", "\\\\$1");
  }
  
  private void printUsage()
  {
    System.out.println("Usage: java -jar htmlcompressor.jar [options] [input]\n\n[input]                        URL, filename, directory, or space separated list\n                               of files and directories to compress.\n                               If none provided reads from <stdin>\n\nGlobal Options:\n -?, /?, -h, --help            Displays this help screen\n -t, --type <html|xml>         If not provided autodetects from file extension\n -r, --recursive               Process files inside subdirectories\n -c, --charset <charset>       Charset for reading files, UTF-8 by default\n -m, --mask <filemask>         Filter input files inside directories by mask\n -o, --output <path>           Filename or directory for compression results.\n                               If none provided outputs result to <stdout>\n -a, --analyze                 Tries different settings and displays report.\n                               All settings except --js-compressor are ignored\n\nXML Compression Options:\n --preserve-comments           Preserve comments\n --preserve-intertag-spaces    Preserve intertag spaces\n\nHTML Compression Options:\n --preserve-comments           Preserve comments\n --preserve-multi-spaces       Preserve multiple spaces\n --preserve-line-breaks        Preserve line breaks\n --remove-intertag-spaces      Remove intertag spaces\n --remove-quotes               Remove unneeded quotes\n --simple-doctype              Change doctype to <!DOCTYPE html>\n --remove-style-attr           Remove TYPE attribute from STYLE tags\n --remove-link-attr            Remove TYPE attribute from LINK tags\n --remove-script-attr          Remove TYPE and LANGUAGE from SCRIPT tags\n --remove-form-attr            Remove METHOD=\"GET\" from FORM tags\n --remove-input-attr           Remove TYPE=\"TEXT\" from INPUT tags\n --simple-bool-attr            Remove values from boolean tag attributes\n --remove-js-protocol          Remove \"javascript:\" from inline event handlers\n --remove-http-protocol        Remove \"http:\" from tag attributes\n --remove-https-protocol       Remove \"https:\" from tag attributes\n --remove-surrounding-spaces <min|max|all|custom_list>\n                               Predefined or custom comma separated list of tags\n --compress-js                 Enable inline JavaScript compression\n --compress-css                Enable inline CSS compression using YUICompressor\n --js-compressor <yui|closure> Switch inline JavaScript compressor between\n                               YUICompressor (default) and Closure Compiler\n\nJavaScript Compression Options for YUI Compressor:\n --nomunge                     Minify only, do not obfuscate\n --preserve-semi               Preserve all semicolons\n --disable-optimizations       Disable all micro optimizations\n --line-break <column num>     Insert a line break after the specified column\n\nJavaScript Compression Options for Google Closure Compiler:\n --closure-opt-level <simple|advanced|whitespace>\n                               Sets level of optimization (simple by default)\n --closure-externs <file>      Sets custom externs file, repeat for each file\n --closure-custom-externs-only Disable default built-in externs\n\nCSS Compression Options for YUI Compressor:\n --line-break <column num>     Insert a line break after the specified column\n\nCustom Block Preservation Options:\n --preserve-php                Preserve <?php ... ?> tags\n --preserve-server-script      Preserve <% ... %> tags\n --preserve-ssi                Preserve <!--# ... --> tags\n -p, --preserve <path>         Read regular expressions that define\n                               custom preservation rules from a file\n\nPlease note that if you enable CSS or JavaScript compression, additional\nYUI Compressor or Google Closure Compiler jar files must be present\nin the same directory as this jar.");
  }
  
  private class CompressorFileFilter
    implements FileFilter
  {
    private Pattern filemaskPattern;
    private boolean withDirs;
    
    public CompressorFileFilter(String type, String filemask, boolean withDirs)
    {
      this.withDirs = withDirs;
      if (filemask == null)
      {
        if ((type != null) && (type.equals("xml"))) {
          filemaskPattern = Pattern.compile("^.*\\.xml$", 2);
        } else {
          filemaskPattern = Pattern.compile("^.*\\.html?$", 2);
        }
      }
      else
      {
        filemask = filemask.replaceAll(CmdLineCompressor.this.escRegEx("."), Matcher.quoteReplacement("\\."));
        filemask = filemask.replaceAll(CmdLineCompressor.this.escRegEx("*"), Matcher.quoteReplacement(".*"));
        filemask = filemask.replaceAll(CmdLineCompressor.this.escRegEx("?"), Matcher.quoteReplacement("."));
        filemask = filemask.replaceAll(CmdLineCompressor.this.escRegEx(";"), Matcher.quoteReplacement("$|^"));
        filemask = "^" + filemask + "$";
        
        filemaskPattern = Pattern.compile(filemask, 2);
      }
    }
    
    public boolean accept(File file)
  
1 2 3 4

Further reading...

For more information on Java 1.5 Tiger, you may find Java 1.5 Tiger, A developer's Notebook by D. Flanagan and B. McLaughlin from O'Reilly of interest.

New!JAR listings


Copyright 2006-2017. Infinite Loop Ltd