/** * Compress HTML * * This is a heavy regex-based removal of whitespace, unnecessary comments and * tokens. IE conditional comments are preserved. There are also options to have * STYLE and SCRIPT blocks compressed by callback functions. * * A test suite is available. * * @package Minify * @author Stephen Clay */ namespace LiteSpeed\Lib; defined( 'WPINC' ) || exit; class HTML_MIN { /** * @var string */ protected $_html = ''; /** * @var boolean */ protected $_jsCleanComments = true; protected $_skipComments = array(); /** * "Minify" an HTML page * * @param string $html * * @param array $options * * 'cssMinifier' : (optional) callback function to process content of STYLE * elements. * * 'jsMinifier' : (optional) callback function to process content of SCRIPT * elements. Note: the type attribute is ignored. * * 'xhtml' : (optional boolean) should content be treated as XHTML1.0? If * unset, minify will sniff for an XHTML doctype. * * @return string */ public static function minify( $html, $options = array() ) { $min = new self( $html, $options ); return $min->process(); } /** * Create a minifier object * * @param string $html * * @param array $options * * 'cssMinifier' : (optional) callback function to process content of STYLE * elements. * * 'jsMinifier' : (optional) callback function to process content of SCRIPT * elements. Note: the type attribute is ignored. * * 'jsCleanComments' : (optional) whether to remove HTML comments beginning and end of script block * * 'xhtml' : (optional boolean) should content be treated as XHTML1.0? If * unset, minify will sniff for an XHTML doctype. */ public function __construct( $html, $options = array() ) { $this->_html = str_replace( "\r\n", "\n", trim( $html ) ); if ( isset( $options['xhtml'] ) ) { $this->_isXhtml = (bool) $options['xhtml']; } if ( isset( $options['cssMinifier'] ) ) { $this->_cssMinifier = $options['cssMinifier']; } if ( isset( $options['jsMinifier'] ) ) { $this->_jsMinifier = $options['jsMinifier']; } if ( isset( $options['jsCleanComments'] ) ) { $this->_jsCleanComments = (bool) $options['jsCleanComments']; } if ( isset( $options['skipComments'] ) ) { $this->_skipComments = $options['skipComments']; } } /** * Minify the markeup given in the constructor * * @return string */ public function process() { if ( $this->_isXhtml === null ) { $this->_isXhtml = ( false !== strpos( $this->_html, '_replacementHash = 'MINIFYHTML' . md5( $_SERVER['REQUEST_TIME'] ); $this->_placeholders = array(); // replace SCRIPTs (and minify) with placeholders $this->_html = preg_replace_callback( '/(\\s*)]*?>)([\\s\\S]*?)<\\/script>(\\s*)/i', array( $this, '_removeScriptCB' ), $this->_html ); // replace STYLEs (and minify) with placeholders $this->_html = preg_replace_callback( '/\\s*]*>)([\\s\\S]*?)<\\/style>\\s*/i', array( $this, '_removeStyleCB' ), $this->_html ); // remove HTML comments (not containing IE conditional comments). $this->_html = preg_replace_callback( '//', array( $this, '_commentCB' ), $this->_html ); // replace PREs with placeholders $this->_html = preg_replace_callback( '/\\s*]*?>[\\s\\S]*?<\\/pre>)\\s*/i', array( $this, '_removePreCB' ), $this->_html ); // replace TEXTAREAs with placeholders $this->_html = preg_replace_callback( '/\\s*]*?>[\\s\\S]*?<\\/textarea>)\\s*/i', array( $this, '_removeTextareaCB' ), $this->_html ); // trim each line. // @todo take into account attribute values that span multiple lines. $this->_html = preg_replace( '/^\\s+|\\s+$/m', '', $this->_html ); // remove ws around block/undisplayed elements $this->_html = preg_replace( '/\\s+(<\\/?(?:area|article|aside|base(?:font)?|blockquote|body' . '|canvas|caption|center|col(?:group)?|dd|dir|div|dl|dt|fieldset|figcaption|figure|footer|form' . '|frame(?:set)?|h[1-6]|head|header|hgroup|hr|html|legend|li|link|main|map|menu|meta|nav' . '|ol|opt(?:group|ion)|output|p|param|section|t(?:able|body|head|d|h||r|foot|itle)' . '|ul|video)\\b[^>]*>)/i', '$1', $this->_html ); // remove ws outside of all elements $this->_html = preg_replace( '/>(\\s(?:\\s*))?([^<]+)(\\s(?:\s*))?$1$2$3<', $this->_html ); // use newlines before 1st attribute in open tags (to limit line lengths) // $this->_html = preg_replace('/(<[a-z\\-]+)\\s+([^>]+>)/i', "$1\n$2", $this->_html); // fill placeholders $this->_html = str_replace( array_keys( $this->_placeholders ), array_values( $this->_placeholders ), $this->_html ); // issue 229: multi-pass to catch scripts that didn't get replaced in textareas $this->_html = str_replace( array_keys( $this->_placeholders ), array_values( $this->_placeholders ), $this->_html ); return $this->_html; } /** * From LSCWP 6.2: Changed the function to test for special comments that will be skipped. See: https://github.com/litespeedtech/lscache_wp/pull/622 */ protected function _commentCB( $m ) { // If is IE conditional comment return it. if ( 0 === strpos( $m[1], '[' ) || false !== strpos( $m[1], ' HTML Settings -> HTML Keep comments if ( count( $this->_skipComments ) > 0 ) { foreach ( $this->_skipComments as $comment ) { if ( $comment && strpos( $m[1], $comment ) !== false ) { return $m[0]; } } } // Comment can be removed. return ''; } protected function _reservePlace( $content ) { $placeholder = '%' . $this->_replacementHash . count( $this->_placeholders ) . '%'; $this->_placeholders[ $placeholder ] = $content; return $placeholder; } protected $_isXhtml = null; protected $_replacementHash = null; protected $_placeholders = array(); protected $_cssMinifier = null; protected $_jsMinifier = null; protected function _removePreCB( $m ) { return $this->_reservePlace( "_reservePlace( "\\s*$)/', '', $css ); // remove CDATA section markers $css = $this->_removeCdata( $css ); // minify $minifier = $this->_cssMinifier ? $this->_cssMinifier : 'trim'; $css = call_user_func( $minifier, $css ); return $this->_reservePlace( $this->_needsCdata( $css ) ? "{$openStyle}/**/" : "{$openStyle}{$css}" ); } protected function _removeScriptCB( $m ) { $openScript = "_jsCleanComments ) { $js = preg_replace( '/(?:^\\s*\\s*$)/', '', $js ); } // remove CDATA section markers $js = $this->_removeCdata( $js ); // minify /** * Added 2nd param by LiteSpeed * * @since 2.2.3 */ if ( $this->_jsMinifier ) { $js = call_user_func( $this->_jsMinifier, $js, trim( $m[2] ) ); } else { $js = trim( $js ); } return $this->_reservePlace( $this->_needsCdata( $js ) ? "{$ws1}{$openScript}/**/{$ws2}" : "{$ws1}{$openScript}{$js}{$ws2}" ); } protected function _removeCdata( $str ) { return ( false !== strpos( $str, '' ), '', $str ) : $str; } protected function _needsCdata( $str ) { return ( $this->_isXhtml && preg_match( '/(?:[<&]|\\-\\-|\\]\\]>)/', $str ) ); } } declare (strict_types=1); namespace ElementorDeps\DI; use ElementorDeps\DI\Definition\ArrayDefinitionExtension; use ElementorDeps\DI\Definition\EnvironmentVariableDefinition; use ElementorDeps\DI\Definition\Helper\AutowireDefinitionHelper; use ElementorDeps\DI\Definition\Helper\CreateDefinitionHelper; use ElementorDeps\DI\Definition\Helper\FactoryDefinitionHelper; use ElementorDeps\DI\Definition\Reference; use ElementorDeps\DI\Definition\StringDefinition; use ElementorDeps\DI\Definition\ValueDefinition; if (!\function_exists('ElementorDeps\\DI\\value')) { /** * Helper for defining a value. * * @param mixed $value */ function value($value) : ValueDefinition { return new ValueDefinition($value); } } if (!\function_exists('ElementorDeps\\DI\\create')) { /** * Helper for defining an object. * * @param string|null $className Class name of the object. * If null, the name of the entry (in the container) will be used as class name. */ function create(string $className = null) : CreateDefinitionHelper { return new CreateDefinitionHelper($className); } } if (!\function_exists('ElementorDeps\\DI\\autowire')) { /** * Helper for autowiring an object. * * @param string|null $className Class name of the object. * If null, the name of the entry (in the container) will be used as class name. */ function autowire(string $className = null) : AutowireDefinitionHelper { return new AutowireDefinitionHelper($className); } } if (!\function_exists('ElementorDeps\\DI\\factory')) { /** * Helper for defining a container entry using a factory function/callable. * * @param callable $factory The factory is a callable that takes the container as parameter * and returns the value to register in the container. */ function factory($factory) : FactoryDefinitionHelper { return new FactoryDefinitionHelper($factory); } } if (!\function_exists('ElementorDeps\\DI\\decorate')) { /** * Decorate the previous definition using a callable. * * Example: * * 'foo' => decorate(function ($foo, $container) { * return new CachedFoo($foo, $container->get('cache')); * }) * * @param callable $callable The callable takes the decorated object as first parameter and * the container as second. */ function decorate($callable) : FactoryDefinitionHelper { return new FactoryDefinitionHelper($callable, \true); } } if (!\function_exists('ElementorDeps\\DI\\get')) { /** * Helper for referencing another container entry in an object definition. */ function get(string $entryName) : Reference { return new Reference($entryName); } } if (!\function_exists('ElementorDeps\\DI\\env')) { /** * Helper for referencing environment variables. * * @param string $variableName The name of the environment variable. * @param mixed $defaultValue The default value to be used if the environment variable is not defined. */ function env(string $variableName, $defaultValue = null) : EnvironmentVariableDefinition { // Only mark as optional if the default value was *explicitly* provided. $isOptional = 2 === \func_num_args(); return new EnvironmentVariableDefinition($variableName, $isOptional, $defaultValue); } } if (!\function_exists('ElementorDeps\\DI\\add')) { /** * Helper for extending another definition. * * Example: * * 'log.backends' => DI\add(DI\get('My\Custom\LogBackend')) * * or: * * 'log.backends' => DI\add([ * DI\get('My\Custom\LogBackend') * ]) * * @param mixed|array $values A value or an array of values to add to the array. * * @since 5.0 */ function add($values) : ArrayDefinitionExtension { if (!\is_array($values)) { $values = [$values]; } return new ArrayDefinitionExtension($values); } } if (!\function_exists('ElementorDeps\\DI\\string')) { /** * Helper for concatenating strings. * * Example: * * 'log.filename' => DI\string('{app.path}/app.log') * * @param string $expression A string expression. Use the `{}` placeholders to reference other container entries. * * @since 5.0 */ function string(string $expression) : StringDefinition { return new StringDefinition($expression); } }/** * The registry for Third Party Plugins Integration files. * * This file is only used to include the integration files/classes. * This works as an entry point for the initial add_action for the * detect function. * * It is not required to add all integration files here, this just provides * a common place for plugin authors to append their file to. */ defined('WPINC') || exit(); use LiteSpeed\API; $third_cls = array( 'Aelia_CurrencySwitcher', 'Autoptimize', 'Avada', 'BBPress', 'Beaver_Builder', 'Caldera_Forms', 'Divi_Theme_Builder', 'Facetwp', 'LiteSpeed_Check', 'Theme_My_Login', 'User_Switching', 'WCML', 'WooCommerce', 'WC_PDF_Product_Vouchers', 'Woo_Paypal', 'Wp_Polls', 'WP_PostRatings', 'Wpdiscuz', 'WPLister', 'WPML', 'WpTouch', 'Yith_Wishlist', ); foreach ($third_cls as $cls) { add_action('litespeed_load_thirdparty', 'LiteSpeed\Thirdparty\\' . $cls . '::detect'); } // Preload needed for certain thirdparty add_action('litespeed_init', 'LiteSpeed\Thirdparty\Divi_Theme_Builder::preload'); add_action('litespeed_init', 'LiteSpeed\Thirdparty\WooCommerce::preload'); add_action('litespeed_init', 'LiteSpeed\Thirdparty\NextGenGallery::preload'); add_action('litespeed_init', 'LiteSpeed\Thirdparty\AMP::preload'); add_action('litespeed_init', 'LiteSpeed\Thirdparty\Elementor::preload'); add_action('litespeed_init', 'LiteSpeed\Thirdparty\Gravity_Forms::preload'); add_action('litespeed_init', 'LiteSpeed\Thirdparty\Perfmatters::preload');XML-RPC server accepts POST requests only.