JavaScriptMinifier C#压缩Javascript
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Text;
using System.IO; /// <summary>
/// 提供压缩 JavaScript 代码的能力。
/// </summary>
public sealed class JavaScriptMinifier
{
#region 私有字段 private const int EOF = -1; private readonly StringBuilder _JsBuilder;
private readonly TextReader _JsReader;
private int _TheA = Convert.ToInt32('\n');
private int _TheB;
private int _TheLookahead = EOF; #endregion #region 构造函数 /// <summary>
/// 初始化 <see cref="JavaScriptMinifier"/> 类的新实例。
/// </summary>
/// <param name="jsReader">包含要压缩的 JavaScript 代码的 <see cref="TextReader"/>。</param>
private JavaScriptMinifier(TextReader jsReader)
{
if (jsReader == null) throw new ArgumentNullException("jsReader"); this._JsReader = jsReader;
this._JsBuilder = new StringBuilder();
} #endregion #region 静态方法 /// <summary>
/// 压缩指定的 JavaScript 代码。
/// </summary>
/// <param name="js">包含要压缩的 JavaScript 代码的 <see cref="StringBuilder"/>。</param>
/// <returns>返回包含压缩后的 JavaScript 代码的 <see cref="StringBuilder"/>。</returns>
public static StringBuilder Minify(StringBuilder js) { return Minify(new StringReader(js.ToString())); } /// <summary>
/// 压缩指定的 JavaScript 代码。
/// </summary>
/// <param name="jsCode">要压缩的 JavaScript 代码。</param>
/// <returns>返回包含压缩后的 JavaScript 代码的 <see cref="StringBuilder"/>。</returns>
public static StringBuilder Minify(string jsCode) { return Minify(new StringReader(jsCode)); } /// <summary>
/// 压缩指定的 JavaScript 代码。
/// </summary>
/// <param name="jsReader">包含要压缩的 JavaScript 代码的 <see cref="TextReader"/>。</param>
/// <returns>返回包含压缩后的 JavaScript 代码的 <see cref="StringBuilder"/>。</returns>
public static StringBuilder Minify(TextReader jsReader)
{
JavaScriptMinifier jsmin = new JavaScriptMinifier(jsReader); jsmin._Jsmin(); return jsmin._JsBuilder;
} #endregion #region 私有方法 private void _Jsmin()
{
this._Action(3); while (this._TheA != EOF)
{
switch ((Char)this._TheA)
{
case ' ':
if (_IsAlphanum(this._TheB)) this._Action(1);
else this._Action(2); break;
case '\n':
switch ((Char)this._TheB)
{
case '{':
case '[':
case '(':
case '+':
case '-':
this._Action(1); break;
case ' ':
this._Action(3); break;
default:
if (_IsAlphanum(this._TheB)) this._Action(1);
else this._Action(2); break;
} break;
default:
switch ((Char)this._TheB)
{
case ' ':
if (_IsAlphanum(this._TheA))
{
this._Action(1); break;
} this._Action(3); break;
case '\n':
switch ((Char)this._TheA)
{
case '}':
case ']':
case ')':
case '+':
case '-':
case '"':
case '\'':
this._Action(1); break;
default:
if (_IsAlphanum(this._TheA)) this._Action(1);
else this._Action(3); break;
} break;
default:
this._Action(1); break;
} break;
}
}
} private void _Action(int d)
{
if (d <= 1) this._Put(this._TheA);
if (d <= 2)
{
this._TheA = this._TheB; if (this._TheA == '\'' || this._TheA == '"')
{
for (; ; )
{
this._Put(this._TheA);
this._TheA = this._Get(); if (this._TheA == this._TheB) break;
if (this._TheA <= '\n') throw new Exception(string.Format("Error: JSMIN unterminated string literal: {0}", this._TheA));
if (this._TheA != '\\') continue; this._Put(this._TheA);
this._TheA = this._Get();
}
}
} if (d > 3) return; this._TheB = this._Next(); if (this._TheB != '/' || ((((((((((((this._TheA != '(' && this._TheA != ',') && this._TheA != '=') && this._TheA != '[') && this._TheA != '!') && this._TheA != ':') && this._TheA != '&') && this._TheA != '|') && this._TheA != '?') && this._TheA != '{') && this._TheA != '}') && this._TheA != ';') && this._TheA != '\n')) return; this._Put(this._TheA);
this._Put(this._TheB); for (; ; )
{
this._TheA = this._Get(); if (this._TheA == '/') break; if (this._TheA == '\\')
{
this._Put(this._TheA);
this._TheA = this._Get();
}
else if (this._TheA <= '\n') throw new Exception(string.Format("Error: JSMIN unterminated Regular Expression literal : {0}.", this._TheA)); this._Put(this._TheA);
} this._TheB = this._Next();
} private int _Next()
{
int c = this._Get();
const int s = (int)'*'; if (c == '/')
{
switch ((Char)this._Peek())
{
case '/':
for (; ; )
{
c = this._Get(); if (c <= '\n') return c;
}
case '*':
this._Get(); for (; ; )
{
switch (this._Get())
{
case s:
if (this._Peek() == '/')
{
this._Get(); return Convert.ToInt32(' ');
} break;
case EOF:
throw new Exception("Error: JSMIN Unterminated comment.");
}
}
default:
return c;
}
} return c;
} private int _Peek()
{
this._TheLookahead = this._Get(); return this._TheLookahead;
} private int _Get()
{
int c = this._TheLookahead;
this._TheLookahead = EOF; if (c == EOF) c = this._JsReader.Read(); return c >= ' ' || c == '\n' || c == EOF ? c : (c == '\r' ? '\n' : ' ');
} private void _Put(int c) { this._JsBuilder.Append((char)c); } private static bool _IsAlphanum(int c) { return ((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || c == '_' || c == '$' || c == '\\' || c > 126); } #endregion
}
JavaScriptMinifier C#压缩Javascript的更多相关文章
- node.js 使用 UglifyJS2 高效率压缩 javascript 文件
UglifyJS2 这个工具使用很长时间了,但之前都是在 gulp 自动构建 时用到了 UglifyJS 算法进行压缩. 最近玩了一下 UglifyJS2 ,做了一个 在线压缩javascript工具 ...
- 使用Ant命令压缩JavaScript文件
压缩JavaScript文件可以减少代码尺寸,保护源代码,节省网络带宽,加快页面打开速度,甚至优化JS代码.Yahoo有一个压缩JS的工具叫做YUI compressor, Google也有一个工具叫 ...
- YUI Compressor 压缩 JavaScript 原理-《转载》
YUI Compressor 压缩 JavaScript 的内容包括: 移除注释 移除额外的空格 细微优化 标识符替换(Identifier Replacement) YUI Compressor包括 ...
- 压缩javascript文件方法
写在前面的话:正式部署前端的时候,javascript文件一般需要压缩,并生成相应的sourcemap文件,对于一些小型的项目开发,这里提供一个简单的办法. ======正文开始====== 1.下载 ...
- gzip压缩JavaScript
为了提高客户端的体验效果,RIA开发逐渐兴起.这样会项目中会充斥的大量的JavaScript代码,与此同时会消耗客户端浏览器性能.对于 Ext 实现的 one page one application ...
- Grunt 使用(二)uglify插件压缩javascript代码
本文在配置grunt基本环境的基础下,讲解如何使用grunt-contrib-uglify进行javascript压缩 本文只介绍了grunt-contrib-uglify插件的一种压缩方式适用于大部 ...
- 使用jsmin压缩javascript脚本
官方地址:http://www.crockford.com/javascript/jsmin.html 点击页下方的”zip file containing an MS-DOS.exe file“下载 ...
- 使用Google Closure Compiler高级压缩Javascript代码
背景 前端开发中,特别是移动端,Javascript代码压缩已经成为上线必备条件. 如今主流的Js代码压缩工具主要有: 1)Uglify http://lisperator.net/uglifyjs/ ...
- 使用Google Closure Compiler高级压缩Javascript代码注意的几个地方
介绍 GCC(Google Closure Compiler)是由谷歌发布的Js代码压缩编译工具.它可以做到分析Js的代码,移除不需要的代码(dead code),并且去重写它,最后再进行压缩. 三种 ...
随机推荐
- Memcached、Redis和MongoDB的区别
Memcached和Redis都是内存数据库. Memcached是多线程运行的: Redis单线程是单线程运行的: MongoDB是文档型的非关系型数据库..Net:RavenDB.
- [神器推荐]node-webkit:跨平台桌面web应用的神器,非常有用(转)
11月8号在清华拍的银杏树 http://finalshares.com/read-931
- 常用上传shell脚本
#!/bin/bash FTP_IP=127.0.0.1 FTP_USER="aaa" FTP_PSW="bbb" GAME_NAME="ccc&qu ...
- struts2拦截器拦截成功后每次请求都出现拦截时的错误信息
action中验证方法 在执行execute之前执行 @Override public void validate() { // TODO Auto-generated metho ...
- 查看Eclipse版本号的方法
查看Eclipse版本号的方法如下所示: 1:假设Eclipse已打开Eclipse的菜单栏: Help-->About Eclipse弹出框中会显示一排logo,点击eclipse的那个log ...
- mysql 二进制安装文件 下载
在linuex环境下安装mysql,二进制安装包是最合适的方式,下载下来不用编译就可用了. 官方说明文档:http://dev.mysql.com/doc/refman/5.1/en/binary-i ...
- WebApi简单使用
一.建立一个WebApi项目 WebApi项目的文件和MVC的基本项目内容差不多,都有Models View Controller等,区别在于WebApi的控制器继承的不是Controller类,而是 ...
- Solarwinds Orion NPM实战视频演示
Orion Network Performance Monitor是全面的带宽性能监控和故障管理软件,能监控并收集来自路由器.交换机.服务器和其他SNMP设备中的数据,您可以直接从Web浏览器上观察您 ...
- docker学习(一)
atomic使用有点费劲,我改为centos7来做为学习环境. 1 安装 epel源就自带,目前版本是1.10.3 yum -y install docker docker version Clien ...
- ENVI二次开发模式下的Landsat数据读取
从usgs网站或者马里兰大学下载TM或Landsat原始数据,数据可能包括9个tif数据,两个txt文件和一个gtf文件.示例结构如下: ENVI下可以直接打开*_MTL.txt文件打开,打开后波段列 ...