function test_Minify_JS_ClosureCompiler() { global $thisDir; $src = "\n(function (window, undefined){\n function addOne(input) {\n return 1 + input;\n }\n window.addOne = addOne;\n window.undefined = undefined;\n})(window);\n "; $minExpected = "(function(a,b){a.addOne=function(a){return 1+a};a.undefined=b})(window);"; $minOutput = Minify_JS_ClosureCompiler::minify($src); if (false !== strpos($minOutput, 'Error(22): Too many compiles')) { echo "!NOTE: Too many recent calls to Closure Compiler API to test.\n"; return; } $passed = assertTrue($minExpected == $minOutput, 'Minify_JS_ClosureCompiler : Overall'); if (__FILE__ === realpath($_SERVER['SCRIPT_FILENAME'])) { echo "\n---Output: " . countBytes($minOutput) . " bytes\n\n{$minOutput}\n\n"; echo "---Expected: " . countBytes($minExpected) . " bytes\n\n{$minExpected}\n\n"; echo "---Source: " . countBytes($src) . " bytes\n\n{$src}\n\n\n"; } $src = "function blah({ return 'blah';} "; $exc = null; try { $minOutput = Minify_JS_ClosureCompiler::minify($src); } catch (Exception $e) { $exc = $e; } $passed = assertTrue($exc instanceof Minify_JS_ClosureCompiler_Exception, 'Minify_JS_ClosureCompiler : Throws Minify_JS_ClosureCompiler_Exception'); if (__FILE__ === realpath($_SERVER['SCRIPT_FILENAME'])) { echo "\n---Message: " . var_export($exc->getMessage(), 1) . "\n\n\n"; } }
public function js($js) { if (!is_array($js)) { $js = array($js); } if (craft()->config->get('devMode')) { $html = ""; foreach ($js as $file) { $html .= "<script src=\"{$file}\"></script>"; } $charset = craft()->templates->getTwig()->getCharset(); return new \Twig_Markup($html, $charset); } $recache = $this->recache($js, "js"); if ($recache['recache'] === false) { return $this->outputJs($recache['cache_file']); } else { if ($recache['recache'] === true) { $cached_file = $this->makeCachePath("cached." . $recache['md5'] . ".js"); $js_content = ""; foreach ($js as $file) { $file = $this->isLocalFile($file) ? $this->document_root . '/' . ltrim($file, '/') : $file; $js_content .= file_get_contents($file); } require_once __DIR__ . '/../lib/Minify/JS/ClosureCompiler.php'; $minified = \Minify_JS_ClosureCompiler::minify($js_content); if (!$minified) { require_once __DIR__ . '/../lib/JShrink/Minifier.php'; $minified = \JShrink\Minifier::minify($js_content, array('flaggedComments' => false)); } file_put_contents($cached_file, $minified); return $this->outputJs(basename($cached_file)); } } }
/** * Create the cache file if it doesnt exist * Return the combined js either compressed or not (depending on the setting) */ private function _script() { // only compress if we're in production if (Configure::read('debug') == 0 || $this->live == true) { // no cache file? write it $cache = $this->filename('js'); if (!file_exists($this->settings['js']['route'] . DS . $cache)) { // get chunks $output = null; $chunks = $this->chunks($this->js['intern']); // compress? if ($this->settings['js']['compression']) { foreach ($chunks as $content) { $output .= trim(\Minify_JS_ClosureCompiler::minify($content)); } } else { $output = implode("\n", $chunks); } // write to file file_put_contents($this->settings['js']['route'] . DS . $cache, $output); } // output with the HTML helper echo $this->Html->script($this->settings['js']['path'] . '/' . $cache, $this->settings['js']['async'] == true ? ['async' => 'async'] : []); // development mode, output separately with the HTML helper } else { echo $this->Html->script($this->js['extern']); } }
/** * Combines and minifies the given local files. * That is if the resulting minified file does not exist yet, * nor it is not older than any of the given files. * * @param string $type Either js or css * @param array $files List of files location in the public_html/[type]/ folder * @return boolean True if the resulting file was updated */ private function minify($type, $files) { // Are there newer source files than the single output file? $newerexists = false; // Return value will be this $wrote = false; // Keep log of what has happened and how much the filesizes were reduced. $dateformat = 'Y-m-d H:i:s'; $log = ''; // Function failed on a mismatching parametre? $fail = false; if ($type == 'js') { require_once $this->config['renshuubase'] . 'libs/minify/Minify/JS/ClosureCompiler.php'; } else { if ($type == 'css') { require_once $this->config['renshuubase'] . 'libs/minify/Minify/CSS/Compressor.php'; } else { $fail = true; } } if (!is_array($files) || count($files) == 0) { $fail = true; } if (!$fail) { $data = array(); $mtime_newest = 0; foreach ($files as $file) { $src = realpath('./' . $type) . '/' . $file; if (file_exists($src)) { $minify = true; $mtime_src = filemtime($src); $p = explode('.', $file); // Remove suffix temporarily for the ".min" check if (end($p) == $type) { unset($p[count($p) - 1]); } // If the filename has a ".min" appended in the end, its content is used as such. if (end($p) == 'min') { $des = $src; $minify = false; } else { // Rebuild the name by including ".min" in the end $p[] = 'min'; $p[] = $type; $des = realpath('./' . $type) . '/' . implode('.', $p); } //echo "\n" . '<!-- src: ' . $src . ', des: ' . $des . ' -->' . "\n"; $log .= date($dateformat) . ' src: ' . $src . ', size: ' . filesize($src) . "\n"; $min = ''; if (file_exists($des)) { $mtime_des = filemtime($des); //echo '<!-- mtime_src: ' . $mtime_src . ', mtime_des: ' . $mtime_des . ' -->' . "\n"; if ($mtime_src <= $mtime_des) { $minify = false; $min = file_get_contents($des); $mtime_newest = max($mtime_des, $mtime_newest); } } //echo '<!-- minify: ' . $minify . ' -->' . "\n"; if ($minify) { $cont = file_get_contents($src); if ($type == 'js') { //$min = JSMin::minify($cont); try { $min = Minify_JS_ClosureCompiler::minify($cont); } catch (Exception $error) { echo $error->getMessage() . ' while src: ' . $src; } } else { if ($type == 'css') { $min = Minify_CSS_Compressor::process($cont); } } $mtime_newest = time(); file_put_contents($des, $min); $log .= date($dateformat) . ' des: ' . $des . ', size: ' . filesize($des) . "\n"; } $data[] = '/* ' . $file . ' */' . "\n" . $min; } } $outfile = realpath('./' . $type) . '/' . $this->config['minified'] . '.' . $type; $outfilegz = realpath('./' . $type) . '/' . $this->config['minified'] . '.gz.' . $type; if (file_exists($outfile)) { $mtime_out = filemtime($outfile); } else { $newerexists = true; } if ($newerexists || $mtime_newest > $mtime_out) { $alldata = implode("\n\n", $data); $bytecount = file_put_contents($outfile, $alldata); $log .= date($dateformat) . ' outfile: ' . $outfile . ', size: ' . $bytecount . "\n"; if ($bytecount !== false) { $gz = gzopen($outfilegz, 'wb9'); gzwrite($gz, $alldata); gzclose($gz); $wrote = true; $log .= date($dateformat) . ' outfilegz: ' . $outfilegz . ', size: ' . filesize($outfilegz) . "\n"; } } } file_put_contents($this->config['minifylog'], $log, FILE_APPEND); return $wrote; }
/** * To use Google's Closure Compiler API (falling back to JSMin on failure), * uncomment the following lines: */ function closureCompiler($js) { require_once 'lib/Minify/JS/ClosureCompiler.php'; return Minify_JS_ClosureCompiler::minify($js); }
function test_Minify_JS_ClosureCompiler() { global $thisDir; $src = "\n(function (window, undefined){\n function addOne(input) {\n return 1 + input;\n }\n window.addOne = addOne;\n window.undefined = undefined;\n})(window);\n "; $minExpected = "(function(a,b){a.addOne=function(a){return 1+a};a.undefined=b})(window);"; $minOutput = Minify_JS_ClosureCompiler::minify($src); if (false !== strpos($minOutput, 'Error(22): Too many compiles')) { echo "!---: Minify_JS_ClosureCompiler : Too many recent calls to Closure Compiler API to test.\n"; return; } $passed = assertTrue($minExpected == $minOutput, 'Minify_JS_ClosureCompiler : Overall'); if (__FILE__ === realpath($_SERVER['SCRIPT_FILENAME'])) { echo "\n---Output: " . countBytes($minOutput) . " bytes\n\n{$minOutput}\n\n"; echo "---Expected: " . countBytes($minExpected) . " bytes\n\n{$minExpected}\n\n"; echo "---Source: " . countBytes($src) . " bytes\n\n{$src}\n\n\n"; } $src = "function blah({ return 'blah';} "; $exc = null; try { $minOutput = Minify_JS_ClosureCompiler::minify($src); } catch (Exception $e) { $exc = $e; } $passed = assertTrue($exc instanceof Minify_JS_ClosureCompiler_Exception, 'Minify_JS_ClosureCompiler : Throws Minify_JS_ClosureCompiler_Exception'); if (__FILE__ === realpath($_SERVER['SCRIPT_FILENAME'])) { echo "\n---Message: " . var_export($exc->getMessage(), 1) . "\n\n\n"; } // Test maximum byte size check (default) $fn = "(function() {})();"; $src = str_repeat($fn, ceil(Minify_JS_ClosureCompiler::DEFAULT_MAX_BYTES / strlen($fn))); $exc = null; try { $minOutput = Minify_JS_ClosureCompiler::minify($src); } catch (Exception $e) { $exc = $e; } $passed = assertTrue($exc instanceof Minify_JS_ClosureCompiler_Exception, 'Minify_JS_ClosureCompiler : Throws Minify_JS_ClosureCompiler_Exception'); assertTrue($exc->getMessage() === 'POST content larger than ' . Minify_JS_ClosureCompiler::DEFAULT_MAX_BYTES . ' bytes', 'Minify_JS_ClosureCompiler : Message must tell how big maximum byte size is'); if (__FILE__ === realpath($_SERVER['SCRIPT_FILENAME'])) { echo "\n---Message: " . var_export($exc->getMessage(), 1) . "\n\n\n"; } // Test maximum byte size check (no limit) $src = "(function(){})();"; try { $minOutput = Minify_JS_ClosureCompiler::minify($src, array(Minify_JS_ClosureCompiler::OPTION_MAX_BYTES => 0)); } catch (Exception $e) { $exc = $e; } $passed = assertTrue($src === $minOutput, 'Minify_JS_ClosureCompiler : With no limit set, it should compile properly'); // Test maximum byte size check (custom) $src = "(function() {})();"; $allowedBytes = 5; $exc = null; try { $minOutput = Minify_JS_ClosureCompiler::minify($src, array(Minify_JS_ClosureCompiler::OPTION_MAX_BYTES => $allowedBytes)); } catch (Exception $e) { $exc = $e; } $passed = assertTrue($exc instanceof Minify_JS_ClosureCompiler_Exception, 'Minify_JS_ClosureCompiler : Throws Minify_JS_ClosureCompiler_Exception'); assertTrue($exc->getMessage() === 'POST content larger than ' . $allowedBytes . ' bytes', 'Minify_JS_ClosureCompiler : Message must tell how big maximum byte size is'); if (__FILE__ === realpath($_SERVER['SCRIPT_FILENAME'])) { echo "\n---Message: " . var_export($exc->getMessage(), 1) . "\n\n\n"; } // Test additional options passed to HTTP request $ecmascript5 = "[1,].length;"; $exc = null; try { $minOutput = Minify_JS_ClosureCompiler::minify($ecmascript5); } catch (Exception $e) { $exc = $e; } $passed = assertTrue($exc instanceof Minify_JS_ClosureCompiler_Exception, 'Minify_JS_ClosureCompiler : Throws Minify_JS_ClosureCompiler_Exception'); if (__FILE__ === realpath($_SERVER['SCRIPT_FILENAME'])) { echo "\n---Message: " . var_export($exc->getMessage(), 1) . "\n\n\n"; } $minExpected = '1;'; $minOutput = Minify_JS_ClosureCompiler::minify($ecmascript5, array(Minify_JS_ClosureCompiler::OPTION_ADDITIONAL_OPTIONS => array('language' => 'ECMASCRIPT5'))); $passed = assertTrue($minOutput === $minExpected, 'Minify_JS_ClosureCompiler : Language option should make it compile'); }