通过Java压缩JavaScript代码实例分享

 更新时间:2017年12月06日 16:03:05   作者:wgd7  
这篇文章主要介绍了通过Java压缩JavaScript代码实例分享,具有一定参考价值,需要的朋友可以了解下。

通过移除空行和注释来压缩 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 <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.
   * 
   * @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代码实例分享的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站其他相关专题,如有不足之处,欢迎留言指出。感谢朋友们对本站的支持!

相关文章

  • Spring中AOP概念与两种动态代理模式原理详解

    Spring中AOP概念与两种动态代理模式原理详解

    AOP是面向切面编程的技术,AOP基于IoC基础,是对OOP的有益补充,流行的AOP框架有Sping AOP、AspectJ,这篇文章主要给大家介绍了关于Spring中AOP概念与两种动态代理模式原理的相关资料,需要的朋友可以参考下
    2021-10-10
  • 盘点SpringBoot中@Async注解的遇到的坑点及解决办法

    盘点SpringBoot中@Async注解的遇到的坑点及解决办法

    SpringBoot是一个流行的Java开发框架,在异步编程方面,Spring Boot提供了@Async注解,它能够让方法异步执行,然而,在使用@Async注解时,有一些潜在的坑需要注意,本文将深入探讨Spring Boot中使用@Async注解时可能遇到的8大坑点,并提供相应的解决方案
    2024-03-03
  • Java反射机制,反射相关API,反射API使用方式(反射获取实体类字段名和注解值)

    Java反射机制,反射相关API,反射API使用方式(反射获取实体类字段名和注解值)

    这篇文章主要介绍了Java反射机制,反射相关API,反射API使用方式(反射获取实体类字段名和注解值),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-07-07
  • jdk源码阅读Collection详解

    jdk源码阅读Collection详解

    这篇文章主要介绍了jdk源码阅读Collection详解,具有一定借鉴价值,需要的朋友可以参考下
    2017-12-12
  • SpringBoot 整合MyBatis+MyBatis-Plus+MyBatisX插件使用

    SpringBoot 整合MyBatis+MyBatis-Plus+MyBatisX插件使用

    本文主要介绍了SpringBoot 整合MyBatis+MyBatis-Plus+MyBatisX插件使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2024-04-04
  • 基于常用json框架介绍和Jackson返回结果处理方式

    基于常用json框架介绍和Jackson返回结果处理方式

    这篇文章主要介绍了基于常用json框架介绍和Jackson返回结果处理方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-09-09
  • SpringBoot自定义动态数据源的流程步骤

    SpringBoot自定义动态数据源的流程步骤

    动态数据源,本质上是把多个数据源存储在一个 Map 中,当需要使用某一个数据源时,使用 key 获取指定数据源进行处理,本文将给大家介绍一下SpringBoot自定义动态数据源的流程步骤,需要的朋友可以参考下
    2024-06-06
  • Java中wait()与sleep()两者的不同深入解析

    Java中wait()与sleep()两者的不同深入解析

    在Java多线程编程中,wait()和sleep()是控制线程执行和等待的两个关键方法,但它们在应用场景和实现上有显著差异,这篇文章主要介绍了Java中wait()与sleep()两者的不同,需要的朋友可以参考下
    2024-11-11
  • Java将本地项目部署到Linux服务器的实践

    Java将本地项目部署到Linux服务器的实践

    本文主要介绍了Java将本地项目部署到Linux服务器的实践,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧<BR>
    2022-06-06
  • Spring集成Druid连接池及监控配置的全过程

    Spring集成Druid连接池及监控配置的全过程

    java程序很大一部分要操作数据库,为了提高性能操作数据库的时候,有不得不使用数据库连接池,下面这篇文章主要给大家介绍了关于Spring集成Druid连接池及监控配置的相关资料,需要的朋友可以参考下
    2021-09-09

最新评论