利用Java来压缩 JavaScript 代码

2018-07-20    来源:open-open

容器云强势上线!快速搭建集群,上万Linux镜像随意使用
通过移除空行和注释来压缩 JavaScript 代码
/**
 * This file is part of the Echo Web Application Framework (hereinafter \"Echo\").
 * Copyright (C) 2002-2009 NextApp, Inc.
 *
 * 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();
        }
    }
}

标签: 代码

版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点!
本站所提供的图片等素材,版权归原作者所有,如需使用,请与原作者联系。

上一篇: java把Excel文件数据导入数据库

下一篇:Android JNI 跨线程使用JniEnv