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

JavaScriptMinifier C#压缩Javascript的更多相关文章

  1. node.js 使用 UglifyJS2 高效率压缩 javascript 文件

    UglifyJS2 这个工具使用很长时间了,但之前都是在 gulp 自动构建 时用到了 UglifyJS 算法进行压缩. 最近玩了一下 UglifyJS2 ,做了一个 在线压缩javascript工具 ...

  2. 使用Ant命令压缩JavaScript文件

    压缩JavaScript文件可以减少代码尺寸,保护源代码,节省网络带宽,加快页面打开速度,甚至优化JS代码.Yahoo有一个压缩JS的工具叫做YUI compressor, Google也有一个工具叫 ...

  3. YUI Compressor 压缩 JavaScript 原理-《转载》

    YUI Compressor 压缩 JavaScript 的内容包括: 移除注释 移除额外的空格 细微优化 标识符替换(Identifier Replacement) YUI Compressor包括 ...

  4. 压缩javascript文件方法

    写在前面的话:正式部署前端的时候,javascript文件一般需要压缩,并生成相应的sourcemap文件,对于一些小型的项目开发,这里提供一个简单的办法. ======正文开始====== 1.下载 ...

  5. gzip压缩JavaScript

    为了提高客户端的体验效果,RIA开发逐渐兴起.这样会项目中会充斥的大量的JavaScript代码,与此同时会消耗客户端浏览器性能.对于 Ext 实现的 one page one application ...

  6. Grunt 使用(二)uglify插件压缩javascript代码

    本文在配置grunt基本环境的基础下,讲解如何使用grunt-contrib-uglify进行javascript压缩 本文只介绍了grunt-contrib-uglify插件的一种压缩方式适用于大部 ...

  7. 使用jsmin压缩javascript脚本

    官方地址:http://www.crockford.com/javascript/jsmin.html 点击页下方的”zip file containing an MS-DOS.exe file“下载 ...

  8. 使用Google Closure Compiler高级压缩Javascript代码

    背景 前端开发中,特别是移动端,Javascript代码压缩已经成为上线必备条件. 如今主流的Js代码压缩工具主要有: 1)Uglify http://lisperator.net/uglifyjs/ ...

  9. 使用Google Closure Compiler高级压缩Javascript代码注意的几个地方

    介绍 GCC(Google Closure Compiler)是由谷歌发布的Js代码压缩编译工具.它可以做到分析Js的代码,移除不需要的代码(dead code),并且去重写它,最后再进行压缩. 三种 ...

随机推荐

  1. 慕课网-安卓工程师初养成-3-3 Java中的赋值运算符

    来源:http://www.imooc.com/code/1298 赋值运算符是指为变量或常量指定数值的符号.如可以使用 “=” 将右边的表达式结果赋给左边的操作数. Java 支持的常用赋值运算符, ...

  2. 'UIShell.OSGi.MvcWebExtension.BundleRuntimeControllerFactory' did not return a controller for the name 'Home'.

    在使用osgi.net 框架的时候,有时会遇到这样的错误: 解决办法: 1. 检查项目文件夹下的 log 日志文件,因 osgi.net 在运行时(包括异常和操作)都会在项目的目录下生成 日志文件,并 ...

  3. NOIP2004 虫食算

    描述 所谓虫食算,就是原先的算式中有一部分被虫子啃掉了,需要我们根据剩下的数字来判定被啃掉的字母.来看一个简单的例子:43#9865#045+ 8468#6633= 44445506678其中#号代表 ...

  4. Bug修复问题

    采用下面的代码,访问网页:http://www.weather.com.cn/data/cityinfo/101010100.html,想读取下图中红框中的内容,但是抛出了IOException,通过 ...

  5. asp.net(c#)修改时的赋值操作

    赋值操作方法(将信息显示至文本框中): public void Show_Infobase(int _peoid) { DataSet ds = new DataSet(); ds = platbll ...

  6. typedef 与define 的区别

    typedef和#define的用法与区别   typedef和#define的用法与区别 一.typedef的用法 在C/C++语言中,typedef常用来定义一个标识符及关键字的别名,它是语言编译 ...

  7. jQuery右键菜单ContextMenu使用笔记

    插件下载地址:http://www.trendskitchens.co.nz/jquery/contextmenu/jquery.contextmenu.r2.packed.js 和http://ww ...

  8. javascript设计模式-观察者模式

    观察者模式定义了一种一对多的关系,让多个观察者对象同时监听某一个主题对象,这个对象的状态发生变化时就会通知所有的观察者对象,使得它们能够自动更新自己. UML示意图: 其中的角色: Subject:主 ...

  9. MongoDB 3: 使用中的问题,及其应用场景

    导读:用MongoDB去存储非关系型的数据,是一个比较正确的选择.但是,如果只是用MongoDB,那么也会出现一些问题.MongoDB,尤其使用的最佳场景,更多的时候,需要结合关系型数据库共同解决问题 ...

  10. 有联系的jQuery选择器

    1.包含关系 2.相邻关系 //JavaScript$(document).ready(function () { $(".studentName + div").hide(); ...