This is a heavy regex-based removal of whitespace, unnecessary
comments and tokens, and some CSS value minimization, where practical.
Many steps have been taken to avoid breaking comment-based hacks,
including the ie5/mac filter (and its inversion), but expect tricky
hacks involving comment tokens in 'content' value strings to break
minimization badly. A test suite is available.
public function dispatchLoopShutdown() { if (!Tool::isHtmlResponse($this->getResponse())) { return; } if (\Pimcore::inDebugMode()) { return; } if (!Tool::useFrontendOutputFilters($this->getRequest()) && !$this->getRequest()->getParam("pimcore_preview")) { return; } if ($this->enabled) { include_once "simple_html_dom.php"; $body = $this->getResponse()->getBody(); $html = str_get_html($body); if ($html) { $styles = $html->find("link[rel=stylesheet], style[type=text/css]"); $stylesheetContent = ""; foreach ($styles as $style) { if ($style->tag == "style") { $stylesheetContent .= $style->innertext; } else { $source = $style->href; $path = ""; if (is_file(PIMCORE_ASSET_DIRECTORY . $source)) { $path = PIMCORE_ASSET_DIRECTORY . $source; } else { if (is_file(PIMCORE_DOCUMENT_ROOT . $source)) { $path = PIMCORE_DOCUMENT_ROOT . $source; } } if (!empty($path) && is_file("file://" . $path)) { $content = file_get_contents($path); $content = $this->correctReferences($source, $content); if ($style->media && $style->media != "all") { $content = "@media " . $style->media . " {" . $content . "}"; } $stylesheetContent .= $content; $style->outertext = ""; } } } if (strlen($stylesheetContent) > 1) { $stylesheetPath = PIMCORE_TEMPORARY_DIRECTORY . "/minified_css_" . md5($stylesheetContent) . ".css"; if (!is_file($stylesheetPath)) { $stylesheetContent = \Minify_CSS::minify($stylesheetContent); // put minified contents into one single file file_put_contents($stylesheetPath, $stylesheetContent); chmod($stylesheetPath, 0766); } $head = $html->find("head", 0); $head->innertext = $head->innertext . "\n" . '<link rel="stylesheet" type="text/css" href="' . str_replace(PIMCORE_DOCUMENT_ROOT, "", $stylesheetPath) . '" />' . "\n"; } $body = $html->save(); $html->clear(); unset($html); $this->getResponse()->setBody($body); } } }
/** * Summarize the file registry in a way like * [ 'ext1' => 'contents', 'ext2' => 'contents' ] * * @return array */ function summarize_registry() { $summasummarum = array(); $keys = array_keys($_SESSION['files_registry']); foreach ($keys as $filename) { $summarized = ""; $last_dot_pos = strrpos($filename, "."); $ext = strtolower(substr($filename, $last_dot_pos + 1, strlen($filename) - $last_dot_pos - 1)); if (!$_SESSION['files_registry'][$filename]['good']) { unset($_SESSION['files_registry'][$filename]); echo sprintf("[Deleted] %s\n-- %s\n\n", date('H:i:s'), $filename); continue; } $summarized .= trim(file_get_contents($filename)); if (!isset($summasummarum[$ext])) { $summasummarum[$ext] = ""; } if ($ext == 'css') { $summarized = Minify_CSS::minify(file_get_contents($filename)); } else { if ($ext == 'js') { $summarized = JSMinPlus::minify(file_get_contents($filename)); } else { $summarized = trim(file_get_contents($filename)); } } $summasummarum[$ext] .= $summarized; } return $summasummarum; }
public function action_css() { $group = (string) $this->request->param('group'); if (empty($group)) { $group = 'default'; } if (!($content = Kohana::cache('minify::css::' . $group))) { $path = isset($this->_config['css'][$group]['path']) ? $this->_config['css'][$group]['path'] : ''; $files = isset($this->_config['css'][$group]['files']) ? $this->_config['css'][$group]['files'] : array(); if (!is_array($files)) { $files = array(); } $content = ''; foreach ($files as $file) { $content .= file_get_contents($path . DIRECTORY_SEPARATOR . $file); } if (!empty($content)) { $minifier = isset($this->_config['css'][$group]['minifier']) ? $this->_config['css'][$group]['minifier'] : ''; if (class_exists($minifier)) { $class = new ReflectionClass($minifier); $css_min = $class->newInstance($content, array('current_dir' => $path)); $content = $class->getMethod('min')->invoke($css_min); } else { $content = Minify_CSS::minify($content, array('current_dir' => $path)); } } if ((bool) $this->_config['cache']) { Kohana::cache('minify::css::' . $group, $content, (int) $this->_config['cache_lifetime']); } } $this->response->body($content); }
/** * Minify css * * @param string $content * @return string */ function minifyCss($content) { if (!empty($_GET['minoff'])) { return $content; } require_once 'Minify/CSS.php'; return Minify_CSS::minify($content); }
/** * Minify a CSS string * * @param string $css * * @param array $options available options: * * 'preserveComments': (default true) multi-line comments that begin * with "/*!" will be preserved with newlines before and after to * enhance readability. * * 'removeCharsets': (default true) remove all @charset at-rules * * 'prependRelativePath': (default null) if given, this string will be * prepended to all relative URIs in import/url declarations * * 'currentDir': (default null) if given, this is assumed to be the * directory of the current CSS file. Using this, minify will rewrite * all relative URIs in import/url declarations to correctly point to * the desired files. For this to work, the files *must* exist and be * visible by the PHP process. * * 'symlinks': (default = array()) If the CSS file is stored in * a symlink-ed directory, provide an array of link paths to * target paths, where the link paths are within the document root. Because * paths need to be normalized for this to work, use "//" to substitute * the doc root in the link paths (the array keys). E.g.: * <code> * array('//symlink' => '/real/target/path') // unix * array('//static' => 'D:\\staticStorage') // Windows * </code> * * 'doc_root': (default = $_SERVER['DOCUMENT_ROOT']) * see Minify_CSS_Uri_Rewriter::rewrite * * @return string */ public static function minify($css, array $options = array()) { static $instance; // this is a singleton if (!$instance) { $instance = new Minify_CSS($css, $options); } return $instance->min(); }
public static function minify($filename) { require_once Pimple::instance()->getRessource('lib/minify/min/lib/Minify/CSS.php'); require_once Pimple::instance()->getRessource('lib/minify/min/lib/Minify/CSS/Compressor.php'); $isPimple = String::StartsWith($filename, Pimple::instance()->getBaseDir()); $base = dirname($isPimple ? substr($filename, strlen(Pimple::instance()->getBaseDir() . 'www/')) : substr($filename, strlen(Pimple::instance()->getSiteDir()))) . '/'; $base = $isPimple ? Settings::get(Pimple::URL) . $base : Url::basePath() . $base; return Minify_CSS::minify(String::normalize(file_get_contents($filename), false), array('prependRelativePath' => $base)); }
public static function getMinimizedStylesheetPath($stylesheetContent) { $stylesheetPath = PIMCORE_TEMPORARY_DIRECTORY . "/minified_css_core_" . md5($stylesheetContent) . ".css"; if (!is_file($stylesheetPath)) { $stylesheetContent = Minify_CSS::minify($stylesheetContent); // put minified contents into one single file file_put_contents($stylesheetPath, $stylesheetContent); chmod($stylesheetPath, 0766); } return str_replace(PIMCORE_DOCUMENT_ROOT, "", $stylesheetPath); }
function minify_views($hook, $type, $content, $params) { $view = $params['view']; if (preg_match("/^js\\//", $view)) { if (include_once dirname(__FILE__) . '/vendors/min/lib/JSMin.php') { return JSMin::minify($content); } } elseif (preg_match("/^css\\//", $view)) { if (include_once dirname(__FILE__) . '/vendors/min/lib/CSS.php') { return Minify_CSS::minify($content); } } }
/** * Minifies CSS and JS files. * */ public function process() { // Get remove important comments option $removeComments = (int) Mage::getConfig()->getNode('apptrian_minify/minify_css_js/remove_comments', 'default'); foreach ($this->getPaths() as $path) { $iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path, RecursiveDirectoryIterator::FOLLOW_SYMLINKS)); foreach ($iterator as $filename => $file) { if ($file->isFile() && preg_match('/^.+\\.(css|js)$/i', $file->getFilename())) { $filePath = $file->getRealPath(); if (!is_writable($filePath)) { Mage::log('Minification failed for ' . $filePath . ' File is not writable.'); continue; } //This is available from php v5.3.6 //$ext = $file->getExtension(); // Using this for compatibility $ext = strtolower(pathinfo($filePath, PATHINFO_EXTENSION)); $optimized = ''; $unoptimized = file_get_contents($filePath); // If it is 0 byte file or cannot be read if (!$unoptimized) { Mage::log('File ' . $filePath . ' cannot be read.'); continue; } // CSS files if ($ext == 'css') { if ($removeComments == 1) { $optimized = Minify_CSS::minify($unoptimized, array('preserveComments' => false)); } else { $optimized = Minify_CSS::minify($unoptimized); } // JS files } else { if ($removeComments == 1) { $optimized = JSMinMax::minify($unoptimized); } else { $optimized = JSMin::minify($unoptimized); } } // If optimization failed if (!$optimized) { Mage::log('File ' . $filePath . ' was not minified.'); continue; } if (file_put_contents($filePath, $optimized, LOCK_EX) === false) { Mage::log('Minification failed for ' . $filePath); } } } } }
function minify_views($hook, $type, $content, $params) { switch ($params['view']) { case 'js/initialise_elgg': case 'js/friendsPickerv1': if (include_once 'lib/min/lib/JSMin.php') { return JSMin::minify($content); } break; case 'css': if (include_once 'lib/min/lib/CSS.php') { return Minify_CSS::minify($content); } break; } }
/** * Generate css cache * * @return false|null */ function ossn_trigger_css_cache() { global $Ossn; require_once ossn_route()->libs . 'minify/CSS.php'; $dir = ossn_route()->cache; if (!is_dir("{$dir}css/view/")) { mkdir("{$dir}css/view/", 0755, true); } if (!isset($Ossn->css)) { return false; } foreach ($Ossn->css as $name => $file) { $cache_file = "{$dir}css/view/{$name}.css"; $css = Minify_CSS::minify(ossn_view($file)); $css .= Minify_CSS::minify(ossn_fetch_extend_views("css/{$name}")); file_put_contents($cache_file, $css); } }
protected function _inlineResources($resources) { $res = ""; foreach ($resources as $is) { $res .= $is; } $res = trim($res); $content = ""; if (strlen($res) > 0) { if (MINCO_MINIFY_INLINE) { Loader::library("3rdparty/minify-2.1.5/min/lib/Minify/CSS", "mainio_minco"); $res = Minify_CSS::minify($res); } $content = '<style type="text/css">'; $content .= $res; $content .= '</style>'; } return $content; }
/** * @param string $filename * @param string $content * @return string */ protected function minifyFile($filename, $content) { // if we have a javascript file and jsmin is enabled, minify the content $isJS = stripos($filename, '.js'); if ($isJS && $this->combine_js_with_jsmin) { increase_time_limit_to(); $content = JSMin::minify($content); } else { if (stripos($filename, '.css')) { increase_time_limit_to(); $minifyCSSConfig = array(); if (Config::inst()->get('Minify_Requirements_Backend', 'rewrite_uris')) { $minifyCSSConfig['currentDir'] = Director::baseFolder() . '/' . dirname($filename); } $content = Minify_CSS::minify($content, $minifyCSSConfig); } } $content .= ($isJS ? ';' : '') . "\n"; return $content; }
function test_CSS() { global $thisDir; $cssPath = dirname(__FILE__) . '/_test_files/css'; // build test file list $d = dir($cssPath); while (false !== ($entry = $d->read())) { if (preg_match('/^([\\w\\-]+)\\.css$/', $entry, $m)) { $list[] = $m[1]; } } $d->close(); foreach ($list as $item) { $options = array(); if ($item === 'paths_prepend') { $options = array('prependRelativePath' => '../'); } elseif ($item === 'paths_rewrite') { $options = array('currentDir' => $thisDir . '/_test_files/css'); $tempDocRoot = $_SERVER['DOCUMENT_ROOT']; $_SERVER['DOCUMENT_ROOT'] = $thisDir; } $src = file_get_contents($cssPath . "/{$item}.css"); $minExpected = file_get_contents($cssPath . "/{$item}.min.css"); $minOutput = Minify_CSS::minify($src, $options); // reset doc root as configured if ($item === 'paths_rewrite') { $_SERVER['DOCUMENT_ROOT'] = $tempDocRoot; } $passed = assertTrue($minExpected === $minOutput, 'Minify_CSS : ' . $item); if (__FILE__ === realpath($_SERVER['SCRIPT_FILENAME'])) { echo "\n---Output: " . countBytes($minOutput) . " bytes\n\n{$minOutput}\n\n"; if (!$passed) { echo "---Expected: " . countBytes($minExpected) . " bytes\n\n{$minExpected}\n\n"; echo "---Source: " . countBytes($src) . " bytes\n\n{$src}\n\n\n"; } } } }
function _a_get_assets_body($type, $assets) { $gzip = sfConfig::get('app_a_minify_gzip', false); sfConfig::set('symfony.asset.' . $type . '_included', true); $html = ''; // We need our own copy of the trivial case here because we rewrote the asset list // for stylesheets after LESS compilation, and there is no way to // reset the list in the response object if (!sfConfig::get('app_a_minify', false)) { // This branch is seen only for CSS, because javascript calls the original Symfony // functionality when minify is off foreach ($assets as $file => $options) { $html .= stylesheet_tag($file, $options); } return $html; } $sets = array(); foreach ($assets as $file => $options) { if (preg_match('/^http(s)?:/', $file) || isset($options['data-minify']) && $options['data-minify'] === 0) { // Nonlocal URL or minify was explicitly shut off. // Don't get cute with it, otherwise things // like Addthis and ckeditor don't work if ($type === 'stylesheets') { $html .= stylesheet_tag($file, $options); } else { $html .= javascript_include_tag($file, $options); } continue; } /* * * Guts borrowed from stylesheet_tag and javascript_tag. We still do a tag if it's * a conditional stylesheet * */ $absolute = false; if (isset($options['absolute']) && $options['absolute']) { unset($options['absolute']); $absolute = true; } $condition = null; if (isset($options['condition'])) { $condition = $options['condition']; unset($options['condition']); } if (!isset($options['raw_name'])) { if ($type === 'stylesheets') { $file = stylesheet_path($file, $absolute); } else { $file = javascript_path($file, $absolute); } } else { unset($options['raw_name']); } if (is_null($options)) { $options = array(); } if ($type === 'stylesheets') { $options = array_merge(array('rel' => 'stylesheet', 'type' => 'text/css', 'media' => 'screen', 'href' => $file), $options); } else { $options = array_merge(array('type' => 'text/javascript', 'src' => $file), $options); } if (null !== $condition) { $tag = tag('link', $options); $tag = comment_as_conditional($condition, $tag); $html .= $tag . "\n"; } else { unset($options['href'], $options['src']); $optionGroupKey = json_encode($options); $set[$optionGroupKey][] = $file; } // echo($file); // $html .= "<style>\n"; // $html .= file_get_contents(sfConfig::get('sf_web_dir') . '/' . $file); // $html .= "</style>\n"; } // CSS files with the same options grouped together to be loaded together foreach ($set as $optionsJson => $files) { $groupFilename = aAssets::getGroupFilename($files); $groupFilename .= $type === 'stylesheets' ? '.css' : '.js'; if ($gzip) { $groupFilename .= 'gz'; } $dir = aFiles::getUploadFolder(array('asset-cache')); if (!file_exists($dir . '/' . $groupFilename)) { $content = ''; foreach ($files as $file) { $path = null; if (sfConfig::get('app_a_stylesheet_cache_http', false)) { $url = sfContext::getRequest()->getUriPrefix() . $file; $fileContent = file_get_contents($url); } else { $path = sfConfig::get('sf_web_dir') . $file; $fileContent = file_get_contents($path); } if ($type === 'stylesheets') { $options = array(); if (!is_null($path)) { // Rewrite relative URLs in CSS files. // This trick is available only when we don't insist on // pulling our CSS files via http rather than the filesystem // dirname would resolve symbolic links, we don't want that $fdir = preg_replace('/\\/[^\\/]*$/', '', $path); $options['currentDir'] = $fdir; $options['docRoot'] = sfConfig::get('sf_web_dir'); } if (sfConfig::get('app_a_minify', false)) { $fileContent = Minify_CSS::minify($fileContent, $options); } } else { // Trailing carriage return makes behavior more consistent with // JavaScript's behavior when loading separate files. For instance, // a missing trailing semicolon should be tolerated to the same // degree it would be with separate files. The minifier is not // a lint tool and should not surprise you with breakage $fileContent = JSMin::minify($fileContent) . "\n"; } $content .= $fileContent; } if ($gzip) { _gz_file_put_contents($dir . '/' . $groupFilename . '.tmp', $content); } else { file_put_contents($dir . '/' . $groupFilename . '.tmp', $content); } @rename($dir . '/' . $groupFilename . '.tmp', $dir . '/' . $groupFilename); } $options = json_decode($optionsJson, true); // Use stylesheet_path and javascript_path so we can respect relative_root_dir if ($type === 'stylesheets') { $options['href'] = stylesheet_path(sfConfig::get('app_a_assetCacheUrl', '/uploads/asset-cache') . '/' . $groupFilename); $html .= tag('link', $options); } else { $options['src'] = javascript_path(sfConfig::get('app_a_assetCacheUrl', '/uploads/asset-cache') . '/' . $groupFilename); $html .= content_tag('script', '', $options); } } return $html; }
/** * Prepare css or js files for aggregation and minification * * @param array $aUrlArray Array of urls of css or js files for aggregation * @param string $sType css or js * @param string $sLnEnd line end * @return string Aggregated (and possibly minified) contents of files */ public function getContents($aUrlArray, $sType, $sLnEnd, $iMinify, $iImport, $iSprite, $sId) { ksort($aUrlArray); $sContents = $this->combineFiles($aUrlArray, $sLnEnd, $sType); if ($sType == 'css') { if ($iImport) { $sContents = $this->replaceImports($sContents, $sLnEnd); } $sContents = trim($this->sortImports($sContents, $sLnEnd)); if ($iSprite) { $sContents = $this->generateSprite($sContents, $sLnEnd); } if ($iMinify) { $sContents = Minify_CSS::process($sContents); } } if ($iMinify && $sType == 'js') { try { $sContents = JSMin::minify($sContents); } catch (JSMinException $e) { //Need to test how this handles JError::raiseWarning(101, $e->getMessage()); //return false; } } $sContents = str_replace('LINE_END', $sLnEnd, $sContents); return $sContents; }
public function ServeCss($ThemeType, $Filename) { // Split the filename into filename and etag. if (preg_match('`([\\w_-]+?)-(\\w+).css$`', $Filename, $Matches)) { $Basename = $Matches[1]; $ETag = $Matches[2]; } else { throw NotFoundException(); } $Basename = ucfirst($Basename); $this->EventArguments['Basename'] = $Basename; $this->EventArguments['ETag'] = $ETag; $this->FireEvent('BeforeServeCss'); if (function_exists('header_remove')) { header_remove('Set-Cookie'); } safeHeader("Content-Type: text/css"); if (!in_array($Basename, array('Style', 'Admin'))) { safeHeader("HTTP/1.0 404", TRUE, 404); echo "/* Could not find {$Basename}/{$ETag} */"; die; } $RequestETags = GetValue('HTTP_IF_NONE_MATCH', $_SERVER); if (get_magic_quotes_gpc()) { $RequestETags = stripslashes($RequestETags); } $RequestETags = explode(',', $RequestETags); foreach ($RequestETags as $RequestETag) { if ($RequestETag == $ETag) { safeHeader("HTTP/1.0 304", TRUE, 304); die; } } safeHeader("Cache-Control:public, max-age=14400"); $CurrentETag = self::ETag(); safeHeader("ETag: {$CurrentETag}"); $CachePath = PATH_CACHE . '/css/' . CLIENT_NAME . '-' . $ThemeType . '-' . strtolower($Basename) . "-{$CurrentETag}.css"; if (!Debug() && file_exists($CachePath)) { readfile($CachePath); die; } // Include minify... set_include_path(PATH_LIBRARY . "/vendors/Minify/lib" . PATH_SEPARATOR . get_include_path()); require_once PATH_LIBRARY . "/vendors/Minify/lib/Minify/CSS.php"; ob_start(); echo "/* CSS generated for etag: {$CurrentETag}.\n *\n"; $Paths = $this->GetCssFiles($ThemeType, $Basename, $ETag, $NotFound); // First, do a pass through the files to generate some information. foreach ($Paths as $Info) { list($Path, $UrlPath) = $Info; echo " * {$UrlPath}\n"; } // Echo the paths that weren't found to help debugging. foreach ($NotFound as $Info) { list($Filename, $Folder) = $Info; echo " * {$Folder}/{$Filename} NOT FOUND.\n"; } echo " */\n\n"; // Now that we have all of the paths we want to serve them. foreach ($Paths as $Info) { list($Path, $UrlPath, $Options) = $Info; echo "/* File: {$UrlPath} */\n"; $Css = GetValue('Css', $Options); if (!$Css) { $Css = file_get_contents($Path); } $Css = Minify_CSS::minify($Css, array('preserveComments' => TRUE, 'prependRelativePath' => $this->UrlPrefix . Asset(dirname($UrlPath) . '/'), 'currentDir' => dirname($Path), 'minify' => TRUE)); echo $Css; echo "\n\n"; } // Create a cached copy of the file. $Css = ob_get_flush(); if (!file_exists(dirname($CachePath))) { mkdir(dirname($CachePath), 0775, TRUE); } file_put_contents($CachePath, $Css); }
/** * Internal function for (maybe) minifying assets * * @param Type of asset to minify (css/js) * @param Contents to be minified * @param The name of the file being minified (used for logging) * @param mixed A relative path to use, if provided (for css minification) * @return String (maybe) minified contents of file */ protected function _minify($type, $contents, $filename, $rel = FALSE) { // used in case we need to return orig $contents_orig = $contents; switch ($type) { case 'js': /** * JS pre-minify hook */ if ($this->EE->extensions->active_hook('minimee_pre_minify_js')) { Minimee_helper::log('Hook `minimee_pre_minify_js` has been activated.', 3); // pass contents to be minified, and instance of self $contents = $this->EE->extensions->call('minimee_pre_minify_js', $contents, $filename, $this); if ($this->EE->extensions->end_script === TRUE) { return $contents; } // re-set $contents_orig in case we need to return $contents_orig = $contents; } // HOOK END // be sure we want to minify if ($this->config->is_yes('minify_js')) { // See if JSMinPlus was explicitly requested if ($this->config->js_library == 'jsminplus') { Minimee_helper::log('Running minification with JSMinPlus.', 3); Minimee_helper::library('jsminplus'); $contents = JSMinPlus::minify($contents); } else { if ($this->config->js_library == 'jsmin') { Minimee_helper::log('Running minification with JSMin.', 3); Minimee_helper::library('jsmin'); $contents = JSMin::minify($contents); } } } break; case 'css': /** * CSS pre-minify hook */ if ($this->EE->extensions->active_hook('minimee_pre_minify_css')) { Minimee_helper::log('Hook `minimee_pre_minify_css` has been activated.', 3); // pass contents to be minified, relative path, and instance of self $contents = $this->EE->extensions->call('minimee_pre_minify_css', $contents, $filename, $rel, $this); if ($this->EE->extensions->end_script === TRUE) { return $contents; } // copy to $contents_orig in case we need to return $contents_orig = $contents; } // HOOK END // prepend URL if relative path exists & configured to do so if ($rel !== FALSE && $this->config->is_yes('css_prepend_mode')) { Minimee_helper::library('css_urirewriter'); $contents = Minify_CSS_UriRewriter::prepend($contents, $rel . '/'); // copy to $contents_orig in case we need to return $contents_orig = $contents; } // minify if configured to do so if ($this->config->is_yes('minify_css')) { // See if CSSMin was explicitly requested if ($this->config->css_library == 'cssmin') { Minimee_helper::log('Running minification with CSSMin.', 3); Minimee_helper::library('cssmin'); $cssmin = new CSSmin(FALSE); $contents = $cssmin->run($contents); unset($cssmin); } else { if ($this->config->css_library == 'minify') { Minimee_helper::log('Running minification with Minify_CSS.', 3); Minimee_helper::library('minify'); $contents = Minify_CSS::minify($contents); } } } break; } // calculate weight loss $before = strlen($contents_orig); $after = strlen($contents); $diff = $before - $after; // quick check that contents are not empty if ($after == 0) { Minimee_helper::log('Minification has returned an empty string for `' . $filename . '`.', 2); } // did we actually reduce our file size? It's possible an already minified asset // uses a more aggressive algorithm than Minify; in that case, keep original contents if ($diff > 0) { $diff_formatted = $diff < 100 ? $diff . 'b' : round($diff / 1000, 2) . 'kb'; $change = round($diff / $before * 100, 2); Minimee_helper::log('Minification has reduced ' . $filename . ' by ' . $diff_formatted . ' (' . $change . '%).', 3); // add to our running total $this->diff_total($diff); } else { Minimee_helper::log('Minification unable to reduce ' . $filename . ', so using original content.', 3); $contents = $contents_orig; } // cleanup (leave some smaller variables because they may or may not have ever been set) unset($contents_orig); // return our (maybe) minified contents return $contents; }
/** * Serve all CSS files. * * @param $themeType * @param $filename * @throws Exception */ public function serveCss($themeType, $filename) { // Split the filename into filename and etag. if (preg_match('`([\\w-]+?)-(\\w+).css$`', $filename, $matches)) { $basename = $matches[1]; $eTag = $matches[2]; } else { throw notFoundException(); } $basename = strtolower($basename); $this->EventArguments['Basename'] = $basename; $this->EventArguments['ETag'] = $eTag; $this->fireEvent('BeforeServeCss'); if (function_exists('header_remove')) { header_remove('Set-Cookie'); } // Get list of anchor files $anchors = $this->getAnchors(); safeHeader("Content-Type: text/css"); $anchorFileName = "{$basename}.css"; if (!in_array($anchorFileName, $anchors)) { safeHeader("HTTP/1.0 404", true, 404); echo "/* Could not find {$basename}/{$eTag} */"; die; } $requestETags = val('HTTP_IF_NONE_MATCH', $_SERVER); $requestETags = explode(',', $requestETags); foreach ($requestETags as $requestETag) { if ($requestETag == $eTag) { safeHeader("HTTP/1.0 304", true, 304); die; } } safeHeader("Cache-Control:public, max-age=14400"); $currentETag = self::eTag(); safeHeader("ETag: {$currentETag}"); $cachePath = PATH_CACHE . '/css/' . CLIENT_NAME . '-' . $themeType . '-' . "{$basename}-{$currentETag}.css"; if (!Debug() && file_exists($cachePath)) { readfile($cachePath); die; } // Include minify... set_include_path(PATH_LIBRARY . "/vendors/Minify/lib" . PATH_SEPARATOR . get_include_path()); require_once PATH_LIBRARY . "/vendors/Minify/lib/Minify/CSS.php"; ob_start(); echo "/* CSS generated for etag: {$currentETag}.\n *\n"; $notFound = []; $paths = $this->getCssFiles($themeType, $basename, $eTag, $notFound); // First, do a pass through the files to generate some information. foreach ($paths as $info) { list($path, $urlPath) = $info; echo " * {$urlPath}\n"; } // Echo the paths that weren't found to help debugging. foreach ($notFound as $info) { list($filename, $folder) = $info; echo " * {$folder}/{$filename} NOT FOUND.\n"; } echo " */\n\n"; // Now that we have all of the paths we want to serve them. foreach ($paths as $info) { list($path, $urlPath, $options) = $info; echo "/* File: {$urlPath} */\n"; $css = val('Css', $options); if (!$css) { $css = file_get_contents($path); } $css = Minify_CSS::minify($css, ['preserveComments' => true, 'prependRelativePath' => $this->UrlPrefix . asset(dirname($urlPath) . '/'), 'currentDir' => dirname($path), 'minify' => true]); echo $css; echo "\n\n"; } // Create a cached copy of the file. $css = ob_get_flush(); if (!file_exists(dirname($cachePath))) { mkdir(dirname($cachePath), 0775, true); } file_put_contents($cachePath, $css); }
static function minifyCss($code, $options = array()) { require_once 'Minify/CSS.php'; return Minify_CSS::minify($code, $options); }
function combine_css() { $master_css = ''; $css_js = file_get_contents($this->css_js_file_dev); $lines = explode("\n", $css_js); foreach ($lines as $key => $row) { preg_match('<link.+href=\\"(.+.css)\\".+\\/>', $row, $matches); if (isset($matches[1]) && !empty($matches[1])) { $master_css .= file_get_contents('../public' . $matches[1]); } } // If we have any new JS we build a new hash file for the JS. $hash = md5($master_css); if (!is_file("{$this->public_cache}/{$hash}.css")) { echo "\n###### Compressing CSS File ######\n"; $cssmin = new \Minify_CSS(); file_put_contents("{$this->public_cache}/{$hash}.css", $cssmin->minify($master_css)); // Upload to rackspace. echo "\n###### Uploading Combined JS To Rackspace ######\n"; $this->rs_upload("{$this->public_cache}/{$hash}.css", "assets/css/{$hash}.css", 'text/css'); //exec("git add $this->public_cache/$hash.css"); } // Add CSS to the prod list. $this->prod_file_lines[] = '<link type="text/css" rel="stylesheet" href="' . $this->cdn_url . "assets/css/{$hash}.css" . '" media="screen" />'; echo "\n"; }
/** * @param array $files * @return array */ protected function _processingCssFiles($files = []) { $fileName = md5(implode(array_keys($files)) . $this->getSettingsHash()) . '.css'; $publicUrl = \Yii::getAlias('@web/assets/css-compress/' . $fileName); $rootDir = \Yii::getAlias('@webroot/assets/css-compress'); $rootUrl = $rootDir . '/' . $fileName; if (file_exists($rootUrl)) { $resultFiles = []; foreach ($files as $fileCode => $fileTag) { if (Url::isRelative($fileCode)) { } else { if (!$this->cssFileRemouteCompile) { $resultFiles[$fileCode] = $fileTag; } } } $publicUrl = $publicUrl . "?v=" . filemtime($rootUrl); $resultFiles[$publicUrl] = Html::cssFile($publicUrl); return $resultFiles; } //Reading the contents of the files try { $resultContent = []; $resultFiles = []; foreach ($files as $fileCode => $fileTag) { if (Url::isRelative($fileCode)) { $contentTmp = trim($this->fileGetContents(Url::to(\Yii::getAlias($fileCode), true))); $fileCodeTmp = explode("/", $fileCode); unset($fileCodeTmp[count($fileCodeTmp) - 1]); $prependRelativePath = implode("/", $fileCodeTmp) . "/"; $contentTmp = \Minify_CSS::minify($contentTmp, ["prependRelativePath" => $prependRelativePath, 'compress' => true, 'removeCharsets' => true, 'preserveComments' => true]); //$contentTmp = \CssMin::minify($contentTmp); $resultContent[] = $contentTmp; } else { if ($this->cssFileRemouteCompile) { //Пытаемся скачать удаленный файл $resultContent[] = trim($this->fileGetContents($fileCode)); } else { $resultFiles[$fileCode] = $fileTag; } } } } catch (\Exception $e) { \Yii::error($e->getMessage(), static::className()); return $files; } if ($resultContent) { $content = implode($resultContent, "\n"); if (!is_dir($rootDir)) { if (!FileHelper::createDirectory($rootDir, 0777)) { return $files; } } if ($this->cssFileCompress) { $content = \CssMin::minify($content); } $page = \Yii::$app->request->absoluteUrl; $useFunction = function_exists('curl_init') ? 'curl extension' : 'php file_get_contents'; $filesString = implode(', ', array_keys($files)); \Yii::info("Create css file: {$publicUrl} from files: {$filesString} to use {$useFunction} on page '{$page}'", static::className()); $file = fopen($rootUrl, "w"); fwrite($file, $content); fclose($file); } if (file_exists($rootUrl)) { $publicUrl = $publicUrl . "?v=" . filemtime($rootUrl); $resultFiles[$publicUrl] = Html::cssFile($publicUrl); return $resultFiles; } else { return $files; } }
/** * Minify a CSS string * * @param string $css * * @param array $options (currently ignored) * * @return string */ public static function process($css, $options = array()) { $obj = new Minify_CSS($options); return $obj->_process($css); }
public function css($src = false) { if ($this->cache->canCache() && !$this->cache->getDeveloperMode() && $this->minify_css) { /* generate file if not exits */ $combined_css_file = '_' . $this->getHash($this->styles, 'css'); if (!file_exists($this->path . $combined_css_file)) { /* parse all styles, generate corresponding minified css file */ foreach ($this->styles as $style) { $file = $this->path . $this->getHash($style, 'css'); if (!file_exists($file)) { $css_file = realpath(DIR_SYSTEM . '../' . $this->removeQueryString($style)); if (!file_exists($css_file)) { continue; } $content = file_get_contents($css_file); $content_min = Minify_CSS::minify($content, array('preserveComments' => false, 'currentDir' => dirname($css_file))); file_put_contents($file, $content_min, LOCK_EX); } } /* combine all styles into one file */ $fh = @fopen($this->path . $combined_css_file, 'w'); flock($fh, LOCK_EX); foreach ($this->styles as $style) { $file = $this->path . $this->getHash($style, 'css'); if (!file_exists($file)) { continue; } $content = file_get_contents($file); fwrite($fh, $content); } /* append journal.css at the end */ $options = array('preserveComments' => false); if (Journal2Utils::staticAsset('') === '') { $options['currentDir'] = realpath($this->path . '../'); } else { $options['prependRelativePath'] = Journal2Utils::staticAsset(''); } if (is_file($this->path . $this->cache->getJournalAssetsFileName('css'))) { $content_min = Minify_CSS::minify(file_get_contents($this->path . $this->cache->getJournalAssetsFileName('css')), $options); } else { $content_min = ''; } fwrite($fh, $content_min); flock($fh, LOCK_UN); fclose($fh); } /* return link tag */ if ($src) { return Journal2Utils::staticAsset($this->dir . $combined_css_file); } return $this->printStyle($this->dir . $combined_css_file); } $assets = ''; foreach ($this->styles as $style) { $assets .= $this->printStyle($style); } return $assets; }
foreach ($files as $f) { $mt = is_array($f) ? filemtime($f[0]) : filemtime($f); if ($mt > $latest) { $latest = $mt; } } $name = md5($name); if (file_exists(USERBASE . '/ww.cache/c/css-' . $name) && filemtime(USERBASE . '/ww.cache/c/css-' . $name) < $latest) { unlink(USERBASE . '/ww.cache/c/css-' . $name); } $css_code = false; if ($css_code == false) { $css_code = ''; require 'Minify/CSS.php'; foreach ($files as $f) { if (is_array($f)) { $css_code .= Minify_CSS::minify(file_get_contents($f[0]), array('prependRelativePath' => preg_replace('/[^\\/]*$/', '', $f[1]))); } else { $css_code .= Minify_CSS::minify(file_get_contents($f)); } } $css_code = str_replace('}', "}\n", str_replace("\n", ' ', $css_code)); Core_cacheSave('c', 'css-' . $name, $css_code); } header('Content-type: text/css; charset=utf-8'); header('Cache-Control: max-age = 2592000'); header('Expires-Active: On'); header('Expires: Fri, 1 Jan 2500 01:01:01 GMT'); header('Pragma:'); header('Content-Length: ' . strlen($css_code)); echo $css_code;
/** * Process a comment and return a replacement * * @param array $m regex matches * * @return string */ protected static function _commentCB($m) { $m = $m[1]; // $m is the comment content w/o the surrounding tokens, // but the return value will replace the entire comment. if ($m === 'keep') { return '/**/'; } if ($m === '" "') { // component of http://tantek.com/CSS/Examples/midpass.html return '/*" "*/'; } if (preg_match('@";\\}\\s*\\}/\\*\\s+@', $m)) { // component of http://tantek.com/CSS/Examples/midpass.html return '/*";}}/* */'; } if (self::$_inHack) { // inversion: feeding only to one browser if (preg_match('@ ^/ # comment started like /*/ \\s* (\\S[\\s\\S]+?) # has at least some non-ws content \\s* /\\* # ends like /*/ or /**/ @x', $m, $n)) { // end hack mode after this comment, but preserve the hack and comment content self::$_inHack = false; return "/*/{$n[1]}/**/"; } } if (substr($m, -1) === '\\') { // comment ends like \*/ // begin hack mode and preserve hack self::$_inHack = true; return '/*\\*/'; } if ($m !== '' && $m[0] === '/') { // comment looks like /*/ foo */ // begin hack mode and preserve hack self::$_inHack = true; return '/*/*/'; } if (self::$_inHack) { // a regular comment ends hack mode but should be preserved self::$_inHack = false; return '/**/'; } return ''; // remove all other comments }
public function parse_cssfile($stylepath = false, $data = false) { $style = $data ? $data : $this->user->style; $stylepath = $stylepath ? $stylepath : $this->style_code; $root_path = '../../../../../'; $storage_folder = $this->pfh->FolderPath('templates/' . $stylepath, 'eqdkp'); if (file_exists($storage_folder . $stylepath . '.css')) { $file = $storage_folder . $stylepath . '.css'; } elseif (file_exists($this->root_path . 'templates/' . $stylepath . '/' . $stylepath . '.css')) { $file = $this->root_path . 'templates/' . $stylepath . '/' . $stylepath . '.css'; } if (file_exists($this->root_path . 'games/' . $this->config->get('default_game') . '/template_background.jpg')) { $template_background_file = $root_path . 'games/' . $this->config->get('default_game') . '/template_background.jpg'; } else { $template_background_file = $root_path . 'templates/' . $this->user->style['template_path'] . '/images/template_background.jpg'; } if ($this->user->style['background_img'] != '') { if (strpos($this->user->style['background_img'], '://') > 1) { $template_background_file = $this->user->style['background_img']; } else { $template_background_file = $root_path . $this->user->style['background_img']; } } $in = array("/T_FONTFACE1/", "/T_FONTFACE2/", "/T_FONTFACE3/", "/T_FONTSIZE1/", "/T_FONTSIZE2/", "/T_FONTSIZE3/", "/T_FONTCOLOR1/", "/T_FONTCOLOR2/", "/T_FONTCOLOR3/", "/T_FONTCOLOR_NEG/", "/T_FONTCOLOR_POS/", "/T_BODY_BACKGROUND/", "/T_TABLE_BORDER_WIDTH/", "/T_TABLE_BORDER_COLOR/", "/T_TABLE_BORDER_STYLE/", "/T_BODY_LINK_STYLE/", "/T_BODY_LINK/", "/T_BODY_HLINK_STYLE/", "/T_BODY_HLINK/", "/T_HEADER_LINK_STYLE/", "/T_HEADER_LINK/", "/T_HEADER_HLINK_STYLE/", "/T_HEADER_HLINK/", "/T_TH_COLOR1/", "/T_TR_COLOR1/", "/T_TR_COLOR2/", "/T_INPUT_BACKGROUND/", "/T_INPUT_BORDER_WIDTH/", "/T_INPUT_BORDER_COLOR/", "/T_INPUT_BORDER_STYLE/", "/T_PORTAL_WIDTH_WITHOUT_BOTH_COLUMNS/", "/T_PORTAL_WIDTH_WITHOUT_LEFT_COLUMN/", "/T_PORTAL_WIDTH/", "/T_COLUMN_LEFT_WIDTH/", "/T_COLUMN_RIGHT_WIDTH/", "/\\.\\.\\/\\.\\.\\//", "/\\.\\.\\//", "/\\(images/", "/\\('images/", "/\\(\"images/", "/EQDKP_ROOT_PATH/", "/EQDKP_IMAGE_PATH/", "/TEMPLATE_IMAGE_PATH/", "/TEMPLATE_BACKGROUND/"); $out = array($style['fontface1'], $style['fontface2'], $style['fontface3'], $style['fontsize1'], $style['fontsize2'], $style['fontsize3'], $style['fontcolor1'], $style['fontcolor2'], $style['fontcolor3'], $style['fontcolor_neg'], $style['fontcolor_pos'], $style['body_background'], $style['table_border_width'], $style['table_border_color'], $style['table_border_style'], $style['body_link_style'], $style['body_link'], $style['body_hlink_style'], $style['body_hlink'], $style['header_link_style'], $style['header_link'], $style['header_hlink_style'], $style['header_hlink'], $style['th_color1'], $style['tr_color1'], $style['tr_color2'], $style['input_color'], $style['input_border_width'], $style['input_border_color'], $style['input_border_style'], intval($style['portal_width']) - intval($style['column_left_width']) - intval($style['column_right_width']) . (strpos($style['portal_width'], '%') !== false ? '%' : 'px'), intval($style['portal_width']) - intval($style['column_left_width']) . (strpos($style['portal_width'], '%') !== false ? '%' : 'px'), $style['portal_width'], $style['column_left_width'], $style['column_right_width'], $root_path, $root_path, '(' . $root_path . 'templates/' . $stylepath . '/images', '(\'' . $root_path . 'templates/' . $stylepath . '/images', '("' . $root_path . 'templates/' . $stylepath . '/images', $root_path, $root_path . 'images/', $root_path . 'templates/' . $stylepath . '/images', $template_background_file); if (strlen($file)) { //The global css file $content = file_get_contents($this->root_path . 'templates/eqdkpplus.css'); $data = preg_replace($in, $out, $content); $content = file_get_contents($file); //Replace everything $data .= preg_replace($in, $out, $content); //Now the class colors $gameclasses = $this->game->get('classes'); if (isset($gameclasses) && is_array($gameclasses)) { foreach ($gameclasses as $class_id => $class_name) { $data .= ' .class_' . $class_id . ', .class_' . $class_id . ':link, .class_' . $class_id . ':visited, .class_' . $class_id . ':active, .class_' . $class_id . ':link:hover, td.class_' . $class_id . ' a:hover, td.class_' . $class_id . ' a:active, td.class_' . $class_id . ', td.class_' . $class_id . ' a:link, td.class_' . $class_id . ' a:visited{ text-decoration: none; color: ' . $this->game->get_class_color($class_id) . ' !important; } '; } } //User additions $strUserFile = $this->root_path . 'templates/' . $stylepath . '/user_additions.css'; if (file_exists($strUserFile)) { $content = file_get_contents($strUserFile); $data .= preg_replace($in, $out, $content); } $minify = new Minify_CSS(); $data = $minify->minify($data); $this->pfh->putContent($storage_folder . 'main.css', $data); $this->timekeeper->put('tpl_cache_' . $stylepath, 'main.css'); } }
/** * Special function to transform css output and wrap in js call */ private function transformCssOutput($resourceName, $cssString, $path = '') { global $wgScriptLoaderRelativeCss; // Minify and update paths on cssString: $cssOptions = array(); // Set comments preservation based on debug state $cssOptions['preserveComments'] = $this->debug; // Check for the two ResourceLoader entry points: if ($wgScriptLoaderRelativeCss) { // Using the local mediaWiki entry point we should have our $wgScriptPath global global $wgScriptPath; $prePendPath = $wgScriptPath == '' ? '' : $wgScriptPath . '/'; $cssOptions['prependRelativePath'] = $prePendPath . dirname($path) . '/'; } else { // Get the server URL $serverUri = $this->getResourceLoaderUri(); $cssOptions['prependRelativePath'] = str_replace('ResourceLoader.php', '', $serverUri) . dirname($path) . '/'; } // We always run minify to update css image urls $cssString = Minify_CSS::minify($cssString, $cssOptions); // Check output format ( if format is "css" ) return the css string directly if ($this->outputFormat == 'css') { return $cssString; } // Output Format is "javascript" return the string in an addStyleString call // CSS classes should be of form mw.style.{className} $cssStyleName = str_replace('mw.style.', '', $resourceName); return 'mw.addStyleString("' . Xml::escapeJsString($cssStyleName) . '", "' . Xml::escapeJsString($cssString) . '");' . "\n"; }
public function minify_css($file) { global $tikipath, $tikiroot; if (strpos($file, $tikiroot) === 0) { $file = substr($file, strlen($tikiroot)); } $currentdir = str_replace($tikipath, $tikiroot, str_replace('\\', '/', dirname(realpath($file)))); if ($file[0] == '/') { $file = $tikipath . $file; } $content = file_get_contents($file); return Minify_CSS::minify($content, array('prependRelativePath' => $currentdir . '/', 'bubbleCssImports' => true)); }
public function compressCSS() { if ($this->_context->_optimize == 1 || $this->_context->_optimize == 3 || $this->_context->_optimize == 4) { // don't create if files have exists if (!JFile::exists($this->_cacheCSSFile)) { Avatar::import('core.libraries.minify.css'); $options = array('prependRelativePath' => '../'); $path = dirname(JPATH_ROOT); $output = ''; foreach ($this->_styleSheets as $style) { $options = array('currentDir' => $path . dirname($style)); $source = @file_get_contents($path . $style); $output .= Minify_CSS::minify($source, $options); } file_put_contents($this->_cacheCSSFile, $output); } $this->_jtemplate->setHeadData(array('styleSheets' => array($this->_cacheCSSFileURI => array('mime' => 'text/css', 'defer' => false, 'async' => false, 'media' => false, 'attribs' => false)))); } }