通过移除空行和注释来压缩 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 append()

* 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 JavaScriptCompressor 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();

}

}

}

java 代码压缩javascript_利用Java来压缩 JavaScript 代码详解相关推荐

  1. WEB后台--邮件和短信业务实现(包括Java一键实现、封装和异步)以及原理详解

    本来就打算针对一些固定的特别点的业务(QQ与网易邮件.拦截设计.短信.定时器等等)来进行记录以及解析原理,这些会比较零散记录在JavaWeb的分类里面,感兴趣的童鞋可以去看下. 有人问为什么要邮件短信 ...

  2. Java构造和解析Json数据的两种方法详解一

    在www.json.org上公布了很多JAVA下的json构造和解析工具,其中org.json和json-lib比较简单,两者使用上差不多但还是有些区别.下面首先介绍用json-lib构造和解析Jso ...

  3. java显示参数,Java中的隐式参数和显示参数实例详解

    在学习java的过程中,我们会遇到许多的问题.下面我们就来看看什么是隐式参数和显示参数. 显式参数,就是平时见到的在方法名括号中间的参数,就是所谓能看得见的参数www.cppcns.com. 隐式参数 ...

  4. java制作海报一:java使用Graphics2D 在图片上写字,文字换行算法详解

    文章目录 前言 一.直接上代码 1. 写字方法 2. 换行算法 二. 叙述换行算法 前言 代码都上传到GitHub了,这里仅仅是贴出来主要部分,GitHub传送门:https://github.com ...

  5. Java中创建String的两道面试题及详解

    转载自 Java中创建String的两道面试题及详解 我们知道创建一个String类型的变量一般有以下两种方法: String str1 = "abcd";String str2 ...

  6. java函数式编程归约reduce概念原理 stream reduce方法详解 reduce三个参数的reduce方法如何使用

    java函数式编程归约reduce概念原理 stream reduce方法详解 reduce三个参数的reduce方法如何使用

  7. php curl 模拟多线程,php利用curl 多线程 模拟 并发的详解

    php利用curl 多线程 模拟 并发的详解 发布于 2014-12-07 10:17:25 | 265 次阅读 | 评论: 0 | 来源: 网友投递 PHP开源脚本语言PHP(外文名: Hypert ...

  8. python 文字语音朗读-python 利用pyttsx3文字转语音过程详解

    这篇文章主要介绍了python 利用pyttsx3文字转语音过程详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 # -*- coding: ut ...

  9. python脚本语言采用声音作为手段_python 利用pyttsx3文字转语音过程详解

    这篇文章主要介绍了python 利用pyttsx3文字转语音过程详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下# -*- coding: utf ...

最新文章

  1. ACE框架解读 - 源码篇
  2. itunes未能连接到iphone_iTunes下载_苹果iTunes官方下载「32位|64位」
  3. sklearn 数据预处理1: StandardScaler
  4. POJ C++程序设计 编程题#2 魔兽世界之二:装备
  5. Go-技篇第二 命名规范
  6. C语言程序设计题解pdf,C语言程序设计题解与上机指导.pdf
  7. 现在主流人工智能(AI)方法的本质是什么?
  8. 电磁场与电磁波MIT版笔记
  9. 谷歌浏览器插件离线安装
  10. kindle安装插件和koreader
  11. 做生意的“四大方向”让你看清财富的本质
  12. 推荐系统:石器与青铜时代
  13. 皮皮虾无水印解析源码实战
  14. 2010计算机录制宏步骤,在word2010录制宏的操作
  15. 解决 C# GetPixel 和 SetPixel 效率问题
  16. 为什么父类引用可以指向子类对象 子类引用不能指向父类对象 泛型
  17. vs2017开发ActiveX(主讲OCX)(七)、方法
  18. 用Python实现DT算法
  19. 金仓数据库KingbaseES序列的操作
  20. 痞子衡嵌入式:PCM编码与Waveform音频文件(.wav)格式详解

热门文章

  1. 学会使用JDK API
  2. JAVA学习笔记-this隐式参数
  3. Visual Studio 2015年预览设置: 辅助安装程序说明
  4. 继承或者重写django的user model?
  5. mySAP标准培训教材全套列表
  6. SpringCloud的Eureka客户端(解决自动退出问题)
  7. [原创]解决某物流企业二维码打印问题
  8. 【报告分享】中国零售业公私域运营手册暨实施指引.pdf(附下载链接)
  9. java栈和队列_栈和队列的面试题Java
  10. 18b20温度检测及其lcd显示_单片机使用DS18B20测量温度的程序