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),并且去重写它,最后再进行压缩. 三种 ...
随机推荐
- winmail安装完成后,SMTP/POP3/ADMIN/HTTP/IMAP/LDAP服务不能启动?
问题原因: 1.特殊端口被占用,可以用命令netstat -ano 查看 2.阿帕奇网络服务 httpd 未开启 解决方案:开启服务后,登录管理工具,点注册,它会自动跳出"httpd通过防火 ...
- Kindle3与亚马逊
喜欢上亚马逊,偶尔会买些免费或极低价格的书,但始终无法把这些书传到“我的”kindle3上,原因是kindle3无法在中国注册,又绕不开DRM,同时经历了换屏.换主板,早已不是原来的kindle了.今 ...
- SQL必知必会笔记(1)
去SQL AXDB 中Query数据 Open the SQL > Connect > Select AXDB > new Query select REFID, ITEMID, R ...
- 百度面试题:从输入url到显示网页,后台发生了什么?
参考http://igoro.com/archive/what-really-happens-when-you-navigate-to-a-url/ http://www.cnblogs.com/we ...
- 慕课网-安卓工程师初养成-2-11 Java常量
来源:http://www.imooc.com/code/1256 所谓常量,我们可以理解为是一种特殊的变量,它的值被设定后,在程序运行过程中不允许改变. 语法:final 常量名 = 值; 程序中使 ...
- STL之vetor 排序
1 STL提供的Sort 算法 C++之所以得到这么多人的喜欢,是因为它既具有面向对象的概念,又保持了C语言高效的特点.STL 排序算法同样需要保持高效.因此,对于不同的需求,STL提供的不同的函数, ...
- 【PL/SQL练习】命名块: 存储过程、函数、触发器、包
创建时定义名称 2.可以被Oracle server 保存 3.可以被任何程序调用 4.可以被共享 存储过程: 1.不带参数的存储过程: SQL> create or replace proce ...
- APP发布Xcode7
一.准备工作 1>准备3.5寸.4寸.4.7寸.5.5寸的程序截图至少个1张,如果支持iPad,那么iPad截图也要有.这些截图尽量截取页面漂亮的,因为这些截图是要放在AppStore中展示的. ...
- Ajax.BeginForm 上传文件
在 Mvc 中上传文件时通常使用 Html.BeginForm 标签,同时对Form 添加属性 enctype = "multipart/form-data",前端代码如下: @H ...
- mongodb分组,的两种方式,先记一下
using MongoDB.Bson; using MongoDB.Driver; using MongoDB.Driver.Builders; using NationalUnion.AdGalle ...