Compresses a String containing JavaScript by removing comments and whitespace. : Script Engines « JDK 6 « Java






Compresses a String containing JavaScript by removing comments and whitespace.

   
/*
 * This file is part of the Echo Web Application Framework (hereinafter "Echo").
 * Copyright (C) 2002-2009 NextApp, Inc.
 * 
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 * 
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with the
 * License. You may obtain a copy of the License at http://www.mozilla.org/MPL/
 * 
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
 * the specific language governing rights and limitations under the License.
 * 
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or the
 * GNU Lesser General Public License Version 2.1 or later (the "LGPL"), in which
 * case the provisions of the GPL or the LGPL are applicable instead of those
 * above. If you wish to allow use of your version of this file only under the
 * terms of either the GPL or the LGPL, and not to allow others to use your
 * version of this file under the terms of the MPL, indicate your decision by
 * deleting the provisions above and replace them with the notice and other
 * provisions required by the GPL or the LGPL. If you do not delete the
 * provisions above, a recipient may use your version of this file under the
 * terms of any one of the MPL, the GPL or the LGPL.
 */


/**
 * Compresses a String containing JavaScript by removing comments and 
 * whitespace.
 */
public class JavaScriptCompressor {

    private static final char LINE_FEED = '\n';
    private static final char CARRIAGE_RETURN = '\r';
    private static final char SPACE = ' ';
    private static final char TAB = '\t';

    /**
     * Compresses a String containing JavaScript by removing comments and 
     * whitespace.
     * 
     * @param script the String to compress
     * @return a compressed version
     */
    public static String compress(String script) {
        JavaScriptCompressor jsc = new JavaScriptCompressor(script);
        return jsc.outputBuffer.toString();
    }

    /** Original JavaScript text. */
    private String script;
    
    /** 
     * Compressed output buffer.
     * This buffer may only be modified by invoking the <code>append()</code>
     * method.
     */
    private StringBuffer outputBuffer;
    
    /** Current parser cursor position in original text. */
    private int pos;
    
    /** Character at parser cursor position. */
    private char ch;
    
    /** Last character appended to buffer. */
    private char lastAppend;

    /** Flag indicating if end-of-buffer has been reached. */
    private boolean endReached;

    /** Flag indicating whether content has been appended after last identifier. */
    private boolean contentAppendedAfterLastIdentifier = true;

    /**
     * Creates a new <code>JavaScriptCompressor</code> instance.
     * 
     * @param script
     */
    private JavaScriptCompressor(String script) {
        this.script = script;
        outputBuffer = new StringBuffer(script.length());
        nextChar();

        while (!endReached) {
            if (Character.isJavaIdentifierStart(ch)) {
                renderIdentifier();
            } else if (ch == ' ') {
                skipWhiteSpace();
            } else if (isWhitespace()) {
                // Compress whitespace
                skipWhiteSpace();
            } else if ((ch == '"') || (ch == '\'')) {
                // Handle strings
                renderString();
            } else if (ch == '/') {
                // Handle comments
                nextChar();
                if (ch == '/') {
                    nextChar();
                    skipLineComment();
                } else if (ch == '*') {
                    nextChar();
                    skipBlockComment();
                } else {
                    append('/');
                }
            } else {
                append(ch);
                nextChar();
            }
        }
    }

    /**
     * Append character to output.
     * 
     * @param ch the character to append
     */
    private void append(char ch) {
        lastAppend = ch;
        outputBuffer.append(ch);
        contentAppendedAfterLastIdentifier = true;
    }
    
    /**
     * Determines if current character is whitespace.
     * 
     * @return true if the character is whitespace
     */
    private boolean isWhitespace() {
        return ch == CARRIAGE_RETURN || ch == SPACE || ch == TAB || ch == LINE_FEED;        
    }

    /**
     * Load next character.
     */
    private void nextChar() {
        if (!endReached) {
            if (pos < script.length()) {
                ch = script.charAt(pos++);
            } else {
                endReached = true;
                ch = 0;
            }
        }
    }

    /**
     * Adds an identifier to output.
     */
    private void renderIdentifier() {
        if (!contentAppendedAfterLastIdentifier)
            append(SPACE);
        append(ch);
        nextChar();
        while (Character.isJavaIdentifierPart(ch)) {
            append(ch);
            nextChar();
        }
        contentAppendedAfterLastIdentifier = false;
    }

    /**
     * Adds quoted String starting at current character to output.
     */
    private void renderString() {
        char startCh = ch; // Save quote char
        append(ch);
        nextChar();
        while (true) {
            if ((ch == LINE_FEED) || (ch == CARRIAGE_RETURN) || (endReached)) {
                // JavaScript error: string not terminated
                return;
            } else {
                if (ch == '\\') {
                    append(ch);
                    nextChar();
                    if ((ch == LINE_FEED) || (ch == CARRIAGE_RETURN) || (endReached)) {
                        // JavaScript error: string not terminated
                        return;
                    }
                    append(ch);
                    nextChar();
                } else {
                    append(ch);
                    if (ch == startCh) {
                        nextChar();
                        return;
                    }
                    nextChar();
                }
            }
        }
    }

    /**
     * Moves cursor past a line comment.
     */
    private void skipLineComment() {
        while ((ch != CARRIAGE_RETURN) && (ch != LINE_FEED)) {
            if (endReached) {
                return;
            }
            nextChar();
        }
    }

    /**
     * Moves cursor past a block comment.
     */
    private void skipBlockComment() {
        while (true) {
            if (endReached) {
                return;
            }
            if (ch == '*') {
                nextChar();
                if (ch == '/') {
                    nextChar();
                    return;
                }
            } else
                nextChar();
        }
    }
    
    /**
     * Renders a new line character, provided previously rendered character 
     * is not a newline.
     */
    private void renderNewLine() {
        if (lastAppend != '\n' && lastAppend != '\r') {
            append('\n');
        }
    }
    
    /**
     * Moves cursor past white space (including newlines).
     */
    private void skipWhiteSpace() {
        if (ch == LINE_FEED || ch == CARRIAGE_RETURN) {
            renderNewLine();
        } else {
            append(ch);
        }
        nextChar();
        while (ch == LINE_FEED || ch == CARRIAGE_RETURN || ch == SPACE || ch == TAB) {
            if (ch == LINE_FEED || ch == CARRIAGE_RETURN) {
                renderNewLine();
            }
            nextChar();
        }
    }
}

   
    
    
  








Related examples in the same category

1.Listing All Script Engines
2.Running Scripts with Java Script Engine
3.Execute Javascript script in a file
4.Variables bound through ScriptEngine
5.Catch ScriptException
6.Any script have to be compiled into intermediate code.
7.With Compilable interface you store the intermediate code of an entire script
8.List the script engines
9.Run JavaScript and get the result by using Java
10.Pass parameter to JavaScript through Java code
11.Get the value in JavaScript from Java Code by reference the variable name
12.Working with Compilable Scripts
13.Call a JavaScript function three times
14.Save the compiled JavaScript to CompiledScript objectSave the compiled JavaScript to CompiledScript object
15.Invoke an function
16.Using thread to run JavaScript by Java
17.Get Script engine by extension name
18.Get a ScriptEngine by MIME type
19.Retrieving Script Engines by Name
20.Retrieving the Metadata of Script Engines
21.Retrieving the Supported File Extensions of a Scripting Engine
22.Retrieving the Supported Mime Types of a Scripting Engine
23.Retrieving the Registered Name of a Scripting Engine
24.Executing Scripts from Java Programs
25.Read and execute a script source file
26.Using Java Objects in JavaScript
27.Pass or retrieve values from a scripting engine (jdk1.6)
28.Use an external file containing the javascript code. The .JS file is loaded from the classpath.
29.Use Java scripting engine
30.Run Javascript function with ScriptEngine
31.Use Java scripting engine (JDK 1.6)
32.Use an external file containing the javascript code
33.Java Language Binding with JavaScript
34.Escape and unescape javascript code
35.Utility to take xml string and convert it to a javascript based tree within html.
36.JavaScript Utils
37.Various Javascript code utilities.
38.JavaScript functions in Java. Internally calls Rhino's implementation of the function calls.