php实现压缩合并js的方法【附demo源码下载】

5年以前  |  阅读数:756 次  |  编程语言:PHP 

本文实例讲述了php实现压缩合并js的方法。分享给大家供大家参考,具体如下:

test.php文件如下:


    require_once('jsmin.php');
    $files = glob("js/*.js");
    $js = "";
    foreach($files as $file) {
      $js .= JSMin::minify(file_get_contents($file));
    }
    file_put_contents("combined.js", $js);
    echo "success";

jsmin.php文件如下:


    <?php
    /**
     * jsmin.php - PHP implementation of Douglas Crockford's JSMin.
     *
     * This is pretty much a direct port of jsmin.c to PHP with just a few
     * PHP-specific performance tweaks. Also, whereas jsmin.c reads from stdin and
     * outputs to stdout, this library accepts a string as input and returns another
     * string as output.
     *
     * PHP 5 or higher is required.
     *
     * Permission is hereby granted to use this version of the library under the
     * same terms as jsmin.c, which has the following license:
     *
     * --
     * Copyright (c) 2002 Douglas Crockford (www.crockford.com)
     *
     * Permission is hereby granted, free of charge, to any person obtaining a copy of
     * this software and associated documentation files (the "Software"), to deal in
     * the Software without restriction, including without limitation the rights to
     * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
     * of the Software, and to permit persons to whom the Software is furnished to do
     * so, subject to the following conditions:
     *
     * The above copyright notice and this permission notice shall be included in all
     * copies or substantial portions of the Software.
     *
     * The Software shall be used for Good, not Evil.
     *
     * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
     * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     * SOFTWARE.
     * --
     *
     * @package JSMin
     * @author Ryan Grove <ryan@wonko.com>
     * @copyright 2002 Douglas Crockford <douglas@crockford.com> (jsmin.c)
     * @copyright 2008 Ryan Grove <ryan@wonko.com> (PHP port)
     * @copyright 2012 Adam Goforth <aag@adamgoforth.com> (Updates)
     * @license http://opensource.org/licenses/mit-license.php MIT License
     * @version 1.1.2 (2012-05-01)
     * @link https://github.com/rgrove/jsmin-php
     */
    class JSMin {
     const ORD_LF      = 10;
     const ORD_SPACE     = 32;
     const ACTION_KEEP_A   = 1;
     const ACTION_DELETE_A  = 2;
     const ACTION_DELETE_A_B = 3;
     protected $a      = '';
     protected $b      = '';
     protected $input    = '';
     protected $inputIndex = 0;
     protected $inputLength = 0;
     protected $lookAhead  = null;
     protected $output   = '';
     // -- Public Static Methods --------------------------------------------------
     /**
      * Minify Javascript
      *
      * @uses __construct()
      * @uses min()
      * @param string $js Javascript to be minified
      * @return string
      */
     public static function minify($js) {
      $jsmin = new JSMin($js);
      return $jsmin->min();
     }
     // -- Public Instance Methods ------------------------------------------------
     /**
      * Constructor
      *
      * @param string $input Javascript to be minified
      */
     public function __construct($input) {
      $this->input    = str_replace("\r\n", "\n", $input);
      $this->inputLength = strlen($this->input);
     }
     // -- Protected Instance Methods ---------------------------------------------
     /**
      * Action -- do something! What to do is determined by the $command argument.
      *
      * action treats a string as a single character. Wow!
      * action recognizes a regular expression if it is preceded by ( or , or =.
      *
      * @uses next()
      * @uses get()
      * @throws JSMinException If parser errors are found:
      *     - Unterminated string literal
      *     - Unterminated regular expression set in regex literal
      *     - Unterminated regular expression literal
      * @param int $command One of class constants:
      *   ACTION_KEEP_A   Output A. Copy B to A. Get the next B.
      *   ACTION_DELETE_A  Copy B to A. Get the next B. (Delete A).
      *   ACTION_DELETE_A_B Get the next B. (Delete B).
     */
     protected function action($command) {
      switch($command) {
       case self::ACTION_KEEP_A:
        $this->output .= $this->a;
       case self::ACTION_DELETE_A:
        $this->a = $this->b;
        if ($this->a === "'" || $this->a === '"') {
         for (;;) {
          $this->output .= $this->a;
          $this->a    = $this->get();
          if ($this->a === $this->b) {
           break;
          }
          if (ord($this->a) <= self::ORD_LF) {
           throw new JSMinException('Unterminated string literal.');
          }
          if ($this->a === '\\') {
           $this->output .= $this->a;
           $this->a    = $this->get();
          }
         }
        }
       case self::ACTION_DELETE_A_B:
        $this->b = $this->next();
        if ($this->b === '/' && (
          $this->a === '(' || $this->a === ',' || $this->a === '=' ||
          $this->a === ':' || $this->a === '[' || $this->a === '!' ||
          $this->a === '&' || $this->a === '|' || $this->a === '?' ||
          $this->a === '{' || $this->a === '}' || $this->a === ';' ||
          $this->a === "\n" )) {
         $this->output .= $this->a . $this->b;
         for (;;) {
          $this->a = $this->get();
          if ($this->a === '[') {
           /*
            inside a regex [...] set, which MAY contain a '/' itself. Example: mootools Form.Validator near line 460:
             return Form.Validator.getValidator('IsEmpty').test(element) || (/^(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]\.?){0,63}[a-z0-9!#$%&'*+/=?^_`{|}~-]@(?:(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)*[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\])$/i).test(element.get('value'));
           */
           for (;;) {
            $this->output .= $this->a;
            $this->a = $this->get();
            if ($this->a === ']') {
              break;
            } elseif ($this->a === '\\') {
             $this->output .= $this->a;
             $this->a    = $this->get();
            } elseif (ord($this->a) <= self::ORD_LF) {
             throw new JSMinException('Unterminated regular expression set in regex literal.');
            }
           }
          } elseif ($this->a === '/') {
           break;
          } elseif ($this->a === '\\') {
           $this->output .= $this->a;
           $this->a    = $this->get();
          } elseif (ord($this->a) <= self::ORD_LF) {
           throw new JSMinException('Unterminated regular expression literal.');
          }
          $this->output .= $this->a;
         }
         $this->b = $this->next();
        }
      }
     }
     /**
      * Get next char. Convert ctrl char to space.
      *
      * @return string|null
      */
     protected function get() {
      $c = $this->lookAhead;
      $this->lookAhead = null;
      if ($c === null) {
       if ($this->inputIndex < $this->inputLength) {
        $c = substr($this->input, $this->inputIndex, 1);
        $this->inputIndex += 1;
       } else {
        $c = null;
       }
      }
      if ($c === "\r") {
       return "\n";
      }
      if ($c === null || $c === "\n" || ord($c) >= self::ORD_SPACE) {
       return $c;
      }
      return ' ';
     }
     /**
      * Is $c a letter, digit, underscore, dollar sign, or non-ASCII character.
      *
      * @return bool
      */
     protected function isAlphaNum($c) {
      return ord($c) > 126 || $c === '\\' || preg_match('/^[\w\$]$/', $c) === 1;
     }
     /**
      * Perform minification, return result
      *
      * @uses action()
      * @uses isAlphaNum()
      * @uses get()
      * @uses peek()
      * @return string
      */
     protected function min() {
      if (0 == strncmp($this->peek(), "\xef", 1)) {
        $this->get();
        $this->get();
        $this->get();
      } 
      $this->a = "\n";
      $this->action(self::ACTION_DELETE_A_B);
      while ($this->a !== null) {
       switch ($this->a) {
        case ' ':
         if ($this->isAlphaNum($this->b)) {
          $this->action(self::ACTION_KEEP_A);
         } else {
          $this->action(self::ACTION_DELETE_A);
         }
         break;
        case "\n":
         switch ($this->b) {
          case '{':
          case '[':
          case '(':
          case '+':
          case '-':
          case '!':
          case '~':
           $this->action(self::ACTION_KEEP_A);
           break;
          case ' ':
           $this->action(self::ACTION_DELETE_A_B);
           break;
          default:
           if ($this->isAlphaNum($this->b)) {
            $this->action(self::ACTION_KEEP_A);
           }
           else {
            $this->action(self::ACTION_DELETE_A);
           }
         }
         break;
        default:
         switch ($this->b) {
          case ' ':
           if ($this->isAlphaNum($this->a)) {
            $this->action(self::ACTION_KEEP_A);
            break;
           }
           $this->action(self::ACTION_DELETE_A_B);
           break;
          case "\n":
           switch ($this->a) {
            case '}':
            case ']':
            case ')':
            case '+':
            case '-':
            case '"':
            case "'":
             $this->action(self::ACTION_KEEP_A);
             break;
            default:
             if ($this->isAlphaNum($this->a)) {
              $this->action(self::ACTION_KEEP_A);
             }
             else {
              $this->action(self::ACTION_DELETE_A_B);
             }
           }
           break;
          default:
           $this->action(self::ACTION_KEEP_A);
           break;
         }
       }
      }
      return $this->output;
     }
     /**
      * Get the next character, skipping over comments. peek() is used to see
      * if a '/' is followed by a '/' or '*'.
      *
      * @uses get()
      * @uses peek()
      * @throws JSMinException On unterminated comment.
      * @return string
      */
     protected function next() {
      $c = $this->get();
      if ($c === '/') {
       switch($this->peek()) {
        case '/':
         for (;;) {
          $c = $this->get();
          if (ord($c) <= self::ORD_LF) {
           return $c;
          }
         }
        case '*':
         $this->get();
         for (;;) {
          switch($this->get()) {
           case '*':
            if ($this->peek() === '/') {
             $this->get();
             return ' ';
            }
            break;
           case null:
            throw new JSMinException('Unterminated comment.');
          }
         }
        default:
         return $c;
       }
      }
      return $c;
     }
     /**
      * Get next char. If is ctrl character, translate to a space or newline.
      *
      * @uses get()
      * @return string|null
      */
     protected function peek() {
      $this->lookAhead = $this->get();
      return $this->lookAhead;
     }
    }
    // -- Exceptions ---------------------------------------------------------------
    class JSMinException extends Exception {}
    ?>

完整实例代码点击此处[本站下载](http://xiazai.jb51.net/201609/yuanma/jsmin-php-master-codes(jb51.net).rar)。

更多关于PHP相关内容感兴趣的读者可查看本站专题:《php文件操作总结》、《PHP目录操作技巧汇总》、《PHP基本语法入门教程》、《PHP运算与运算符用法总结》、《php面向对象程序设计入门教程》、《PHP网络编程技巧总结》、《php字符串(string)用法总结》、《PHP数组(Array)操作技巧大全》、《php+mysql数据库操作入门教程》及《php常见数据库操作技巧汇总

希望本文所述对大家PHP程序设计有所帮助。

 相关文章:
PHP分页显示制作详细讲解
SSH 登录失败:Host key verification failed
获取IMSI
将二进制数据转为16进制以便显示
获取IMEI
文件下载
贪吃蛇
双位运算符
PHP自定义函数获取搜索引擎来源关键字的方法
Java生成UUID
发送邮件
年的日历图
提取后缀名
在Zeus Web Server中安装PHP语言支持
让你成为最历害的git提交人
Yii2汉字转拼音类的实例代码
再谈PHP中单双引号的区别详解
指定应用ID以获取对应的应用名称
Python 2与Python 3版本和编码的对比
php封装的page分页类完整实例