/** * Optimize website by aggregating css and js * */ public function process($sHtml) { JCH_DEBUG ? JchPlatformProfiler::mark('beforeProcess plgSystem (JCH Optimize)') : null; loadJchOptimizeClass(array('JchOptimizeBase', 'JchOptimizeParser', 'JchOptimizeFileRetriever', 'JchOptimizeLinkBuilder', 'JchOptimizeHelper')); JCH_DEBUG ? JchPlatformProfiler::mark('afterLoadClass plgSystem (JCH Optimize)') : null; try { $oParser = new JchOptimizeParser($this->params, $sHtml, JchOptimizeFileRetriever::getInstance()); $oLinkBuilder = new JchOptimizeLinkBuilder($oParser); $oLinkBuilder->insertJchLinks(); $sOptimizedHtml = JchOptimizeHelper::minifyHtml($oParser->getHtml(), $this->params); } catch (Exception $ex) { JchOptimizeLogger::log($ex->getMessage(), $this->params); $sOptimizedHtml = $sHtml; } spl_autoload_unregister('loadJchOptimizeClass'); JCH_DEBUG ? JchPlatformProfiler::mark('afterProcess plgSystem (JCH Optimize)') : null; return $sOptimizedHtml; }
/** * Minify the markeup given in the constructor * * @return string */ public function process() { JCH_DEBUG ? \JchPlatformProfiler::mark('beforeProcess plgSystem (JCH Optimize)') : null; if ($this->_isXhtml === null) { $this->_isXhtml = preg_match('#^\\s*+<!DOCTYPE[^X]++XHTML#i', $this->_html); } if ($this->_isHtml5 === null) { $this->_isHtml5 = preg_match('#^\\s*+<!DOCTYPE html>#i', $this->_html); } // JCH_DEBUG ? \JchPlatformProfiler::mark('afterTestHtml plgSystem (JCH Optimize)') : null; //Replace comments (not containing IE conditional comments) $this->_html = preg_replace('#(?>(?:<(?!!))?[^<]*+(?:<(?:script|style)\\b[^>]*+>(?><?[^<]*+)*?<\\/(?:script|style)>|<!--\\[(?>\\]?[^\\]]*+)*?\\]--!?>|' . '<!DOCTYPE[^>]++>)?)*?\\K(?:<!--(?>-?[^-\\[]*+)*?--!?>|[^<]*+\\K$)#i', '', $this->_html); // JCH_DEBUG ? \JchPlatformProfiler::mark('afterReplaceComments plgSystem (JCH Optimize)') : null; //Reduce whitespace outside all elements to one space $this->_html = preg_replace('#(?>>?[^>]*+>(?>[^>]*+\\S[^>]*+>)*?)*?\\K(?:(?<=>)\\s++(?=<)|[^<]*+$\\K)#', ' ', $this->_html); // JCH_DEBUG ? \JchPlatformProfiler::mark('afterReduceWs plgSystem (JCH Optimize)') : null; //block/undisplayed elements $b = 'address|article|aside|audio|body|blockquote|canvas|dd|div|dl' . '|fieldset|figcaption|figure|footer|form|h[1-6]|head|header|hgroup|html|noscript|ol|output|p' . '|pre|section|style|table|title|tfoot|ul|video'; //self closing block/undisplayed elements $b2 = 'base|meta|link|hr'; //inline elements $i = 'b|big|i|small|tt' . '|abbr|acronym|cite|code|dfn|em|kbd|strong|samp|var' . '|a|bdo|br|map|object|q|script|span|sub|sup' . '|button|label|select|textarea'; //self closing inline elements $i2 = 'img|input'; // remove ws around block elements preserving space around inline elements $this->_html = preg_replace("#(?>\\s*+(?:<(?:(?>{$i})\\b[^>]*+>|(?:/(?>{$i})\\b>|(?>{$i2})\\b[^>]*+>)\\s*+)|<[^>]*+>)|[^<]++)*?\\K" . "(?:\\s++(?=<(?>{$b}|{$b2})\\b)|(?:</(?>{$b})\\b>|<(?>{$b2})\\b[^>]*+>)\\K\\s++(?!<(?>{$i}|{$i2})\\b)|\$)#i", '', $this->_html); // JCH_DEBUG ? \JchPlatformProfiler::mark('afterRemoveWsAroundBlocks plgSystem (JCH Optimize)') : null; //Minify scripts $this->_html = preg_replace_callback('#(?><?[^<]*+)*?\\K(?:(<(script|style)\\b[^>]*+>)((?>(?:<(?!/\\g{2}))?[^<]++)+?)(<\\/\\g{2}>)|$)#i', array($this, '_minifyCB'), $this->_html); // JCH_DEBUG ? \JchPlatformProfiler::mark('afterMinifyScripts plgSystem (JCH Optimize)') : null; //elements to escape $e = 'pre|script|style|textarea'; //Regex for escape elements $p = "<pre\\b[^>]*+>(?><?[^<]*+)*?</pre>"; $sc = "<script\\b[^>]*+>(?><?[^<]*+)*?</script>"; $st = "<style\\b[^>]*+>(?><?[^<]*+)*?</style>"; $t = "<textarea\\b[^>]*+>(?><?[^<]*+)*?</textarea>"; //Replace runs of whitespace inside elements with single space escaping pre, textarea, scripts and style elements $this->_html = preg_replace("#(?>[^<]*+(?:{$p}|{$sc}|{$st}|{$t}|<[^>]++>[^<]*+))*?(?:(?:<(?!{$e})[^>]*+>)?(?>\\s?[^\\s<]*+)*?\\K\\s{2,}|\\K\$)#i", ' ', $this->_html); // JCH_DEBUG ? \JchPlatformProfiler::mark('afterReplaceRunsOfWs plgSystem (JCH Optimize)') : null; //Remove additional ws around attributes $this->_html = preg_replace('#(?><?[^<]*+)*?(?:<[a-z0-9]++\\K\\s++|\\G[^\\>=]++=(?(?=\\s*+["\'])\\s*+["\'][^"\']*+["\']|[^\\s]++)\\K\\s++|$\\K)#i', ' ', $this->_html); // JCH_DEBUG ? \JchPlatformProfiler::mark('afterRemoveWsAroundAttributes plgSystem (JCH Optimize)') : null; if ($this->_isHtml5) { $ns1 = '"[^"\'`=<>\\s]*+(?:[\'`=<>\\s]|(?<=\\\\)")(?>(?:(?<=\\\\)")?[^"]*+)*?(?<!\\\\)"'; $ns2 = "'[^'\"`=<>\\s]*+(?:[\"`=<>\\s]|(?<=\\\\)')(?>(?:(?<=\\\\)')?[^']*+)*?(?<!\\\\)'"; //Remove quotes from selected attributes $this->_html = preg_replace("#(?:(?=[^>]*+>)|<[a-z0-9]++ )" . "(?>[=]?[^=>]*+(?:=(?:{$ns1}|{$ns2})|>(?><?[^<]*+)*?(?:<[a-z0-9]++ |\$))?)*?" . "(?:=\\K([\"'])([^\"'`=<>\\s]++)\\g{1}[ ]?|\\K\$)#i", '$2 ', $this->_html); } // JCH_DEBUG ? \JchPlatformProfiler::mark('afterRemoveQuotes plgSystem (JCH Optimize)') : null; //remove redundant attributes $this->_html = preg_replace('#(?><?[^<]*+)*?<(?:(?:script|style|link)|/html>)(?>[ ]?[^ >]*+)*?\\K(?: type=["\']?text/(?:javascript|css)|[^<]*+\\K$)#i', '', $this->_html); // JCH_DEBUG ? \JchPlatformProfiler::mark('afterRemoveAttributes plgSystem (JCH Optimize)') : null; //Remove last whitespace in open tag $this->_html = preg_replace('#(?><?[^<]*+)*?(?:<[a-z0-9]++(?>\\s*+[^\\s>]++)*?\\K(?:\\s++(?=>)|(?<=["\'])\\s++(?=/>))|$\\K)#i', '', $this->_html); // JCH_DEBUG ? \JchPlatformProfiler::mark('afterRemoveLastWs plgSystem (JCH Optimize)') : null; return trim($this->_html); }
/** * * @param type $sHtml */ public static function attachProfiler(&$sHtml) { if (!is_super_admin()) { return; } $items = JchPlatformProfiler::mark(TRUE); $node = self::getAdminBarNodeBegin() . $items . self::getAdminBarNodeEnd(); $script = '<script type="application/javascript">' . 'var ul = document.getElementById("wp-admin-bar-root-default");' . 'ul.insertAdjacentHTML(\'beforeend\', \'' . $node . '\');' . '</script>'; $sHtml = str_replace('</body>', $script . '</body>', $sHtml); }
/** * Grabs background images with no-repeat attribute from css and merge them in one file called a sprite. * Css is updated with sprite url and correct background positions for affected images. * Sprite saved in {Joomla! base}/images/jch-optimize/ * * @param string $sCss Aggregated css file before sprite generation * @return string Css updated with sprite information on success. Original css on failure */ public function getSprite($sCss) { JCH_DEBUG ? JchPlatformProfiler::mark('beforeGetSprite plgSystem (JCH Optimize)') : null; $sImageLibrary = $this->getImageLibrary(); $aMatches = $this->processCssUrls($sCss); if (empty($aMatches) || $sImageLibrary === FALSE) { return $sCss; } $this->params->set('sprite-path', JchPlatformPaths::spriteDir()); $aSearch = $this->generateSprite($aMatches, new CssSpriteGen($sImageLibrary, $this->params)); JCH_DEBUG ? JchPlatformProfiler::mark('afterGetSprite plgSystem (JCH Optimize)') : null; return $aSearch; }
public function getOriginalHtml() { JCH_DEBUG ? JchPlatformProfiler::mark('beforeGetHtml') : null; $url = home_url() . '/?jchbackend=1'; try { $oFileRetriever = JchOptimizeFileRetriever::getInstance(); $response = $oFileRetriever->getFileContents($url); if ($oFileRetriever->response_code != 200) { throw new Exception(JchPlatformUtility::translate('Failed fetching front end HTML with response code ' . $oFileRetriever->response_code)); } JCH_DEBUG ? JchPlatformProfiler::mark('afterGetHtml') : null; return $response; } catch (Exception $e) { JchOptimizeLogger::log($url . ': ' . $e->getMessage(), $this->params); JCH_DEBUG ? JchPlatformProfiler::mark('afterGetHtml)') : null; throw new RunTimeException(_('Load or refresh the front-end site first then refresh this page ' . 'to populate the multi select exclude lists.')); } }
/** * * @param type $oObj * @param type $sCss * @return type */ public function generateAdminLinks($oObj, $sCss) { JCH_DEBUG ? JchPlatformProfiler::mark('beforeGenerateAdminLinks plgSystem (JCH Optimize)') : null; $params = clone $this->params; $params->set('javascript', '1'); $params->set('css', '1'); $params->set('excludeAllExtensions', '0'); $params->set('css_minify', '0'); $params->set('debug', '0'); $params->set('bottom_js', '2'); $sHtml = $oObj->getOriginalHtml(); $oParser = new JchOptimizeParser($params, $sHtml, JchOptimizeFileRetriever::getInstance()); $aLinks = $oParser->getReplacedFiles(); if ($sCss == '') { $oCombiner = new JchOptimizeCombiner($params, $this->bBackend); $oCssParser = new JchOptimizeCssParser($params, $this->bBackend); $oCombiner->combineFiles($aLinks['css'][0], 'css', $oCssParser); $sCss = $oCombiner->css; } $oSpriteGenerator = new JchOptimizeSpriteGenerator($params); $aLinks['images'] = $oSpriteGenerator->processCssUrls($sCss, TRUE); JCH_DEBUG ? JchPlatformProfiler::mark('afterGenerateAdminLinks plgSystem (JCH Optimize)') : null; return $aLinks; }
/** * If parameter is set will minify HTML before sending to browser; * Inline CSS and JS will also be minified if respective parameters are set * * @return string Optimized HTML * @throws Exception */ public static function minifyHtml($sHtml, $oParams) { JCH_DEBUG ? JchPlatformProfiler::mark('beforeMinifyHtml plgSystem (JCH Optimize)') : null; $aOptions = array(); if ($oParams->get('css_minify', 0)) { $aOptions['cssMinifier'] = array('JchOptimize\\CSS_Optimize', 'process'); } if ($oParams->get('js_minify', 0)) { $aOptions['jsMinifier'] = array('JchOptimize\\JS_Optimize', 'minify'); } $aOptions['minify_level'] = $oParams->get('html_minify_level', 2); if ($oParams->get('html_minify', 0)) { $sHtmlMin = HTML_Optimize::minify($sHtml, $aOptions); if ($sHtmlMin == '') { JchOptimizeLogger::log(JchPlatformUtility::translate('Error while minifying HTML'), $oParams); $sHtmlMin = $sHtml; } $sHtml = $sHtmlMin; } JCH_DEBUG ? JchPlatformProfiler::mark('afterMinifyHtml plgSystem (JCH Optimize)') : null; return $sHtml; }
/** * * @param type $sContent * @param type $sUrl */ protected function minifyContent($sContent, $sType, $aUrl) { if ($this->params->get($sType . '_minify', 0) && preg_match('#\\s++#', trim($sContent))) { $sUrl = isset($aUrl['url']) ? $aUrl['url'] : ($sType == 'css' ? 'Style' : 'Script') . ' Declaration'; JCH_DEBUG ? JchPlatformProfiler::mark('beforeMinifyContent - "' . $sUrl . '" plgSystem (JCH Optimize)') : null; $sMinifiedContent = trim($sType == 'css' ? CSS_Optimize::process($sContent) : JS_Optimize::minify($sContent)); if (is_null($sMinifiedContent) || $sMinifiedContent == '') { JchOptimizeLogger::log(sprintf(JchPlatformUtility::translate('Error occurred trying to minify: %s'), $aUrl['url']), $this->params); $sMinifiedContent = $sContent; } JCH_DEBUG ? JchPlatformProfiler::mark('afterMinifyContent - "' . $sUrl . '" plgSystem (JCH Optimize)') : null; return $sMinifiedContent; } return $sContent; }
/** * Create and cache aggregated file if it doesn't exists, file will have * lifetime set in global configurations. * * @param array $aFunction Name of function used to aggregate files * @param array $aArgs Arguments used by function above * @param string $sId Generated id to identify cached file * @return boolean True on success */ public function loadCache($aFunction, $aArgs, $sId) { JCH_DEBUG ? JchPlatformProfiler::mark('beforeLoadCache plgSystem (JCH Optimize)') : null; $iLifeTime = (int) $this->params->get('lifetime', '30') * 24 * 60 * 60; $bCached = JchPlatformCache::getCallbackCache($sId, $iLifeTime, $aFunction, $aArgs); JCH_DEBUG ? JchPlatformProfiler::mark('afterLoadCache plgSystem (JCH Optimize)') : null; return $bCached; }
/** * * @param type $sRegex * @param type $sType * @param type $sSection * @param type $aCBArgs * @throws Exception */ protected function searchArea($sRegex, $sSection, $aCBArgs) { JCH_DEBUG ? JchPlatformProfiler::mark('beforeSearchArea - ' . $sSection . ' plgSystem (JCH Optimize)') : null; $obj = $this; $sProcessedHtml = preg_replace_callback($sRegex, function ($aMatches) use($obj, $aCBArgs) { return $obj->replaceScripts($aMatches, $aCBArgs); }, $this->{'s' . ucfirst($sSection) . 'Html'}); if (is_null($sProcessedHtml)) { throw new Exception(sprintf(JchPlatformUtility::translate('Error while parsing for links in %1$s'), $sSection)); } $this->{'s' . ucfirst($sSection) . 'Html'} = $sProcessedHtml; JCH_DEBUG ? JchPlatformProfiler::mark('afterSearchArea - ' . $sSection . ' plgSystem (JCH Optimize)') : null; }