From: Marcin Haba Date: Tue, 29 Oct 2019 17:44:02 +0000 (+0100) Subject: baculum: Add jsmin-php as framework dependency X-Git-Tag: Release-9.6.0~104 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=59bb718f1c370c5117b292b3396216bc6f285697;p=thirdparty%2Fbacula.git baculum: Add jsmin-php as framework dependency --- diff --git a/gui/baculum/framework/composer/ClassLoader.php b/gui/baculum/framework/composer/ClassLoader.php index dc02dfb11..fce8549f0 100644 --- a/gui/baculum/framework/composer/ClassLoader.php +++ b/gui/baculum/framework/composer/ClassLoader.php @@ -279,7 +279,7 @@ class ClassLoader */ public function setApcuPrefix($apcuPrefix) { - $this->apcuPrefix = function_exists('apcu_fetch') && ini_get('apc.enabled') ? $apcuPrefix : null; + $this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null; } /** @@ -377,7 +377,7 @@ class ClassLoader $subPath = $class; while (false !== $lastPos = strrpos($subPath, '\\')) { $subPath = substr($subPath, 0, $lastPos); - $search = $subPath.'\\'; + $search = $subPath . '\\'; if (isset($this->prefixDirsPsr4[$search])) { $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1); foreach ($this->prefixDirsPsr4[$search] as $dir) { diff --git a/gui/baculum/framework/composer/autoload_namespaces.php b/gui/baculum/framework/composer/autoload_namespaces.php index b7fc0125d..89764e0cc 100644 --- a/gui/baculum/framework/composer/autoload_namespaces.php +++ b/gui/baculum/framework/composer/autoload_namespaces.php @@ -6,4 +6,5 @@ $vendorDir = dirname(dirname(__FILE__)); $baseDir = dirname($vendorDir); return array( + 'JSMin\\' => array($vendorDir . '/mrclay/jsmin-php/src'), ); diff --git a/gui/baculum/framework/composer/autoload_static.php b/gui/baculum/framework/composer/autoload_static.php index 53ee51813..44baaad54 100644 --- a/gui/baculum/framework/composer/autoload_static.php +++ b/gui/baculum/framework/composer/autoload_static.php @@ -20,11 +20,22 @@ class ComposerStaticInitce99a96f11b07d74c065123825cb4155 ), ); + public static $prefixesPsr0 = array ( + 'J' => + array ( + 'JSMin\\' => + array ( + 0 => __DIR__ . '/..' . '/mrclay/jsmin-php/src', + ), + ), + ); + public static function getInitializer(ClassLoader $loader) { return \Closure::bind(function () use ($loader) { $loader->prefixLengthsPsr4 = ComposerStaticInitce99a96f11b07d74c065123825cb4155::$prefixLengthsPsr4; $loader->prefixDirsPsr4 = ComposerStaticInitce99a96f11b07d74c065123825cb4155::$prefixDirsPsr4; + $loader->prefixesPsr0 = ComposerStaticInitce99a96f11b07d74c065123825cb4155::$prefixesPsr0; }, null, ClassLoader::class); } diff --git a/gui/baculum/framework/composer/installed.json b/gui/baculum/framework/composer/installed.json index 76d2be614..024dd97ef 100644 --- a/gui/baculum/framework/composer/installed.json +++ b/gui/baculum/framework/composer/installed.json @@ -11,8 +11,7 @@ "dist": { "type": "zip", "url": "https://api.github.com/repos/jquery/jquery-dist/zipball/9e8ec3d10fad04748176144f108d7355662ae75e", - "reference": "9e8ec3d10fad04748176144f108d7355662ae75e", - "shasum": null + "reference": "9e8ec3d10fad04748176144f108d7355662ae75e" }, "type": "bower-asset", "installation-source": "dist", @@ -26,14 +25,13 @@ "version_normalized": "1.12.1.0", "source": { "type": "git", - "url": "https://github.com/components/jqueryui.git", + "url": "git@github.com:components/jqueryui.git", "reference": "44ecf3794cc56b65954cc19737234a3119d036cc" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/components/jqueryui/zipball/44ecf3794cc56b65954cc19737234a3119d036cc", - "reference": "44ecf3794cc56b65954cc19737234a3119d036cc", - "shasum": null + "reference": "44ecf3794cc56b65954cc19737234a3119d036cc" }, "require": { "bower-asset/jquery": ">=1.6" @@ -44,6 +42,60 @@ "MIT" ] }, + { + "name": "mrclay/jsmin-php", + "version": "2.4.0", + "version_normalized": "2.4.0.0", + "source": { + "type": "git", + "url": "https://github.com/mrclay/jsmin-php.git", + "reference": "bb05febc9440852d39899255afd5569b7f21a72c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/mrclay/jsmin-php/zipball/bb05febc9440852d39899255afd5569b7f21a72c", + "reference": "bb05febc9440852d39899255afd5569b7f21a72c", + "shasum": "" + }, + "require": { + "ext-pcre": "*", + "php": ">=5.3.0" + }, + "require-dev": { + "phpunit/phpunit": "4.2" + }, + "time": "2018-12-06T15:03:38+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-0": { + "JSMin\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Stephen Clay", + "email": "steve@mrclay.org", + "role": "Developer" + }, + { + "name": "Ryan Grove", + "email": "ryan@wonko.com", + "role": "Developer" + } + ], + "description": "Provides a modified port of Douglas Crockford's jsmin.c, which removes unnecessary whitespace from JavaScript files.", + "homepage": "https://github.com/mrclay/jsmin-php/", + "keywords": [ + "compress", + "jsmin", + "minify" + ] + }, { "name": "pradosoft/prado", "version": "4.0.1", diff --git a/gui/baculum/framework/mrclay/jsmin-php/.editorconfig b/gui/baculum/framework/mrclay/jsmin-php/.editorconfig new file mode 100644 index 000000000..09c610724 --- /dev/null +++ b/gui/baculum/framework/mrclay/jsmin-php/.editorconfig @@ -0,0 +1,19 @@ +# top-most EditorConfig file +root = true + +[*] +charset = utf-8 +end_of_line = lf + +; temporary +trim_trailing_whitespace = false + +[*.php] +indent_style = space +indent_size = 4 +insert_final_newline = true + +[vendor/**] +; Use editor default (possible autodetection). +indent_style = +indent_size = diff --git a/gui/baculum/framework/mrclay/jsmin-php/.gitignore b/gui/baculum/framework/mrclay/jsmin-php/.gitignore new file mode 100644 index 000000000..04e2064f9 --- /dev/null +++ b/gui/baculum/framework/mrclay/jsmin-php/.gitignore @@ -0,0 +1,6 @@ +.idea/ +.DS_Store +/vendor +/composer.lock +/tests/Resources/*/actual/* +composer.phar diff --git a/gui/baculum/framework/mrclay/jsmin-php/HISTORY.txt b/gui/baculum/framework/mrclay/jsmin-php/HISTORY.txt new file mode 100644 index 000000000..ca682d454 --- /dev/null +++ b/gui/baculum/framework/mrclay/jsmin-php/HISTORY.txt @@ -0,0 +1,30 @@ +JSMin fixes + +Version 2.3.2 + * Correctly identifies regexes following keywords with no space. E.g. return/regex/; + +Version 2.3.1 + * Exception classes are PSR-0 loadable + +Version 2.3.0 + * Removes leading UTF-8 BOM + +Version 2.2.0 + * Fix handling of RegEx in certain situations in JSMin + * Fix bug in JSMin exceptions + +Version 2.1.6 + * JSMin fixes + +Version 2.1.4 + * JSMin won't choke on common Closure compiler syntaxes (i+ ++j) + * mbstring.func_overload usage is safer + +Version 2.1.2 + * quote characters inside RegExp literals no longer cause exception + +Version 2.1.0 + * JS: preserves IE conditional comments + +Version 1.0.1 (2007-05-05) + * Replaced old JSMin library with a much faster custom implementation. diff --git a/gui/baculum/framework/mrclay/jsmin-php/LICENSE.txt b/gui/baculum/framework/mrclay/jsmin-php/LICENSE.txt new file mode 100644 index 000000000..8f008adb5 --- /dev/null +++ b/gui/baculum/framework/mrclay/jsmin-php/LICENSE.txt @@ -0,0 +1,26 @@ +Copyright (c) 2008 Ryan Grove +Copyright (c) 2008 Steve Clay +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 this 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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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. diff --git a/gui/baculum/framework/mrclay/jsmin-php/README.devel.txt b/gui/baculum/framework/mrclay/jsmin-php/README.devel.txt new file mode 100644 index 000000000..1d7ffb273 --- /dev/null +++ b/gui/baculum/framework/mrclay/jsmin-php/README.devel.txt @@ -0,0 +1,10 @@ +The following steps can be performed to setup a development environment. + +Download composer.phar as described at https://getcomposer.org/download/ + +Execute composer: + php composer.phar update + +Execute phpunit tests: + ./vendor/bin/phpunit + diff --git a/gui/baculum/framework/mrclay/jsmin-php/composer.json b/gui/baculum/framework/mrclay/jsmin-php/composer.json new file mode 100644 index 000000000..fb00b9743 --- /dev/null +++ b/gui/baculum/framework/mrclay/jsmin-php/composer.json @@ -0,0 +1,34 @@ +{ + "name": "mrclay/jsmin-php", + "type": "library", + "description": "Provides a modified port of Douglas Crockford's jsmin.c, which removes unnecessary whitespace from JavaScript files.", + "keywords": ["jsmin", "minify", "compress"], + "homepage": "https://github.com/mrclay/jsmin-php/", + "license": "MIT", + "authors": [ + { + "name": "Stephen Clay", + "email": "steve@mrclay.org", + "role": "Developer" + }, + { + "name": "Ryan Grove", + "email": "ryan@wonko.com", + "role": "Developer" + } + ], + "support": { + "email": "minify@googlegroups.com", + "issues": "https://github.com/mrclay/jsmin-php/issues" + }, + "require": { + "php": ">=5.3.0", + "ext-pcre": "*" + }, + "require-dev": { + "phpunit/phpunit": "4.2" + }, + "autoload": { + "psr-0": {"JSMin\\": "src/"} + } +} diff --git a/gui/baculum/framework/mrclay/jsmin-php/phpunit.xml.dist b/gui/baculum/framework/mrclay/jsmin-php/phpunit.xml.dist new file mode 100644 index 000000000..37f3bad3a --- /dev/null +++ b/gui/baculum/framework/mrclay/jsmin-php/phpunit.xml.dist @@ -0,0 +1,27 @@ + + + + + + ./tests/ + + + + + + ./ + + ./tests + ./vendor + + + + \ No newline at end of file diff --git a/gui/baculum/framework/mrclay/jsmin-php/src/JSMin/JSMin.php b/gui/baculum/framework/mrclay/jsmin-php/src/JSMin/JSMin.php new file mode 100644 index 000000000..bbf7c5057 --- /dev/null +++ b/gui/baculum/framework/mrclay/jsmin-php/src/JSMin/JSMin.php @@ -0,0 +1,457 @@ + + * $minifiedJs = JSMin::minify($js); + * + * + * This is a modified port of jsmin.c. Improvements: + * + * Does not choke on some regexp literals containing quote characters. E.g. /'/ + * + * Spaces are preserved after some add/sub operators, so they are not mistakenly + * converted to post-inc/dec. E.g. a + ++b -> a+ ++b + * + * Preserves multi-line comments that begin with /*! + * + * 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 (PHP port) + * @author Steve Clay (modifications + cleanup) + * @author Andrea Giammarchi (spaceBeforeRegExp) + * @copyright 2002 Douglas Crockford (jsmin.c) + * @copyright 2008 Ryan Grove (PHP port) + * @license http://opensource.org/licenses/mit-license.php MIT License + * @link http://code.google.com/p/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 = "\n"; + protected $b = ''; + protected $input = ''; + protected $inputIndex = 0; + protected $inputLength = 0; + protected $lookAhead = null; + protected $output = ''; + protected $lastByteOut = ''; + protected $keptComment = ''; + + /** + * Minify Javascript. + * + * @param string $js Javascript to be minified + * + * @return string + */ + public static function minify($js) + { + $jsmin = new JSMin($js); + return $jsmin->min(); + } + + /** + * @param string $input + */ + public function __construct($input) + { + $this->input = $input; + } + + /** + * Perform minification, return result + * + * @return string + */ + public function min() + { + if ($this->output !== '') { // min already run + return $this->output; + } + + $mbIntEnc = null; + if (function_exists('mb_strlen') && ((int)ini_get('mbstring.func_overload') & 2)) { + $mbIntEnc = mb_internal_encoding(); + mb_internal_encoding('8bit'); + } + + if (isset($this->input[0]) && $this->input[0] === "\xef") { + $this->input = substr($this->input, 3); + } + + $this->input = str_replace("\r\n", "\n", $this->input); + $this->inputLength = strlen($this->input); + + $this->action(self::ACTION_DELETE_A_B); + + while ($this->a !== null) { + // determine next command + $command = self::ACTION_KEEP_A; // default + if ($this->a === ' ') { + if (($this->lastByteOut === '+' || $this->lastByteOut === '-') + && ($this->b === $this->lastByteOut)) { + // Don't delete this space. If we do, the addition/subtraction + // could be parsed as a post-increment + } elseif (! $this->isAlphaNum($this->b)) { + $command = self::ACTION_DELETE_A; + } + } elseif ($this->a === "\n") { + if ($this->b === ' ') { + $command = self::ACTION_DELETE_A_B; + + // in case of mbstring.func_overload & 2, must check for null b, + // otherwise mb_strpos will give WARNING + } elseif ($this->b === null + || (false === strpos('{[(+-!~', $this->b) + && ! $this->isAlphaNum($this->b))) { + $command = self::ACTION_DELETE_A; + } + } elseif (! $this->isAlphaNum($this->a)) { + if ($this->b === ' ' + || ($this->b === "\n" + && (false === strpos('}])+-"\'', $this->a)))) { + $command = self::ACTION_DELETE_A_B; + } + } + $this->action($command); + } + $this->output = trim($this->output); + + if ($mbIntEnc !== null) { + mb_internal_encoding($mbIntEnc); + } + return $this->output; + } + + /** + * ACTION_KEEP_A = Output A. Copy B to A. Get the next B. + * ACTION_DELETE_A = Copy B to A. Get the next B. + * ACTION_DELETE_A_B = Get the next B. + * + * @param int $command + * @throws UnterminatedRegExpException|UnterminatedStringException + */ + protected function action($command) + { + // make sure we don't compress "a + ++b" to "a+++b", etc. + if ($command === self::ACTION_DELETE_A_B + && $this->b === ' ' + && ($this->a === '+' || $this->a === '-')) { + // Note: we're at an addition/substraction operator; the inputIndex + // will certainly be a valid index + if ($this->input[$this->inputIndex] === $this->a) { + // This is "+ +" or "- -". Don't delete the space. + $command = self::ACTION_KEEP_A; + } + } + + switch ($command) { + case self::ACTION_KEEP_A: // 1 + $this->output .= $this->a; + + if ($this->keptComment) { + $this->output = rtrim($this->output, "\n"); + $this->output .= $this->keptComment; + $this->keptComment = ''; + } + + $this->lastByteOut = $this->a; + + // fallthrough intentional + case self::ACTION_DELETE_A: // 2 + $this->a = $this->b; + if ($this->a === "'" || $this->a === '"' || $this->a === '`') { // string/template literal + $delimiter = $this->a; + $str = $this->a; // in case needed for exception + for(;;) { + $this->output .= $this->a; + $this->lastByteOut = $this->a; + + $this->a = $this->get(); + if ($this->a === $this->b) { // end quote + break; + } + if ($delimiter === '`' && $this->a === "\n") { + // leave the newline + } elseif ($this->isEOF($this->a)) { + $byte = $this->inputIndex - 1; + throw new UnterminatedStringException( + "JSMin: Unterminated String at byte {$byte}: {$str}"); + } + $str .= $this->a; + if ($this->a === '\\') { + $this->output .= $this->a; + $this->lastByteOut = $this->a; + + $this->a = $this->get(); + $str .= $this->a; + } + } + } + + // fallthrough intentional + case self::ACTION_DELETE_A_B: // 3 + $this->b = $this->next(); + if ($this->b === '/' && $this->isRegexpLiteral()) { + $this->output .= $this->a . $this->b; + $pattern = '/'; // keep entire pattern in case we need to report it in the exception + for(;;) { + $this->a = $this->get(); + $pattern .= $this->a; + if ($this->a === '[') { + for(;;) { + $this->output .= $this->a; + $this->a = $this->get(); + $pattern .= $this->a; + if ($this->a === ']') { + break; + } + if ($this->a === '\\') { + $this->output .= $this->a; + $this->a = $this->get(); + $pattern .= $this->a; + } + if ($this->isEOF($this->a)) { + throw new UnterminatedRegExpException( + "JSMin: Unterminated set in RegExp at byte " + . $this->inputIndex .": {$pattern}"); + } + } + } + + if ($this->a === '/') { // end pattern + break; // while (true) + } elseif ($this->a === '\\') { + $this->output .= $this->a; + $this->a = $this->get(); + $pattern .= $this->a; + } elseif ($this->isEOF($this->a)) { + $byte = $this->inputIndex - 1; + throw new UnterminatedRegExpException( + "JSMin: Unterminated RegExp at byte {$byte}: {$pattern}"); + } + $this->output .= $this->a; + $this->lastByteOut = $this->a; + } + $this->b = $this->next(); + } + // end case ACTION_DELETE_A_B + } + } + + /** + * @return bool + */ + protected function isRegexpLiteral() + { + if (false !== strpos("(,=:[!&|?+-~*{;", $this->a)) { + // we can't divide after these tokens + return true; + } + + // check if first non-ws token is "/" (see starts-regex.js) + $length = strlen($this->output); + if ($this->a === ' ' || $this->a === "\n") { + if ($length < 2) { // weird edge case + return true; + } + } + + // if the "/" follows a keyword, it must be a regexp, otherwise it's best to assume division + + $subject = $this->output . trim($this->a); + if (!preg_match('/(?:case|else|in|return|typeof)$/', $subject, $m)) { + // not a keyword + return false; + } + + // can't be sure it's a keyword yet (see not-regexp.js) + $charBeforeKeyword = substr($subject, 0 - strlen($m[0]) - 1, 1); + if ($this->isAlphaNum($charBeforeKeyword)) { + // this is really an identifier ending in a keyword, e.g. "xreturn" + return false; + } + + // it's a regexp. Remove unneeded whitespace after keyword + if ($this->a === ' ' || $this->a === "\n") { + $this->a = ''; + } + + return true; + } + + /** + * Return the next character from stdin. Watch out for lookahead. If the character is a control character, + * translate it to a space or linefeed. + * + * @return string + */ + protected function get() + { + $c = $this->lookAhead; + $this->lookAhead = null; + if ($c === null) { + // getc(stdin) + if ($this->inputIndex < $this->inputLength) { + $c = $this->input[$this->inputIndex]; + $this->inputIndex += 1; + } else { + $c = null; + } + } + if (ord($c) >= self::ORD_SPACE || $c === "\n" || $c === null) { + return $c; + } + if ($c === "\r") { + return "\n"; + } + return ' '; + } + + /** + * Does $a indicate end of input? + * + * @param string $a + * @return bool + */ + protected function isEOF($a) + { + return ord($a) <= self::ORD_LF; + } + + /** + * Get next char (without getting it). If is ctrl character, translate to a space or newline. + * + * @return string + */ + protected function peek() + { + $this->lookAhead = $this->get(); + return $this->lookAhead; + } + + /** + * Return true if the character is a letter, digit, underscore, dollar sign, or non-ASCII character. + * + * @param string $c + * + * @return bool + */ + protected function isAlphaNum($c) + { + return (preg_match('/^[a-z0-9A-Z_\\$\\\\]$/', $c) || ord($c) > 126); + } + + /** + * Consume a single line comment from input (possibly retaining it) + */ + protected function consumeSingleLineComment() + { + $comment = ''; + while (true) { + $get = $this->get(); + $comment .= $get; + if (ord($get) <= self::ORD_LF) { // end of line reached + // if IE conditional comment + if (preg_match('/^\\/@(?:cc_on|if|elif|else|end)\\b/', $comment)) { + $this->keptComment .= "/{$comment}"; + } + return; + } + } + } + + /** + * Consume a multiple line comment from input (possibly retaining it) + * + * @throws UnterminatedCommentException + */ + protected function consumeMultipleLineComment() + { + $this->get(); + $comment = ''; + for(;;) { + $get = $this->get(); + if ($get === '*') { + if ($this->peek() === '/') { // end of comment reached + $this->get(); + if (0 === strpos($comment, '!')) { + // preserved by YUI Compressor + if (!$this->keptComment) { + // don't prepend a newline if two comments right after one another + $this->keptComment = "\n"; + } + $this->keptComment .= "/*!" . substr($comment, 1) . "*/\n"; + } else if (preg_match('/^@(?:cc_on|if|elif|else|end)\\b/', $comment)) { + // IE conditional + $this->keptComment .= "/*{$comment}*/"; + } + return; + } + } elseif ($get === null) { + throw new UnterminatedCommentException( + "JSMin: Unterminated comment at byte {$this->inputIndex}: /*{$comment}"); + } + $comment .= $get; + } + } + + /** + * Get the next character, skipping over comments. Some comments may be preserved. + * + * @return string + */ + protected function next() + { + $get = $this->get(); + if ($get === '/') { + switch ($this->peek()) { + case '/': + $this->consumeSingleLineComment(); + $get = "\n"; + break; + case '*': + $this->consumeMultipleLineComment(); + $get = ' '; + break; + } + } + return $get; + } +} diff --git a/gui/baculum/framework/mrclay/jsmin-php/src/JSMin/UnterminatedCommentException.php b/gui/baculum/framework/mrclay/jsmin-php/src/JSMin/UnterminatedCommentException.php new file mode 100644 index 000000000..c0bd2f7fa --- /dev/null +++ b/gui/baculum/framework/mrclay/jsmin-php/src/JSMin/UnterminatedCommentException.php @@ -0,0 +1,6 @@ +=0;if(is.ua.indexOf('opera')>=0){is.ie=is.ns=false;is.opera=true;} +if(is.ua.indexOf('gecko')>=0){is.ie=is.ns=false;is.gecko=true;}/*@cc_on + /*@if (@_win32) + if (is.ie && is.win) + document.write("PASS: IE/win honored conditional comment.
"); + @else @*/if(is.ie&&is.win) +document.write("FAIL: IE/win did not honor multi-line conditional comment.
");else +document.write("PASS: Non-IE/win browser ignores multi-line conditional comment.
");/*@end +@*/var recognizesCondComm=true;//@cc_on/* +recognizesCondComm=false;//@cc_on*/ +if((is.ie&&is.win)==recognizesCondComm) +document.write("PASS: IE/win honored single-line conditional comment.
");else +document.write("FAIL: Non-IE/win browser did not ignore single-line conditional comment.
");//@cc_on/* +//@cc_on*/ +//@cc_on/* +'hello'; +/*!* preserved */ +/*!* preserved */ \ No newline at end of file diff --git a/gui/baculum/framework/mrclay/jsmin-php/tests/Resources/minify/expected/condcomm.js b/gui/baculum/framework/mrclay/jsmin-php/tests/Resources/minify/expected/condcomm.js new file mode 100644 index 000000000..5c798318b --- /dev/null +++ b/gui/baculum/framework/mrclay/jsmin-php/tests/Resources/minify/expected/condcomm.js @@ -0,0 +1,6 @@ +var isWin;/*@cc_on + @if (@_win32) + isWin = true; + @else @*/isWin=false;/*@end +@*/isWin=/*@cc_on!*/!1;var recognizesCondComm=true;//@cc_on/* +recognizesCondComm=false;//@cc_on*/ \ No newline at end of file diff --git a/gui/baculum/framework/mrclay/jsmin-php/tests/Resources/minify/expected/es6-literal.js b/gui/baculum/framework/mrclay/jsmin-php/tests/Resources/minify/expected/es6-literal.js new file mode 100644 index 000000000..79d0a1f3c --- /dev/null +++ b/gui/baculum/framework/mrclay/jsmin-php/tests/Resources/minify/expected/es6-literal.js @@ -0,0 +1,2 @@ +`line +break`+`he llo`;foo`hel( '');lo`;`he\nl\`lo`;(`he${one + two}`) \ No newline at end of file diff --git a/gui/baculum/framework/mrclay/jsmin-php/tests/Resources/minify/expected/issue144.js b/gui/baculum/framework/mrclay/jsmin-php/tests/Resources/minify/expected/issue144.js new file mode 100644 index 000000000..e339d0aa5 --- /dev/null +++ b/gui/baculum/framework/mrclay/jsmin-php/tests/Resources/minify/expected/issue144.js @@ -0,0 +1 @@ +a/++b;a*--b;a++-b;a+--b;a-++b;a+-b;a+ ++b;a+--b;a- --b; \ No newline at end of file diff --git a/gui/baculum/framework/mrclay/jsmin-php/tests/Resources/minify/expected/issue256.js b/gui/baculum/framework/mrclay/jsmin-php/tests/Resources/minify/expected/issue256.js new file mode 100644 index 000000000..eb1b0d6ed --- /dev/null +++ b/gui/baculum/framework/mrclay/jsmin-php/tests/Resources/minify/expected/issue256.js @@ -0,0 +1,2 @@ +!function(){}(window) +!function(){}(window) \ No newline at end of file diff --git a/gui/baculum/framework/mrclay/jsmin-php/tests/Resources/minify/expected/keyword-regex.js b/gui/baculum/framework/mrclay/jsmin-php/tests/Resources/minify/expected/keyword-regex.js new file mode 100644 index 000000000..02ec79ee0 --- /dev/null +++ b/gui/baculum/framework/mrclay/jsmin-php/tests/Resources/minify/expected/keyword-regex.js @@ -0,0 +1 @@ +return/return/; \ No newline at end of file diff --git a/gui/baculum/framework/mrclay/jsmin-php/tests/Resources/minify/expected/not-regexp.js b/gui/baculum/framework/mrclay/jsmin-php/tests/Resources/minify/expected/not-regexp.js new file mode 100644 index 000000000..a7516fbcc --- /dev/null +++ b/gui/baculum/framework/mrclay/jsmin-php/tests/Resources/minify/expected/not-regexp.js @@ -0,0 +1 @@ +!function(){return xreturn/foo}();!function(){return xtypeof/foo}(); \ No newline at end of file diff --git a/gui/baculum/framework/mrclay/jsmin-php/tests/Resources/minify/expected/regexes.js b/gui/baculum/framework/mrclay/jsmin-php/tests/Resources/minify/expected/regexes.js new file mode 100644 index 000000000..d7d5b4ec1 --- /dev/null +++ b/gui/baculum/framework/mrclay/jsmin-php/tests/Resources/minify/expected/regexes.js @@ -0,0 +1,2 @@ +function testIssue74(){return/'/;} +!function(s){return/^[£$€?.]/.test(s);}();typeof/ ' /;x=/ [/] /;1/foo;(2)/foo;function(){return/foo/};function(){return typeof/foo/}; \ No newline at end of file diff --git a/gui/baculum/framework/mrclay/jsmin-php/tests/Resources/minify/expected/starts-regex.js b/gui/baculum/framework/mrclay/jsmin-php/tests/Resources/minify/expected/starts-regex.js new file mode 100644 index 000000000..262362475 --- /dev/null +++ b/gui/baculum/framework/mrclay/jsmin-php/tests/Resources/minify/expected/starts-regex.js @@ -0,0 +1 @@ +/return/.test(bar); \ No newline at end of file diff --git a/gui/baculum/framework/mrclay/jsmin-php/tests/Resources/minify/expected/token-regexp.js b/gui/baculum/framework/mrclay/jsmin-php/tests/Resources/minify/expected/token-regexp.js new file mode 100644 index 000000000..13f263ca9 --- /dev/null +++ b/gui/baculum/framework/mrclay/jsmin-php/tests/Resources/minify/expected/token-regexp.js @@ -0,0 +1 @@ +typeof[/return/]; \ No newline at end of file diff --git a/gui/baculum/framework/mrclay/jsmin-php/tests/Resources/minify/input/before.js b/gui/baculum/framework/mrclay/jsmin-php/tests/Resources/minify/input/before.js new file mode 100644 index 000000000..ae9656825 --- /dev/null +++ b/gui/baculum/framework/mrclay/jsmin-php/tests/Resources/minify/input/before.js @@ -0,0 +1,66 @@ +/*! is.js + + (c) 2001 Douglas Crockford + 2001 June 3 +*/ + +// is + +// The -is- object is used to identify the browser. Every browser edition +// identifies itself, but there is no standard way of doing it, and some of +// the identification is deceptive. This is because the authors of web +// browsers are liars. For example, Microsoft's IE browsers claim to be +// Mozilla 4. Netscape 6 claims to be version 5. + +var is = { + ie: navigator.appName == 'Microsoft Internet Explorer', + java: navigator.javaEnabled(), + ns: navigator.appName == 'Netscape', + ua: navigator.userAgent.toLowerCase(), + version: parseFloat(navigator.appVersion.substr(21)) || + parseFloat(navigator.appVersion), + win: navigator.platform == 'Win32' +} +/*!* + * preserve this comment, too + */ +is.mac = is.ua.indexOf('mac') >= 0; +if (is.ua.indexOf('opera') >= 0) { + is.ie = is.ns = false; + is.opera = true; +} +if (is.ua.indexOf('gecko') >= 0) { + is.ie = is.ns = false; + is.gecko = true; +} + +/*@cc_on + /*@if (@_win32) + if (is.ie && is.win) + document.write("PASS: IE/win honored conditional comment.
"); + @else @*/ + if (is.ie && is.win) + document.write("FAIL: IE/win did not honor multi-line conditional comment.
"); + else + document.write("PASS: Non-IE/win browser ignores multi-line conditional comment.
"); + /*@end +@*/ + +var recognizesCondComm = true; +//@cc_on/* +recognizesCondComm = false; +//@cc_on*/ + +if ((is.ie && is.win) == recognizesCondComm) + document.write("PASS: IE/win honored single-line conditional comment.
"); +else + document.write("FAIL: Non-IE/win browser did not ignore single-line conditional comment.
"); + +// hello +//@cc_on/* +// world +//@cc_on*/ +//@cc_on/* +'hello'; +/*!* preserved */ +/*!* preserved */ \ No newline at end of file diff --git a/gui/baculum/framework/mrclay/jsmin-php/tests/Resources/minify/input/condcomm.js b/gui/baculum/framework/mrclay/jsmin-php/tests/Resources/minify/input/condcomm.js new file mode 100644 index 000000000..28aa1268b --- /dev/null +++ b/gui/baculum/framework/mrclay/jsmin-php/tests/Resources/minify/input/condcomm.js @@ -0,0 +1,14 @@ +var isWin; +/*@cc_on + @if (@_win32) + isWin = true; + @else @*/ isWin = false; + /*@end +@*/ + +isWin = /*@cc_on!*/!1; + +var recognizesCondComm = true; +//@cc_on/* +recognizesCondComm = false; +//@cc_on*/ diff --git a/gui/baculum/framework/mrclay/jsmin-php/tests/Resources/minify/input/es6-literal.js b/gui/baculum/framework/mrclay/jsmin-php/tests/Resources/minify/input/es6-literal.js new file mode 100644 index 000000000..57aea260f --- /dev/null +++ b/gui/baculum/framework/mrclay/jsmin-php/tests/Resources/minify/input/es6-literal.js @@ -0,0 +1,2 @@ +`line +break` + `he llo`; foo`hel( '');lo`; `he\nl\`lo`; (`he${one + two}`) diff --git a/gui/baculum/framework/mrclay/jsmin-php/tests/Resources/minify/input/issue144.js b/gui/baculum/framework/mrclay/jsmin-php/tests/Resources/minify/input/issue144.js new file mode 100644 index 000000000..204911da3 --- /dev/null +++ b/gui/baculum/framework/mrclay/jsmin-php/tests/Resources/minify/input/issue144.js @@ -0,0 +1,9 @@ +a / ++b; +a * --b; +a++ - b; +a + --b; +a - ++b; +a + -b; +a + ++b; +a + --b; +a - --b; \ No newline at end of file diff --git a/gui/baculum/framework/mrclay/jsmin-php/tests/Resources/minify/input/issue256.js b/gui/baculum/framework/mrclay/jsmin-php/tests/Resources/minify/input/issue256.js new file mode 100644 index 000000000..519a52f85 --- /dev/null +++ b/gui/baculum/framework/mrclay/jsmin-php/tests/Resources/minify/input/issue256.js @@ -0,0 +1,3 @@ +!function(){}(window) + +!function(){}(window) \ No newline at end of file diff --git a/gui/baculum/framework/mrclay/jsmin-php/tests/Resources/minify/input/keyword-regex.js b/gui/baculum/framework/mrclay/jsmin-php/tests/Resources/minify/input/keyword-regex.js new file mode 100644 index 000000000..36e2fce99 --- /dev/null +++ b/gui/baculum/framework/mrclay/jsmin-php/tests/Resources/minify/input/keyword-regex.js @@ -0,0 +1,3 @@ +// this is specifically designed so that, if the first "/" is misinterpreted as division, +// then "/;" will be interpreted as an incomplete regexp, causing a failing test. +return /return/; \ No newline at end of file diff --git a/gui/baculum/framework/mrclay/jsmin-php/tests/Resources/minify/input/not-regexp.js b/gui/baculum/framework/mrclay/jsmin-php/tests/Resources/minify/input/not-regexp.js new file mode 100644 index 000000000..9da508269 --- /dev/null +++ b/gui/baculum/framework/mrclay/jsmin-php/tests/Resources/minify/input/not-regexp.js @@ -0,0 +1,3 @@ +!function(){return xreturn/foo}(); + +!function(){return xtypeof/foo}(); diff --git a/gui/baculum/framework/mrclay/jsmin-php/tests/Resources/minify/input/regexes.js b/gui/baculum/framework/mrclay/jsmin-php/tests/Resources/minify/input/regexes.js new file mode 100644 index 000000000..57e083e3a --- /dev/null +++ b/gui/baculum/framework/mrclay/jsmin-php/tests/Resources/minify/input/regexes.js @@ -0,0 +1,24 @@ +function testIssue74() { + return /'/; +} + +!function(s) { + return /^[£$€?.]/.test(s); +}(); + +typeof + / ' /; + +x = / [/] /; + +1 + +/ foo; + +(2) + +/ foo; + +function(){return/foo/}; + +function(){return typeof/foo/}; diff --git a/gui/baculum/framework/mrclay/jsmin-php/tests/Resources/minify/input/starts-regex.js b/gui/baculum/framework/mrclay/jsmin-php/tests/Resources/minify/input/starts-regex.js new file mode 100644 index 000000000..997b9055d --- /dev/null +++ b/gui/baculum/framework/mrclay/jsmin-php/tests/Resources/minify/input/starts-regex.js @@ -0,0 +1,3 @@ +// this is specifically designed so that, if the first "/" is misinterpreted as division, +// then "/.test(bar);" will be interpreted as an incomplete regexp, causing a failing test. +/return/.test(bar); \ No newline at end of file diff --git a/gui/baculum/framework/mrclay/jsmin-php/tests/Resources/minify/input/token-regexp.js b/gui/baculum/framework/mrclay/jsmin-php/tests/Resources/minify/input/token-regexp.js new file mode 100644 index 000000000..917bd2047 --- /dev/null +++ b/gui/baculum/framework/mrclay/jsmin-php/tests/Resources/minify/input/token-regexp.js @@ -0,0 +1,3 @@ +// this is specifically designed so that, if the first "/" is misinterpreted as division, +// then "/[;" will be interpreted as an incomplete regexp, causing a failing test. +typeof [/return/]; \ No newline at end of file diff --git a/gui/baculum/framework/mrclay/jsmin-php/tests/Tests/JSMin/JSMinTest.php b/gui/baculum/framework/mrclay/jsmin-php/tests/Tests/JSMin/JSMinTest.php new file mode 100644 index 000000000..90b8aace4 --- /dev/null +++ b/gui/baculum/framework/mrclay/jsmin-php/tests/Tests/JSMin/JSMinTest.php @@ -0,0 +1,168 @@ +assertEquals($expected, $actual, 'Running Minify Test: ' . $testName); + } + + public function testWhitespace() { + $this->assertEquals("hello;", JSMin::minify("\r\n\r\nhello;\r\n")); + } + + public function testBomRemoval() { + $this->assertEquals("hello;", JSMin::minify("\xEF\xBB\xBFhello;")); + } + + public function testFuncOverload() { + if (!function_exists('mb_strlen') || !((int)ini_get('mbstring.func_overload') & 2)) { + $this->markTestIncomplete('Cannot be tested unless mbstring.func_overload is used'); + return; + } + + $input = 'function(s) { return /^[£$€?.]/.test(s); }'; + $expected = 'function(s){return/^[£$€?.]/.test(s);}'; + $this->assertEquals($expected, JSMin::minify($input)); + } + + /** + * @dataProvider exceptionProvider + */ + public function testExpections($input, $label, $expClass, $expMessage) { + $eClass = $eMsg = ''; + try { + JSMin::minify($input); + } catch (\Exception $e) { + $eClass = get_class($e); + $eMsg = $e->getMessage(); + } + $this->assertTrue( + $eClass === $expClass && $eMsg === $expMessage, + 'JSMin : throw on ' . $label + ); + } + + public function exceptionProvider() { + return array( + array( + '"Hello' + ,'Unterminated String' + ,'JSMin\\UnterminatedStringException' + ,"JSMin: Unterminated String at byte 5: \"Hello"), + array( + "return /regexp\n}" + ,'Unterminated RegExp' + ,'JSMin\\UnterminatedRegExpException' + ,"JSMin: Unterminated RegExp at byte 14: /regexp\n"), + array( + "return/regexp\n}" + ,'Unterminated RegExp' + ,'JSMin\\UnterminatedRegExpException' + ,"JSMin: Unterminated RegExp at byte 13: /regexp\n"), + array( + ";return/regexp\n}" + ,'Unterminated RegExp' + ,'JSMin\\UnterminatedRegExpException' + ,"JSMin: Unterminated RegExp at byte 14: /regexp\n"), + array( + ";return /regexp\n}" + ,'Unterminated RegExp' + ,'JSMin\\UnterminatedRegExpException' + ,"JSMin: Unterminated RegExp at byte 15: /regexp\n"), + array( + "typeof/regexp\n}" + ,'Unterminated RegExp' + ,'JSMin\\UnterminatedRegExpException' + ,"JSMin: Unterminated RegExp at byte 13: /regexp\n"), + array( + "/* Comment " + ,'Unterminated Comment' + ,'JSMin\\UnterminatedCommentException' + ,"JSMin: Unterminated comment at byte 11: /* Comment "), + ); + } + + /** + * This function loads all of the test cases from the specified group. + * Groups are created simply by populating the appropriate directories: + * + * /tests/Resources/GROUPNAME/input/ + * /tests/Resources/GROUPNAME/output/ + * + * Each test case should have two identically named files, with the raw + * javascript going in the test folder and the expected results to be in + * the output folder. + * + * @param $group string + * @return array + */ + public function getTestFiles($group) + { + $baseDir = __DIR__ . '/../../Resources/' . $group . '/'; + $testDir = $baseDir . 'input/'; + $expectDir = $baseDir . 'expected/'; + $actualDir = $baseDir . 'actual/'; + + $returnData = array(); + + $testFiles = scandir($testDir); + foreach ($testFiles as $testFile) { + if (substr($testFile, -3) !== '.js' || !file_exists(($expectDir . $testFile))) { + continue; + } + + $testInput = file_get_contents($testDir . $testFile); + $expectedOutput = file_get_contents($expectDir . $testFile); + $actualFile = $actualDir . $testFile; + + $returnData[] = array($testFile, $testInput, $expectedOutput, $actualFile); + } + + return $returnData; + } + + public function minifyProvider() + { + return $this->getTestFiles('minify'); + } +} diff --git a/gui/baculum/framework/mrclay/jsmin-php/tests/bootstrap.php b/gui/baculum/framework/mrclay/jsmin-php/tests/bootstrap.php new file mode 100644 index 000000000..b3d9bbc7f --- /dev/null +++ b/gui/baculum/framework/mrclay/jsmin-php/tests/bootstrap.php @@ -0,0 +1 @@ +" . h($e->getMessage()) . "

"; + + if (0 !== strpos(get_class($e), 'JSMin\\Unterminated') + || !preg_match('~byte (\d+)~', $e->getMessage(), $m)) { + return $msg; + } + + $msg .= "
";
+    if ($m[1] > 200) {
+        $msg .= h(substr($input, ($m[1] - 200), 200));
+    } else {
+        $msg .= h(substr($input, 0, $m[1]));
+    }
+    $highlighted = isset($input[$m[1]]) ? h($input[$m[1]]) : '␄';
+    if ($highlighted === "\n") {
+        $highlighted = "⏎\n";
+    }
+    $msg .= "$highlighted";
+    $msg .= h(substr($input, $m[1] + 1, 200)) . "
"; + + return $msg; +} + +/** + * Draw page + * + * @param array $vars + */ +function sendPage($vars) { + header('Content-Type: text/html; charset=utf-8'); + + ?> + JSMin + + Bytes in{$vars['inBytes']} (after line endings normalized to \\n) + Bytes out{$vars['outBytes']} (reduced " . round(100 - (100 * $vars['outBytes'] / $vars['inBytes'])) . "%) + Time (s)" . round($vars['time'], 5) . " + + "; + } + ?> +
+

+

+