【Java】通过移除空行和注释来压缩 JavaScript 代码
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();
}
}
}
【Java】通过移除空行和注释来压缩 JavaScript 代码的更多相关文章
- java正则表达式移除网页中注释代码
/** * 移除网页中注释掉的代码 * * @param str * @return */ public static String removedisablecode(String str) { P ...
- java简单统计.java文件中的有效代码行,空行,注释行
package regxdemo; import java.io.BufferedReader; import java.io.File; import java.io.FileNotFoundExc ...
- java编码规范_缩进和注释
1. 缩进排版(Indentation) 4个空格常被作为缩进排版的一个单位.缩进的确切解释并未详细指定(空格 vs. 制表符).一个制表符等于n个空格(视具体的编辑器而定,Eclipse ...
- Java基础学习总结(92)——Java编码规范之排版、注释及命名
为使开发人员养成良好的开发习惯,编写可读性强.易维护的程序,结合以往资料,现整理Java编码规范,将之作为开发人员的参照依据. 一.排版 1.相对独立的程序块之间必须加空行 下列情况应该使用一个空行: ...
- 007-使用python统计代码行数,空行以及注释
# 自己写过的程序,统计一下你写过多少行代码.包括空行和注释,但是要分别列出来 1.打开文件方法 1.1 以读文件的模式打开一个文件对象,使用Python内置的open()函数,传入文件名和标示符 f ...
- linux过滤旧文件中的空行和注释行剩余内容组成新文件
一.说明 在某些场景下我们想要将旧文件中空行和注释行过滤掉,将产生实际效果的行保留. 比如redis提供的配置示例文件中有很多用于说明的空行和注释行,我们想把产生实际效果的配置行筛选出来组成新的简洁的 ...
- java 生成jar包并保留注释
java 生成jar包并保留注释 CreationTime--2018年7月17日08点32分 Author:Marydon 1.选中java项目-->右键-->Export: 2.去 ...
- python 判断是否是空行或注释行
#coding:utf-8 '''''cdays-4-exercise-6.py 文件基本操作 @note: 文件读取写入, 列表排序, 字符串操作 @see: 字符串各方法可参考hekp(str)或 ...
- vim删除空行和注释
vim删除空行和注释 来源: http://jpuyy.com/2015/06/vim-delete-lines-using-regexp.html 删除空行 :g/^$/d 删除空行以及只有空格的 ...
随机推荐
- Eclipse 语言文件下载地址
http://www.eclipse.org/babel/downloads.php 更改配色: 安装新软件: http://eclipse-color-theme.github.com/update
- 2018 ICPC 沈阳网络赛预赛 Supreme Number(找规律)
[传送门]https://nanti.jisuanke.com/t/31452 [题目大意]:给定一个数字(最大可达10100),现在要求不超过它的最大超级质数.超级质数定义:对于一个数,把它看成数字 ...
- input标签附带提示文字(bootstrap里面输入框的两侧同时添加额外元素)
一直不太喜欢用定位,今天写界面的时候,要在输入框右边添加默认的元素符号. 第一次尝试,因为本身项目用的是bootstrap所以就想利用输入框的两侧同时添加额外元素. 但是写了代码发现效果不同. 第二次 ...
- Chrome 浏览器安装Vue插件方法 (十分详细)
博主最近在研究Vue,无奈新手想安装Chrome的Vue插件,整理下安装流程: 1.首先去github下载vue.zip文件插件(还有npm安装方法这里就不介绍了自行百度)下载地址:https://g ...
- 【c++】面向对象程序设计之关于继承
面向对象程序设计的核心思想是数据抽象(类的接口与实现分离).继承和动态绑定 基类 虚函数:基类希望派生类各自定义适合自身的版本的函数 在c++中,当我们使用基类的引用或指针调用虚函数时将发生动态绑定. ...
- 转:国内Top500Android应用分析报告
转自:https://mp.weixin.qq.com/s?__biz=MzA5OTMxMjQzMw==&mid=2648112527&idx=1&sn=b23c1b5f3e3 ...
- 项目整理--Echarts前端后台的贯通写法
项目整理–Echarts前端后台的贯通写法 注:下面所有内容建立在FH admin开源框架和eharts插件基础上,建议观看本案例者进行了解. 业务逻辑 绘制两张图表.分别显示城市空间库和其它数据仓库 ...
- [HTML5] Show Images of Differing Resolutions Depending on the Viewport Width with srcset
For small viewports, we want to save bandwidth and we may be dealing with slow speeds; so it's very ...
- js中对arry数组的各种操作小结 瀑布流AJAX无刷新加载数据列表--当页面滚动到Id时再继续加载数据 web前端url传递值 js加密解密 HTML中让表单input等文本框为只读不可编辑的方法 js监听用户的键盘敲击事件,兼容各大主流浏览器 HTML特殊字符
js中对arry数组的各种操作小结 最近工作比较轻松,于是就花时间从头到尾的对js进行了详细的学习和复习,在看书的过程中,发现自己平时在做项目的过程中有很多地方想得不过全面,写的不够合理,所以说啊 ...
- C3P0连接池配置和实现详解(转)
一.配置 <c3p0-config> <default-config> <!--当连接池中的连接耗尽的时候c3p0一次同时获取的连接数.Default: 3 --> ...