Development

Changeset 10353

You must first sign up to be able to contribute.

Changeset 10353

Show
Ignore:
Timestamp:
07/18/08 15:34:39 (4 months ago)
Author:
KRavEN
Message:

Switched to JsMinEnh? javascript compression class to improve speed and memory usage

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • plugins/sfCombineFilterPlugin/branches/kraven/README

    r10352 r10353  
    2323 * Support for css filtered paths for additional paths that need to be removed from the file path before replacing relative paths 
    2424 * Cache that refreshes automatically when source files are changed 
    25  * Option to minimize the packed.js with JSMin 
     25 * Option to minimize the packed.js with JsMinEnh 
    2626 * Option to safe minimize the css 
    2727 * Options to only pack/compress the javascript or css in /packed/js or /packed/css 
     
    6767 
    6868Internet Explorer 6 has problems with large javascript files when gzip compression is on.  If you experience strange issues with your pages in IE6, set compressed: off for you environment in settings.yml and it should resolve the problem 
     69Requires a memory_limit of 32M or more in php.ini. 
    6970 
    7071== Changelog == 
     
    8182 - New: Option to minify the js using JSMin. 
    8283 
    83  === 2008-07-03 | 0.1.2 beta === 
     84 === 2008-07-18 | 0.1.2 beta === 
    8485Changes by Benjamin Runnels: 
    8586 - Moved cache generation/management into the filter 
     
    8889 - added client side caching for the packed files and improved the request name so it will cache properly 
    8990 - added routing rules to route to the sfCombineFilter module 
    90  - added non-harmfull css compressor as JSMin can mess up the css for some javascript libraries 
     91 - added non-harmfull css compressor 
    9192 - added path replacement in css files to resolve relative path issues 
     93 - switched to JsMinEnh class to improve memory usage and speed of javascript compression 
  • plugins/sfCombineFilterPlugin/branches/kraven/lib/JSMin.class.php

    r10089 r10353  
    1 <?php 
     1<?php // coding:utf-8 
    22/** 
    3  * jsmin.php - PHP implementation of Douglas Crockford's JSMin. 
    4  * 
    5  * This is pretty much a direct port of jsmin.c to PHP with just a few 
    6  * PHP-specific performance tweaks. Also, whereas jsmin.c reads from stdin and 
    7  * outputs to stdout, this library accepts a string as input and returns another 
    8  * string as output. 
    9  * 
    10  * PHP 5 or higher is required. 
    11  * 
    12  * Permission is hereby granted to use this version of the library under the 
    13  * same terms as jsmin.c, which has the following license: 
    14  * 
    15  * -- 
    16  * Copyright (c) 2002 Douglas Crockford  (www.crockford.com) 
    17  * 
    18  * Permission is hereby granted, free of charge, to any person obtaining a copy of 
    19  * this software and associated documentation files (the "Software"), to deal in 
    20  * the Software without restriction, including without limitation the rights to 
    21  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 
    22  * of the Software, and to permit persons to whom the Software is furnished to do 
    23  * so, subject to the following conditions: 
    24  * 
    25  * The above copyright notice and this permission notice shall be included in all 
    26  * copies or substantial portions of the Software. 
    27  * 
    28  * The Software shall be used for Good, not Evil. 
    29  * 
    30  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
    31  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
    32  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
    33  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
    34  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
    35  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 
    36  * SOFTWARE. 
    37  * -- 
    38  * 
    39  * @package JSMin 
    40  * @author Ryan Grove <ryan@wonko.com> 
    41  * @copyright 2002 Douglas Crockford <douglas@crockford.com> (jsmin.c) 
    42  * @copyright 2007 Ryan Grove <ryan@wonko.com> (PHP port) 
    43  * @license http://opensource.org/licenses/mit-license.php MIT License 
    44  * @version 1.1.0 (2007-06-01) 
    45  * @link http://code.google.com/p/jsmin-php/ 
     3* JsMinEnh.php (for PHP 5 only) 
     4
     5* Based on "PHP adaptation of JSMin" 
     6* <http://gggeek.altervista.org/2006/12/22/shrink-the-size-of-your-javascript-with-js-min-the-php-way/> 
     7* but freely adapted to my own needs. 
     8
     9* PHP adaptation of JSMin, published by Douglas Crockford as jsmin.c, also based 
     10* on its Java translation by John Reilly. 
     11
     12* Permission is hereby granted to use the PHP version under the same conditions 
     13* as jsmin.c, which has the following notice : 
     14
     15* ---------------------------------------------------------------------------- 
     16
     17* Copyright (c) 2002 Douglas Crockford  (www.crockford.com) 
     18
     19* Permission is hereby granted, free of charge, to any person obtaining a copy of 
     20* this software and associated documentation files (the "Software"), to deal in 
     21* the Software without restriction, including without limitation the rights to 
     22* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 
     23* of the Software, and to permit persons to whom the Software is furnished to do 
     24* so, subject to the following conditions: 
     25
     26* The above copyright notice and this permission notice shall be included in all 
     27* copies or substantial portions of the Software. 
     28
     29* The Software shall be used for Good, not Evil. 
     30
     31* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
     32* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
     33* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
     34* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
     35* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
     36* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 
     37* SOFTWARE. 
     38
     39* ---------------------------------------------------------------------------- 
     40
     41* @copyright   No new copyright ; please keep above and following information. 
     42* @author      David Holmes <dholmes@cfdsoftware.net> of CFD Labs, France 
     43* @author      Gaetano Giunta 
     44* @author      RĂ©mi Lanvin (aka cgo2) <cgo2@the-asw.com>, France 
     45* @version     $Id: $ 
     46*/ 
     47 
     48/** 
     49 * Generic exception class related to JSMin. 
    4650 */ 
    47  
    48 class JSMin { 
    49   const ORD_LF    = 10; 
    50   const ORD_SPACE = 32; 
    51  
    52   protected $a           = ''; 
    53   protected $b           = ''; 
    54   protected $input       = ''; 
    55   protected $inputIndex  = 0; 
    56   protected $inputLength = 0; 
    57   protected $lookAhead   = null; 
    58   protected $output      = array(); 
    59  
    60   // -- Public Static Methods -------------------------------------------------- 
    61  
    62   public static function minify($js) { 
    63     $jsmin = new JSMin($js); 
    64     return $jsmin->min(); 
    65   } 
    66  
    67   // -- Public Instance Methods ------------------------------------------------ 
    68  
    69   public function __construct($input) { 
    70     $this->input       = str_replace("\r\n", "\n", $input); 
    71     $this->inputLength = strlen($this->input); 
    72   } 
    73  
    74   // -- Protected Instance Methods --------------------------------------------- 
    75  
    76   protected function action($d) { 
    77     switch($d) { 
    78       case 1: 
    79         $this->output[] = $this->a; 
    80  
    81       case 2: 
    82         $this->a = $this->b; 
    83  
    84         if ($this->a === "'" || $this->a === '"') { 
    85           for (;;) { 
    86             $this->output[] = $this->a; 
    87             $this->a        = $this->get(); 
    88  
    89             if ($this->a === $this->b) { 
    90               break; 
    91             } 
    92  
    93             if (ord($this->a) <= self::ORD_LF) { 
    94               throw new JSMinException('Unterminated string literal.'); 
    95             } 
    96  
    97             if ($this->a === '\\') { 
    98               $this->output[] = $this->a; 
    99               $this->a        = $this->get(); 
    100             } 
    101           } 
    102         } 
    103  
    104       case 3: 
    105         $this->b = $this->next(); 
    106  
    107         if ($this->b === '/' && ( 
    108             $this->a === '(' || $this->a === ',' || $this->a === '=' || 
    109             $this->a === ':' || $this->a === '[' || $this->a === '!' || 
    110             $this->a === '&' || $this->a === '|' || $this->a === '?')) { 
    111  
    112           $this->output[] = $this->a; 
    113           $this->output[] = $this->b; 
    114  
    115           for (;;) { 
    116             $this->a = $this->get(); 
    117  
    118             if ($this->a === '/') { 
    119               break; 
    120             } 
    121             elseif ($this->a === '\\') { 
    122               $this->output[] = $this->a; 
    123               $this->a        = $this->get(); 
    124             } 
    125             elseif (ord($this->a) <= self::ORD_LF) { 
    126               throw new JSMinException('Unterminated regular expression '. 
    127                   'literal.'); 
    128             } 
    129  
    130             $this->output[] = $this->a; 
    131           } 
    132  
    133           $this->b = $this->next(); 
    134         } 
    135     } 
    136   } 
    137  
    138   protected function get() { 
    139     $c = $this->lookAhead; 
    140     $this->lookAhead = null; 
    141  
    142     if ($c === null) { 
    143       if ($this->inputIndex < $this->inputLength) { 
    144         $c = $this->input[$this->inputIndex]; 
    145         $this->inputIndex += 1; 
    146       } 
    147       else { 
    148         $c = null; 
    149       } 
    150     } 
     51class JsMinEnhException extends Exception 
     52
     53  public function __construct($msg) 
     54  { 
     55    parent :: __construct($msg); 
     56  } 
     57
     58 
     59 
     60/** 
     61* Main JSMin application class. 
     62
     63* Example of use : 
     64
     65* $code = file_get_contents($file); 
     66* $jsMin = new JsMinEnh($code); 
     67* $code = $jsMin->minify(); 
     68*/ 
     69class JsMinEnh 
     70
     71  /** 
     72   * How fgetc() reports an End Of File. 
     73   * N.B. : use === and not == to test the result of fgetc() ! (see manual) 
     74   */ 
     75  const EOF = false; 
     76 
     77  /** 
     78   * Some ASCII character ordinals. 
     79   */ 
     80  const ORD_NL = 10; 
     81  const ORD_space = 32; 
     82  const ORD_cA = 65; 
     83  const ORD_cZ = 90; 
     84  const ORD_a = 97; 
     85  const ORD_z = 122; 
     86  const ORD_0 = 48; 
     87  const ORD_9 = 57; 
     88 
     89  /** 
     90   * Constant describing an {@link action()} : Output A. Copy B to A. Get the next B. 
     91   */ 
     92  const JSMIN_ACT_FULL = 1; 
     93 
     94  /** 
     95   * Constant describing an {@link action()} : Copy B to A. Get the next B. (Delete A). 
     96   */ 
     97  const JSMIN_ACT_BUF = 2; 
     98 
     99  /** 
     100   * Constant describing an {@link action()} : Get the next B. (Delete B). 
     101   */ 
     102  const JSMIN_ACT_IMM = 3; 
     103 
     104  /** 
     105   * The input stream, from which to read a JS file to minimize. Obtained by fopen(). 
     106   * NB: might be a string instead of a stream 
     107   * @var SplFileObject | string 
     108   */ 
     109  private $in; 
     110 
     111  /** 
     112   * The output stream, in which to write the minimized JS file. Obtained by fopen(). 
     113   * NB: might be a string instead of a stream 
     114   * @var SplFileObject | string 
     115   */ 
     116  private $out; 
     117 
     118  /** 
     119   * Temporary I/O character (A). 
     120   * @var string 
     121   */ 
     122  private $theA; 
     123 
     124  /** 
     125   * Temporary I/O character (B). 
     126   * @var string 
     127   */ 
     128  private $theB; 
     129 
     130  /** variables used for string-based parsing **/ 
     131  private $inLength = 0; 
     132  private $inPos = 0; 
     133 
     134  /** 
     135   * Indicates whether a character is alphanumeric or _, $, \ or non-ASCII. 
     136   * 
     137   * @param   string      $c  The single character to test. 
     138   * @return  boolean     Whether the char is a letter, digit, underscore, dollar, backslash, or non-ASCII. 
     139   */ 
     140  private function isAlphaNum($c) { 
     141 
     142    // Get ASCII value of character for C-like comparisons 
     143    $a = ord($c); 
     144 
     145    // Compare using defined character ordinals, or between PHP strings 
     146    // Note : === is micro-faster than == when types are known to be the same 
     147    return 
     148      ($a >= self::ORD_a && $a <= self::ORD_z) || 
     149      ($a >= self::ORD_0 && $a <= self::ORD_9) || 
     150      ($a >= self::ORD_cA && $a <= self::ORD_cZ) || 
     151      $c === '_' || $c === '$' || $c === '\\' || $a > 126 
     152    ; 
     153  } 
     154 
     155  /** 
     156   * Get the next character from the input stream. 
     157   * 
     158   * If said character is a control character, translate it to a space or linefeed. 
     159   * 
     160   * @return  string      The next character from the specified input stream. 
     161   * @see     $in 
     162   * @see     peek() 
     163   */ 
     164  private function get() { 
     165 
     166    // Get next input character and advance position in file 
     167    if ($this->inPos < $this->inLength) { 
     168      $c = $this->in[$this->inPos]; 
     169      ++$this->inPos; 
     170    } 
     171    else { 
     172      return self::EOF; 
     173    } 
     174 
     175    // Test for non-problematic characters 
     176    if ($c === "\n" || $c === self::EOF || ord($c) >= self::ORD_space) { 
     177      return $c; 
     178    } 
     179 
     180    // else 
     181    // Make linefeeds into newlines 
    151182 
    152183    if ($c === "\r") { 
     
    154185    } 
    155186 
    156     if ($c === null || $c === "\n" || ord($c) >= self::ORD_SPACE) { 
    157       return $c; 
    158     } 
     187    // else 
     188    // Consider space 
    159189 
    160190    return ' '; 
    161191  } 
    162192 
    163   protected function isAlphaNum($c) { 
    164     return ord($c) > 126 || $c === '\\' || preg_match('/^[\w\$]$/', $c) === 1; 
    165   } 
    166  
    167   protected function min() { 
    168     $this->a = "\n"; 
    169     $this->action(3); 
    170  
    171     while ($this->a !== null) { 
    172       switch ($this->a) { 
    173         case ' ': 
    174           if ($this->isAlphaNum($this->b)) { 
    175             $this->action(1); 
     193  private function getCloser($string, $needle, $offset) 
     194  { 
     195    $closer = false; 
     196    foreach ($needle as $n) { 
     197      $pos = strpos($string, $n, $offset); 
     198      if ( $pos !== false && ($closer === false || $pos < $closer) ) 
     199        $closer = $pos; 
     200    } 
     201    return $closer; 
     202  } 
     203 
     204  /** 
     205   * Get the next character from the input stream, without gettng it. 
     206   * 
     207   * @return  string      The next character from the specified input stream, without advancing the position 
     208   *                      in the underlying file. 
     209   * @see     $in 
     210   * @see     get() 
     211   */ 
     212  private function peek() 
     213  { 
     214    return ($this->inPos < $this->inLength) ? $this->in[$this->inPos] : self::EOF; 
     215  } 
     216 
     217  /** 
     218   * Adds a char to the output string 
     219   * @see $out 
     220   */ 
     221  function put($c) 
     222  { 
     223    $this->out .= $c; 
     224  } 
     225 
     226  /** 
     227   * Get the next character from the input stream, excluding comments. 
     228   * 
     229   * {@link peek()} is used to see if a '/' is followed by a '*' or '/'. 
     230   * Multiline comments are actually returned as a single space. 
     231   * 
     232   * @return  string  The next character from the specified input stream, skipping comments. 
     233   * @see     $in 
     234   */ 
     235  function next() { 
     236 
     237    // Get next char from input, translated if necessary 
     238 
     239    $c = $this->get(); 
     240 
     241    // Check comment possibility 
     242 
     243    if ($c == '/') { 
     244 
     245      // Look ahead : a comment is two slashes or slashes followed by asterisk (to be closed) 
     246 
     247      switch ($this->peek()) { 
     248 
     249        case '/' : 
     250 
     251          // Comment is up to the end of the line 
     252          $this->inPos = strpos($this->in, "\n", $this->inPos); 
     253          return $this->in[$this->inPos]; 
     254 
     255        case '*' : 
     256 
     257          // Comment is up to comment close. 
     258          // Might not be terminated, if we hit the end of file. 
     259 
     260          $this->inPos = strpos($this->in, "*/", $this->inPos); 
     261          if ( $this->inPos === false ) { 
     262            throw new JsMinEnhException('UnterminatedComment'); 
     263          } 
     264          $this->inPos += 2; 
     265          return ' '; 
     266        default : 
     267 
     268          // Not a comment after all 
     269 
     270          return $c; 
     271      } 
     272    } 
     273 
     274    // No risk of a comment 
     275 
     276    return $c; 
     277  } 
     278 
     279  /** 
     280   * Do something ! 
     281   * 
     282   * The action to perform is determined by the argument : 
     283   * 
     284   * JSMin::ACT_FULL : Output A. Copy B to A. Get the next B. 
     285   * JSMin::ACT_BUF  : Copy B to A. Get the next B. (Delete A). 
     286   * JSMin::ACT_IMM  : Get the next B. (Delete B). 
     287   * 
     288   * A string is treated as a single character. Also, regular expressions are recognized if preceded 
     289   * by '(', ',' or '='. 
     290   * 
     291   * @param   int     $action     The action to perform : one of the JSMin::ACT_* constants. 
     292   */ 
     293  function action($action) { 
     294 
     295    // Choice of possible actions 
     296    // Note the frequent fallthroughs : the actions are decrementally "long" 
     297    switch ($action) { 
     298 
     299      case self::JSMIN_ACT_FULL : 
     300        // Write A to output, then fall through 
     301 
     302        $this->put($this->theA); 
     303 
     304      case self::JSMIN_ACT_BUF : // N.B. possible fallthrough from above 
     305        // Copy B to A 
     306 
     307        $tmpA = $this->theA = $this->theB; 
     308 
     309        // Treating a string as a single char : outputting it whole 
     310        // Note that the string-opening char (" or ') is memorized in B 
     311 
     312        if ($tmpA == '\'' || $tmpA == '"') { 
     313 
     314          $pos = $this->inPos; 
     315          while (true) { 
     316            // instead of looping char by char, we directly go to the next 
     317            // revelant char, thanks to php strpos function. 
     318            $pos = $this->getCloser($this->in, array($this->theB,'\\',"\n"), $pos); 
     319 
     320            if ( $pos === false ) { 
     321              // Whoopsie 
     322              throw new JsMinEnhException('UnterminatedStringLiteral'); 
     323            } 
     324 
     325            $tmpA = $this->in[$pos]; 
     326 
     327            if ($tmpA == $this->theB) { 
     328              // String terminated 
     329              break; // from while(true) 
     330            } 
     331            if ($tmpA == "\n") { 
     332              // Whoopsie 
     333              throw new JsMinEnhException('UnterminatedStringLiteral'); 
     334            } 
     335            // else 
     336            if ($tmpA == '\\') { 
     337              // Escape next char immediately 
     338              $pos += 2; 
     339            } 
     340          } 
     341 
     342          // cool, we got the whole string 
     343          $this->put(substr($this->in, $this->inPos - 1, $pos - $this->inPos + 1)); 
     344          $this->inPos = $pos + 1; 
     345          $this->theA = $tmpA; 
     346        } 
     347 
     348      case self::JSMIN_ACT_IMM : // N.B. possible fallthrough from above 
     349        // Get the next B 
     350 
     351        $this->theB = $this->next(); 
     352 
     353        // Special case of recognising regular expressions (beginning with /) that are 
     354        // preceded by '(', ',' or '=' 
     355 
     356        $tmpA = $this->theA; 
     357 
     358        if ($this->theB == '/' && ($tmpA == '(' || $tmpA == ',' || $tmpA == '=')) { 
     359 
     360          // Output the two successive chars 
     361          $this->put($tmpA); 
     362          $this->put($this->theB); 
     363 
     364          // Look for the end of the RE literal, watching out for escaped chars or a control / 
     365          // end of line char (the RE literal then being unterminated !) 
     366          $pos = $this->inPos; 
     367          while (true) { 
     368            // instead of looping char by char, we directly go to the next 
     369            // revelant char, thanks to php strpos function. 
     370            $pos = $this->getCloser($this->in, array('/','\\',"\n"), $pos); 
     371 
     372            if ( $pos === false ) { 
     373              // Whoopsie 
     374              throw new JsMinEnhException('UnterminatedRegExpLiteral'); 
     375            } 
     376 
     377            $tmpA = $this->in[$pos]; 
     378 
     379            if ($tmpA == '/') { 
     380              // RE literal terminated 
     381              break; // from while(true) 
     382            } 
     383            if ( $tmpA == "\n") { 
     384              // Whoopsie 
     385              throw new JsMinEnhException('UnterminatedRegExpLiteral'); 
     386            } 
     387            // else 
     388            if ($tmpA == '\\') { 
     389              // Escape next char immediately 
     390              $pos += 2; 
     391            } 
     392          } 
     393          $this->put(substr($this->in, $this->inPos, $pos - $this->inPos)); 
     394          $this->inPos = $pos + 1; 
     395          $this->theA = $tmpA; 
     396 
     397 
     398          // Move forward after the RE literal 
     399          $this->theB = $this->next(); 
     400        } 
     401 
     402      break; 
     403      default : 
     404        throw new JsMinEnhException('Expected a JSMin::ACT_* constant in action()'); 
     405    } 
     406  } 
     407 
     408  /** 
     409   * Run the JSMin application : minify some JS code. 
     410   * 
     411   * The code is read from the input stream, and its minified version is written to the output one. 
     412   * In case input is a string, minified vesrions is also returned by this function as string. 
     413   * That is : characters which are insignificant to JavaScript are removed, as well as comments ; 
     414   * tabs are replaced with spaces ; carriage returns are replaced with linefeeds, and finally most 
     415   * spaces and linefeeds are deleted. 
     416   * 
     417   * Note : name was changed from jsmin() because PHP identifiers are case-insensitive, and it is already 
     418   * the name of this class. 
     419   * 
     420   * @see     JSMin() 
     421   * @return null | string 
     422   */ 
     423  function minify() { 
     424 
     425    // Initialize A and run the first (minimal) action 
     426 
     427    $this->theA = "\n"; 
     428    $this->action(self::JSMIN_ACT_IMM); 
     429 
     430    // Proceed all the way to the end of the input file 
     431 
     432    while ($this->theA !== self::EOF) { 
     433      switch ($this->theA) { 
     434        case ' ' : 
     435 
     436          if ($this->isAlphaNum($this->theB)) { 
     437            $this->action(self::JSMIN_ACT_FULL); 
    176438          } 
    177439          else { 
    178             $this->action(2); 
    179           } 
    180           break; 
    181  
    182         case "\n": 
    183           switch ($this->b) { 
    184             case '{': 
    185             case '[': 
    186             case '(': 
    187             case '+': 
    188             case '-': 
    189               $this->action(1); 
    190               break; 
    191  
    192             case ' ': 
    193               $this->action(3); 
    194               break; 
    195  
    196             default: 
    197               if ($this->isAlphaNum($this->b)) { 
    198                 $this->action(1); 
     440            $this->action(self::JSMIN_ACT_BUF); 
     441          } 
     442 
     443        break; 
     444        case "\n" : 
     445 
     446          switch ($this->theB) { 
     447 
     448            case '{' : case '[' : case '(' : 
     449            case '+' : case '-' : 
     450 
     451              $this->action(self::JSMIN_ACT_FULL); 
     452 
     453            break; 
     454            case ' ' : 
     455 
     456              $this->action(self::JSMIN_ACT_IMM); 
     457 
     458            break; 
     459            default : 
     460 
     461              if ($this->isAlphaNum($this->theB)) { 
     462                $this->action(self::JSMIN_ACT_FULL); 
    199463              } 
    200464              else { 
    201                 $this->action(2); 
     465                $this->action(self::JSMIN_ACT_BUF); 
    202466              } 
    203           } 
    204           break; 
    205  
    206         default: 
    207           switch ($this->b) { 
    208             case ' ': 
    209               if ($this->isAlphaNum($this->a)) { 
    210                 $this->action(1); 
     467 
     468            break; 
     469          } 
     470 
     471        break; 
     472        default : 
     473 
     474          switch ($this->theB) { 
     475 
     476            case ' ' : 
     477 
     478              if ($this->isAlphaNum($this->theA)) { 
     479 
     480                $this->action(self::JSMIN_ACT_FULL); 
    211481                break; 
    212482              } 
    213483 
    214               $this->action(3); 
    215               break; 
    216  
    217             case "\n": 
    218               switch ($this->a) { 
    219                 case '}': 
    220                 case ']': 
    221                 case ')': 
    222                 case '+': 
    223                 case '-': 
    224                 case '"': 
    225                 case "'": 
    226                   $this->action(1); 
    227                   break; 
    228  
    229                 default: 
    230                   if ($this->isAlphaNum($this->a)) { 
    231                     $this->action(1); 
     484              // else 
     485 
     486              $this->action(self::JSMIN_ACT_IMM); 
     487 
     488            break; 
     489            case "\n" : 
     490 
     491              switch ($this->theA) { 
     492 
     493                case '}' : case ']' : case ')' : case '+' : 
     494                case '-' : case '"' : case '\'' : 
     495 
     496                  $this->action(self::JSMIN_ACT_FULL); 
     497 
     498                break; 
     499                default : 
     500 
     501                  if ($this->isAlphaNum($this->theA)) { 
     502                    $this->action(self::JSMIN_ACT_FULL); 
    232503                  } 
    233504                  else { 
    234                     $this->action(3); 
     505                    $this->action(self::JSMIN_ACT_IMM); 
    235506                  } 
     507 
     508                break; 
    236509              } 
    237               break; 
    238  
    239             default: 
    240               $this->action(1); 
    241               break; 
    242           } 
     510 
     511            break; 
     512            default : 
     513 
     514              $this->action(self::JSMIN_ACT_FULL); 
     515 
     516            break; 
     517          } 
     518 
     519        break; 
    243520      } 
    244521    } 
    245522 
    246     return implode('', $this->output); 
    247   } 
    248  
    249   protected function next() { 
    250     $c = $this->get(); 
    251  
    252     if ($c === '/') { 
    253       switch($this->peek()) { 
    254         case '/': 
    255           for (;;) { 
    256             $c = $this->get(); 
    257  
    258             if (ord($c) <= self::ORD_LF) { 
    259               return $c; 
    260             } 
    261           } 
    262  
    263         case '*': 
    264           $this->get(); 
    265  
    266           for (;;) { 
    267             switch($this->get()) { 
    268               case '*': 
    269                 if ($this->peek() === '/') { 
    270                   $this->get(); 
    271                   return ' '; 
    272                 } 
    273                 break; 
    274  
    275               case null: 
    276                 throw new JSMinException('Unterminated comment.'); 
    277             } 
    278           } 
    279  
    280         default: 
    281           return $c; 
     523    return $this->out; 
     524  } 
     525 
     526  /** 
     527   * Prepare a new JSMin application. 
     528   * 
     529   * The next step is to {@link minify()} the input into the output. 
     530   * 
     531   * @param   string  $inString       The code to minify 
     532   * @param   array   $comments       Optional lines to present as comments at the beginning of the output. 
     533   */ 
     534  function __construct($inString, $comments = NULL) { 
     535    $this->in = str_replace("\r\n","\n", $inString); 
     536    $this->out = ''; 
     537    $this->inLength = strlen($this->in); 
     538    $this->inPos = 0; 
     539 
     540    if (is_array($comments)) { 
     541      foreach ($comments as $comm) { 
     542        $this->out .= '// '.str_replace("\n", " ", $comm)."\n"; 
    282543      } 
    283544    } 
    284  
    285     return $c; 
    286   } 
    287  
    288   protected function peek() { 
    289     $this->lookAhead = $this->get(); 
    290     return $this->lookAhead; 
    291545  } 
    292546} 
    293  
    294 // -- Exceptions --------------------------------------------------------------- 
    295 class JSMinException extends Exception {} 
  • plugins/sfCombineFilterPlugin/branches/kraven/lib/sfCombineFilter.class.php

    r10177 r10353  
    138138        } 
    139139 
    140         $contents .= "\n/* FILENAME */\n/* $path */\n"; 
    141         $contents .= "\n\n" . $con; 
    142       } 
    143  
    144       if ($this->type=='javascript'&& sfConfig::get('app_sf_combine_filter_plugin_compress_js', false)) 
    145       { 
    146         $contents = JSMin::minify($contents); 
    147       } 
    148       elseif($this->type=='css'&& sfConfig::get('app_sf_combine_filter_plugin_compress_css', true)) 
    149       { 
    150         $contents = $this->compressCss($contents)
     140        if ($this->type=='javascript'&& sfConfig::get('app_sf_combine_filter_plugin_compress_js', false)) 
     141        { 
     142          $jsMin = new JsMinEnh($con); 
     143          $con = $jsMin->minify(); 
     144        } 
     145        elseif($this->type=='css'&& sfConfig::get('app_sf_combine_filter_plugin_compress_css', true)) 
     146        { 
     147          $con = $this->compressCss($con); 
     148        } 
     149 
     150        $contents .= "\n" . $con
    151151      } 
    152152