%PDF- %PDF-
Mini Shell

Mini Shell

Direktori : /home1/lightco1/upgrade.lightco.com.au/libraries/compojoom/minifier/
Upload File :
Create Path :
Current File : //home1/lightco1/upgrade.lightco.com.au/libraries/compojoom/minifier/minifier.php

<?php

/**

 * @package    Lib_Compojoom

 * @author     DanielDimitrov <daniel@compojoom.com>

 * @date       20.08.14

 *

 * @copyright  Copyright (C) 2008 - 2013 compojoom.com . All rights reserved.

 * @license    GNU General Public License version 2 or later; see LICENSE

 */



defined('_JEXEC') or die('Restricted access');



/**

 * This file is part of the JShrink package.

 *

 * @link     https://github.com/tedious/JShrink

 * @license  http://www.opensource.org/licenses/bsd-license.php  BSD License

 *

 * (c) Robert Hafner <tedivm@tedivm.com>

 *

 * For the full copyright and license information, please view the LICENSE

 * file that was distributed with this source code.

 *

 * Copyright (c) 2009, Robert Hafner

 * All rights reserved.

 *

 * Redistribution and use in source and binary forms, with or without

 * modification, are permitted provided that the following conditions are met:

 *       * Redistributions of source code must retain the above copyright

 *          notice, this list of conditions and the following disclaimer.

 *       * Redistributions in binary form must reproduce the above copyright

 *          notice, this list of conditions and the following disclaimer in the

 *          documentation and/or other materials provided with the distribution.

 *       * Neither the name of the Stash Project nor the

 *           names of its contributors may be used to endorse or promote products

 *           derived from this software without specific prior written permission.

 *

 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND

 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED

 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE

 * DISCLAIMED. IN NO EVENT SHALL Robert Hafner BE LIABLE FOR ANY

 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES

 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;

 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND

 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS

 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

 */



/**

 * JShrink

 *

 *

 * @package    JShrink

 * @author     Robert Hafner <tedivm@tedivm.com>

 */



/**

 * This is the original Minifier class. I've renamed it to CompojoomMinifier in order for it

 * to be autoloaded with our library. Other than that all functions from jshrink are the same

 *

 * Usage - CompojoomMinifier::minify($js);

 * Usage - CompojoomMinifier::minify($js, $options);

 * Usage - CompojoomMinifier::minify($js, array('flaggedComments' => false));

 *

 * @since  4.0

 */

class CompojoomMinifier

{

	/**

	 * The input javascript to be minified.

	 *

	 * @var string

	 */

	protected $input;



	/**

	 * The location of the character (in the input string) that is next to be

	 * processed.

	 *

	 * @var int

	 */

	protected $index = 0;



	/**

	 * The first of the characters currently being looked at.

	 *

	 * @var string

	 */

	protected $a = '';



	/**

	 * The next character being looked at (after a);

	 *

	 * @var string

	 */

	protected $b = '';



	/**

	 * This character is only active when certain look ahead actions take place.

	 *

	 * @var string

	 */

	protected $c;



	/**

	 * Contains the options for the current minification process.

	 *

	 * @var array

	 */

	protected $options;



	/**

	 * Contains the default options for minification. This array is merged with

	 * the one passed in by the user to create the request specific set of

	 * options (stored in the $options attribute).

	 *

	 * @var array

	 */

	protected static $defaultOptions = array('flaggedComments' => true);



	/**

	 * Contains lock ids which are used to replace certain code patterns and

	 * prevent them from being minified

	 *

	 * @var array

	 */

	protected $locks = array();



	/**

	 * Takes a string containing javascript and removes unneeded characters in

	 * order to shrink the code without altering it's functionality.

	 *

	 * @param   string  $js       The raw javascript to be minified

	 * @param   array   $options  Various runtime options in an associative array

	 *

	 * @throws \Exception

	 * @return bool|string

	 */

	public static function minify($js, $options = array())

	{

		try

		{

			ob_start();



			$jshrink = new CompojoomMinifier;

			$js = $jshrink->lock($js);

			$jshrink->minifyDirectToOutput($js, $options);



			// Sometimes there's a leading new line, so we trim that out here.

			$js = ltrim(ob_get_clean());

			$js = $jshrink->unlock($js);

			unset($jshrink);



			return $js;

		}

		catch (\Exception $e)

		{



			if (isset($jshrink))

			{

				// Since the breakdownScript function probably wasn't finished

				// we clean it out before discarding it.

				$jshrink->clean();

				unset($jshrink);

			}



			// Without this call things get weird, with partially outputted js.

			ob_end_clean();

			throw $e;

		}

	}



	/**

	 * Processes a javascript string and outputs only the required characters,

	 * stripping out all unneeded characters.

	 *

	 * @param   string  $js       The raw javascript to be minified

	 * @param   array   $options  Various runtime options in an associative array

	 *

	 * @return void

	 */

	protected function minifyDirectToOutput($js, $options)

	{

		$this->initialize($js, $options);

		$this->loop();

		$this->clean();

	}



	/**

	 *  Initializes internal variables, normalizes new lines,

	 *

	 * @param   string  $js       The raw javascript to be minified

	 * @param   array   $options  Various runtime options in an associative array

	 *

	 * @return void

	 */

	protected function initialize($js, $options)

	{

		$this->options = array_merge(static::$defaultOptions, $options);

		$js = str_replace("\r\n", "\n", $js);

		$this->input = str_replace("\r", "\n", $js);



		/**

		 * We add a newline to the end of the script to make it easier to deal

		 * with comments at the bottom of the script- this prevents the unclosed

		 * comment error that can otherwise occur.

		 */

		$this->input .= PHP_EOL;



		// Populate "a" with a new line, "b" with the first character, before entering the loop

		$this->a = "\n";

		$this->b = $this->getReal();

	}



	/**

	 * The primary action occurs here. This function loops through the input string,

	 * outputting anything that's relevant and discarding anything that is not.

	 *

	 * @return void

	 */

	protected function loop()

	{

		while ($this->a !== false && !is_null($this->a) && $this->a !== '')

		{

			switch ($this->a)

			{

				// New lines

				case "\n":

					// If the next line is something that can't stand alone preserve the newline

					if (strpos('(-+{[@', $this->b) !== false)

					{

						echo $this->a;

						$this->saveString();

						break;

					}



					// If B is a space we skip the rest of the switch block and go down to the

					// String/regex check below, resetting $this->b with getReal

					if ($this->b === ' ')

					{

						break;

					}



				// Otherwise we treat the newline like a space

				case ' ':

					if (static::isAlphaNumeric($this->b))

					{

						echo $this->a;

					}



					$this->saveString();

					break;



				default:

					switch ($this->b)

					{

						case "\n":

							if (strpos('}])+-"\'', $this->a) !== false)

							{

								echo $this->a;

								$this->saveString();

								break;

							}

							else

							{

								if (static::isAlphaNumeric($this->a))

								{

									echo $this->a;

									$this->saveString();

								}

							}

							break;



						case ' ':

							if (!static::isAlphaNumeric($this->a))

							{

								break;

							}



						default:

							// Check for some regex that breaks stuff

							if ($this->a == '/' && ($this->b == '\'' || $this->b == '"'))

							{

								$this->saveRegex();

								continue;

							}



							echo $this->a;

							$this->saveString();

							break;

					}

			}



			// Do reg check of doom

			$this->b = $this->getReal();



			if (($this->b == '/' && strpos('(,=:[!&|?', $this->a) !== false))

			{

				$this->saveRegex();

			}

		}

	}



	/**

	 * Resets attributes that do not need to be stored between requests so that

	 * the next request is ready to go. Another reason for this is to make sure

	 * the variables are cleared and are not taking up memory.

	 *

	 * @return void

	 */

	protected function clean()

	{

		unset($this->input);

		$this->index = 0;

		$this->a = $this->b = '';

		unset($this->c);

		unset($this->options);

	}



	/**

	 * Returns the next string for processing based off of the current index.

	 *

	 * @return string

	 */

	protected function getChar()

	{

		// Check to see if we had anything in the look ahead buffer and use that.

		if (isset($this->c))

		{

			$char = $this->c;

			unset($this->c);



			// Otherwise we start pulling from the input.

		}

		else

		{

			$char = substr($this->input, $this->index, 1);



			// If the next character doesn't exist return false.

			if (isset($char) && $char === false)

			{

				return false;

			}



			// Otherwise increment the pointer and use this char.

			$this->index++;

		}



		// Normalize all whitespace except for the newline character into a standard space.

		if ($char !== "\n" && ord($char) < 32)

		{

			return ' ';

		}



		return $char;

	}



	/**

	 * This function gets the next "real" character. It is essentially a wrapper

	 * around the getChar function that skips comments. This has significant

	 * performance benefits as the skipping is done using native functions (ie,

	 * c code) rather than in script php.

	 *

	 * @return   string   Next 'real' character to be processed.

	 *

	 * @throws   \RuntimeException

	 */

	protected function getReal()

	{

		$startIndex = $this->index;

		$char = $this->getChar();



		// Check to see if we're potentially in a comment

		if ($char !== '/')

		{

			return $char;

		}



		$this->c = $this->getChar();



		if ($this->c == '/')

		{

			return $this->processOneLineComments($startIndex);

		}

		elseif ($this->c == '*')

		{

			return $this->processMultiLineComments($startIndex);

		}



		return $char;

	}



	/**

	 * Removed one line comments, with the exception of some very specific types of

	 * conditional comments.

	 *

	 * @param   int  $startIndex  The index point where "getReal" function started

	 *

	 * @return string

	 */

	protected function processOneLineComments($startIndex)

	{

		$thirdCommentString = substr($this->input, $this->index, 1);



		// Kill rest of line

		$this->getNext("\n");



		if ($thirdCommentString == '@')

		{

			$endPoint = ($this->index) - $startIndex;

			unset($this->c);

			$char = "\n" . substr($this->input, $startIndex, $endPoint);

		}

		else

		{

			// First one is contents of $this->c

			$this->getChar();

			$char = $this->getChar();

		}



		return $char;

	}



	/**

	 * Skips multiline comments where appropriate, and includes them where needed.

	 * Conditional comments and "license" style blocks are preserved.

	 *

	 * @param   int  $startIndex  The index point where "getReal" function started

	 *

	 * @return bool|string       False if there's no character#

	 *

	 * @throws \RuntimeException Unclosed comments will throw an error

	 */

	protected function processMultiLineComments($startIndex)

	{

		// Current C

		$this->getChar();

		$thirdCommentString = $this->getChar();



		// Kill everything up to the next */ if it's there

		if ($this->getNext('*/'))

		{

			// Get *

			$this->getChar();



			// Get /

			$this->getChar();



			// Get next real character

			$char = $this->getChar();



			// Now we reinsert conditional comments and YUI-style licensing comments

			if (($this->options['flaggedComments'] && $thirdCommentString == '!')

				|| ($thirdCommentString == '@'))

			{

				// If conditional comments or flagged comments are not the first thing in the script

				// we need to echo a and fill it with a space before moving on.

				if ($startIndex > 0)

				{

					echo $this->a;

					$this->a = " ";



					// If the comment started on a new line we let it stay on the new line

					if ($this->input[($startIndex - 1)] == "\n")

					{

						echo "\n";

					}

				}



				$endPoint = ($this->index - 1) - $startIndex;

				echo substr($this->input, $startIndex, $endPoint);



				return $char;

			}

		}

		else

		{

			$char = false;

		}



		if ($char === false)

		{

			throw new \RuntimeException('Unclosed multiline comment at position: ' . ($this->index - 2));

		}



		// If we're here c is part of the comment and therefore tossed

		if (isset($this->c))

		{

			unset($this->c);

		}



		return $char;

	}



	/**

	 * Pushes the index ahead to the next instance of the supplied string. If it

	 * is found the first character of the string is returned and the index is set

	 * to it's position.

	 *

	 * @param   string  $string  - the string

	 *

	 * @return string|false Returns the first character of the string or false.

	 */

	protected function getNext($string)

	{

		// Find the next occurrence of "string" after the current position.

		$pos = strpos($this->input, $string, $this->index);



		// If it's not there return false.

		if ($pos === false)

		{

			return false;

		}



		// Adjust position of index to jump ahead to the asked for string

		$this->index = $pos;



		// Return the first character of that string.

		return substr($this->input, $this->index, 1);

	}



	/**

	 * When a javascript string is detected this function crawls for the end of

	 * it and saves the whole string.

	 *

	 * @throws \RuntimeException Unclosed strings will throw an error

	 *

	 * @return void

	 */

	protected function saveString()

	{

		$startpos = $this->index;



		// SaveString is always called after a gets cleared, so we push b into that spot.

		$this->a = $this->b;



		// If this isn't a string we don't need to do anything.

		if ($this->a != "'" && $this->a != '"')

		{

			return;

		}



		// String type is the quote used, " or '

		$stringType = $this->a;



		// Echo out that starting quote

		echo $this->a;



		// Loop until the string is done

		while (1)

		{

			// Grab the very next character and load it into a

			$this->a = $this->getChar();



			switch ($this->a)

			{

				/**

				 * If the string opener (single or double quote) is used

				 * output it and break out of the while loop-

				 * The string is finished!

				 */

				case $stringType:

					break 2;



				/**

				 * New lines in strings without line delimiters are bad- actual

				 * new lines will be represented by the string \n and not the actual

				 * character, so those will be treated just fine using the switch

				 * block below.

				 */

				case "\n":

					throw new \RuntimeException('Unclosed string at position: ' . $startpos);

					break;



				// Escaped characters get picked up here. If it's an escaped new line it's not really needed

				case '\\':

					/**

					 * a is a slash. We want to keep it, and the next character,

					 * unless it's a new line. New lines as actual strings will be

					 * preserved, but escaped new lines should be reduced.

					 */

					$this->b = $this->getChar();



					// If b is a new line we discard a and b and restart the loop.

					if ($this->b == "\n")

					{

						break;

					}



					// Echo out the escaped character and restart the loop.

					echo $this->a . $this->b;

					break;



				// Since we're not dealing with any special cases we simply

				// output the character and continue our loop.

				default:

					echo $this->a;

			}

		}

	}



	/**

	 * When a regular expression is detected this function crawls for the end of

	 * it and saves the whole regex.

	 *

	 * @throws \RuntimeException Unclosed regex will throw an error

	 *

	 * @return void

	 */

	protected function saveRegex()

	{

		echo $this->a . $this->b;



		while (($this->a = $this->getChar()) !== false)

		{

			if ($this->a == '/')

			{

				break;

			}



			if ($this->a == '\\')

			{

				echo $this->a;

				$this->a = $this->getChar();

			}



			if ($this->a == "\n")

			{

				throw new \RuntimeException('Unclosed regex pattern at position: ' . $this->index);

			}



			echo $this->a;

		}



		$this->b = $this->getReal();

	}



	/**

	 * Checks to see if a character is alphanumeric.

	 *

	 * @param   string  $char  Just one character

	 *

	 * @return bool

	 */

	protected static function isAlphaNumeric($char)

	{

		return preg_match('/^[\w\$]$/', $char) === 1 || $char == '/';

	}



	/**

	 * Replace patterns in the given string and store the replacement

	 *

	 * @param   string  $js  The string to lock

	 *

	 * @return bool

	 */

	protected function lock($js)

	{

		/* lock things like <code>"asd" + ++x;</code> */

		$lock = '"LOCK---' . crc32(time()) . '"';



		$matches = array();

		preg_match('/([+-])(\s+)([+-])/', $js, $matches);



		if (empty($matches))

		{

			return $js;

		}



		$this->locks[$lock] = $matches[2];



		$js = preg_replace('/([+-])\s+([+-])/', "$1{$lock}$2", $js);

		/* -- */



		return $js;

	}



	/**

	 * Replace "locks" with the original characters

	 *

	 * @param   string  $js  The string to unlock

	 *

	 * @return bool

	 */

	protected function unlock($js)

	{

		if (!count($this->locks))

		{

			return $js;

		}



		foreach ($this->locks as $lock => $replacement)

		{

			$js = str_replace($lock, $replacement, $js);

		}



		return $js;

	}

}


Zerion Mini Shell 1.0