1. [代码]JavaScriptCompressor.java
/**
 * 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.
     * flash动画
     * @param ch the character to append
     */http://www.huiyi8.com/donghua/​
    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();
        }
    }
}

最新文章

  1. html你可能还不知道的一些知识点
  2. Swift高级语法学习总结(转)
  3. c++大数模板
  4. CodeForces 148D-Bag of mice(概率dp)
  5. dt dd 如何在同一行上
  6. 盒子游戏(The Seventh Hunan Collegiate Programming Contest)
  7. Python:学会创建并调用函数
  8. socket 异步通信的一些问题
  9. springboot学习随笔(二):简单的HelloWorld
  10. ABAP非Unicode系统中字符串拼接(CONCATENATE)时吃字符问题
  11. Mybaits
  12. HAProxy出现&quot;远程主机强迫关闭了一个现有的连接 &quot; 的错误及解决
  13. HDU 1109 Run Away
  14. JSONObject基本内容(三)
  15. C#调用百度地图API经验分享(三)
  16. ERROR 2002 (HY000): Can&#39;t connect to local MySQL server through socket &#39;/var/lib/mysql/mysql.sock&#39; (2) 的解决办法
  17. Python的多线程和多进程
  18. 02 How to Write Go Code 如何编写go语言代码
  19. 20181120-8 Beta阶段第2周/共2周 Scrum立会报告+燃尽图 06
  20. Mysql Communications link failure 问题的解决

热门文章

  1. [MFC] TabControl选项卡的使用
  2. Day 7 Linux之系统监控、硬盘分区等
  3. 同时在windows和linux环境开发时换行符的处理
  4. 测试开发系列之Python开发mock接口(三)
  5. NFV产品如何才能走向规模商用
  6. P1551 亲戚 洛谷
  7. codevs 2669 简单的试炼
  8. 【.Net 学习系列】-- 利用Aspose转换Excel为PDF文件
  9. python内存诊断
  10. mysql修改删除列,删除有外键依赖的列