首页 > 开发 > PHP > 正文

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

2024-05-04 22:52:46
字体:
来源:转载
供稿:网友

本文实例讲述了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 {}?>            
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表