Compressor.

@since 150510 Initial release.

@param string $css Input CSS.
762820
public static function compress($css)
    {
        $css = (string) $css;
        try {
            $css_minifier = new static($css);
            $minified_css = $css_minifier->min();
            return $minified_css;
        } catch (\Exception $exception) {
            return $css;
        }
    }
902
private function loadStyleSheetAsset($css){

        $imageRe = "/url\\s*\\(['|\"]?([^)]*\.(png|jpg|jpeg|gif|svg))['|\"]?\\)/mi";
        $importRe = "/@import\\s*(url\\s*\\()?['\"]?([^;]*)['\"]/mi";
        $fontFaceRe = "/@font-face\\s*\\{(.*)?\\}/mi";
        $fontRe = "/url\\s*\\(['|\"]?([^)'|\"]*)['|\"]?\\)/i";

        //extract images
        preg_match_all($imageRe, $css, $matches);
        if(isset($matches[1])){
            foreach($matches[1] as $match){
                $this->addAsset('img', $match);
            }
        }

        //extract @import
        preg_match_all($importRe, $css, $matches);
        if(isset($matches[2])){
            foreach($matches[2] as $match){
                $this->addAsset('css', $match);
            }
        }

        //extract fonts
        preg_match_all($fontFaceRe, $css, $matches);
        if(isset($matches[1])){
            foreach($matches[1] as $faceMatch){
                preg_match_all($fontRe, $faceMatch, $fontMatches);
                if(isset($fontMatches[1])){
                    foreach($fontMatches[1] as $fontMatch){
                        $this->addAsset('font', $fontMatch);
                    }
                }
            }
        }
    }
850741
public function addCss($css)
    {
        if (!is_array($css)) {

            // Clean css argument from unnecessary spaces
            $css = preg_replace('/[ ]+/', ' ', $css);

            // Do not trust the programmer and convert a possible
            // string of multiple css class notations to array
            $css = explode(' ', $css);
        }

        foreach ($css as $class) {
            $this->css[$class] = $class;
        }
    }
105162
public static function cssStringToArray($css)
    {
        $statements = explode(';', preg_replace('/\s+/s', ' ', $css));
        $styles = array();
        foreach ($statements as $statement) {
            $statement = trim($statement);
            if ('' === $statement) {
                continue;
            }
            $p = strpos($statement, ':');
            if ($p <= 0) {
                continue;
            } // invalid statement, just ignore it
            $key = trim(substr($statement, 0, $p));
            $value = trim(substr($statement, $p + 1));
            $styles[$key] = $value;
        }
        return $styles;
    }
988908
private function getCss($cssFiles = array())
    {
        $css = '';
        foreach ($cssFiles as $file) {
            if (file_exists($file)) {
                $css .= file_get_contents($file) . "\n";
            }
        }
        return $css;
    }
1318411
public static function css_files(array $files) {
        if (empty($files)) {
            return '';
        }

        $compressed = array();
        foreach ($files as $file) {
            $content = file_get_contents($file);
            if ($content === false) {
                $compressed[] = "\n\n/* Cannot read CSS file ".basename(dirname(dirname($file))).'/'.basename(dirname($file)).'/'.basename($file)."*/\n\n";
                continue;
            }
            $compressed[] = self::css($content);
        }

        return implode("\n", $compressed);
    }
1098713
protected function addStyleElementToDocument($css)
    {
        $styleElement = $this->domDocument->createElement('style', $css);
        $styleAttribute = $this->domDocument->createAttribute('type');
        $styleAttribute->value = 'text/css';
        $styleElement->appendChild($styleAttribute);

        $headElement = $this->getHeadElement();
        $headElement->appendChild($styleElement);
    }
524372
private static function fixLtrRtlInURL($css) {
		$css = preg_replace(self::$patterns['ltr_in_url'], self::$patterns['tmpToken'], $css);
		$css = preg_replace(self::$patterns['rtl_in_url'], 'ltr', $css);
		$css = str_replace(self::$patterns['tmpToken'], 'rtl', $css);

		return $css;
	}
80958
public static function styles_parse( $css = [] ) {

		// Pass our styles from the kirki_styles_array filter.
		$css = apply_filters( 'kirki_styles_array', $css );

		// Process the array of CSS properties and produce the final CSS.
		$final_css = '';
		if ( ! is_array( $css ) || empty( $css ) ) {
			return '';
		}
		foreach ( $css as $media_query => $styles ) {
			$final_css .= ( 'global' !== $media_query ) ? $media_query . '{' : '';
			foreach ( $styles as $style => $style_array ) {
				$css_for_style = '';

				foreach ( $style_array as $property => $value ) {
					if ( is_string( $value ) && '' !== $value ) {
						$css_for_style .= $property . ':' . $value . ';';
					} elseif ( is_array( $value ) ) {
						foreach ( $value as $subvalue ) {
							if ( is_string( $subvalue ) && '' !== $subvalue ) {
								$css_for_style .= $property . ':' . $subvalue . ';';
							}
						}
					}
					$value = ( is_string( $value ) ) ? $value : '';
				}
				if ( '' !== $css_for_style ) {
					$final_css .= $style . '{' . $css_for_style . '}';
				}
			}
			$final_css .= ( 'global' !== $media_query ) ? '}' : '';
		}
		return $final_css;
	}
695476
def css_compressor=(compressor)
      if compressor.respond_to?(:to_sym)
        compressor = CSS_COMPRESSORS[compressor.to_sym]
      end
      Tilt.prefer compressor, 'css'
    end
863496
private function splitIntoBlocks($css)
	{
		if (is_array($css)) {
			return $css;
		}

		$blocks = array();
		$css    = $this->stripComments($css);
		$offset = 0;

		// catch all @feature {...} blocks
		if (preg_match_all('/(@[^{]+){([^{}]*{[^}]*})*\s*}/ism', $css, $matches, PREG_OFFSET_CAPTURE) > 0) {
			foreach ($matches[0] as $key => $match) {
				$atRule              = trim($matches[1][$key][0]);
				list($rules, $start) = $match;

				if ($start > $offset) {
					// make previous selectors into their own block
					$block = trim(substr($css, $offset, $start - $offset));
					if (!empty($block)) {
						$blocks[] = $this->summarizeBlock($block);
					}
				}
				$offset = $start + strlen($rules);

				// currently only @media rules need to be parsed and counted for IE9 selectors
				if (strpos($atRule, '@media') === 0) {
					$block  = $this->summarizeBlock(substr($rules, strpos($rules, '{') + 1, -1));
				}
				else {
					$block  = array(
						'count'   => 1,
						'rules'   => array(
							array(
								'rule' => substr($rules, strpos($rules, '{') + 1, -1),
								'count' => 1,
							)
						),

					);
				}

				$block['at-rule'] = $atRule;
				$blocks[]               = $block;
			}

			// catch any remaining as it's own block
			$block = trim(substr($css, $offset));
			if (!empty($block)) {
				$blocks[] = $this->summarizeBlock($block);
			}
		}
		else {
			$blocks[] = $this->summarizeBlock($css);
		}

		return $blocks;
	}
479670
public function convertToRadius($css)
    {
        // explode the value
        $css = explode(' ', $css);

        foreach ($css as $k => $v) {
            $v = trim($v);
            if ($v) {
                $v = $this->convertToMM($v, 0);
                if ($v!==null) {
                    $css[$k] = $v;
                } else {
                    unset($css[$k]);
                }
            } else {
                unset($css[$k]);
            }
        }

        return array_values($css);
    }
138697
public static function add_prefixes( $css ) {
		if ( is_array( $css ) ) {
			foreach ( $css as $media_query => $elements ) {
				foreach ( $elements as $element => $style_array ) {
					foreach ( $style_array as $property => $value ) {

						// Add -webkit-* and -moz-*.
						if ( is_string( $property ) && in_array(
							$property,
							[
								'border-radius',
								'box-shadow',
								'box-sizing',
								'text-shadow',
								'transform',
								'background-size',
								'transition',
								'transition-property',
							],
							true
						) ) {
							unset( $css[ $media_query ][ $element ][ $property ] );
							$css[ $media_query ][ $element ][ '-webkit-' . $property ] = $value;
							$css[ $media_query ][ $element ][ '-moz-' . $property ]    = $value;
							$css[ $media_query ][ $element ][ $property ]              = $value;
						}

						// Add -ms-* and -o-*.
						if ( is_string( $property ) && in_array(
							$property,
							[
								'transform',
								'background-size',
								'transition',
								'transition-property',
							],
							true
						) ) {
							unset( $css[ $media_query ][ $element ][ $property ] );
							$css[ $media_query ][ $element ][ '-ms-' . $property ] = $value;
							$css[ $media_query ][ $element ][ '-o-' . $property ]  = $value;
							$css[ $media_query ][ $element ][ $property ]          = $value;
						}
					}
				}
			}
		}
		return $css;
	}
914138
protected function removeCss($css)
    {
        $key=array_keys($this->data['css']['internal'],$css);
        if($key){
            array_splice($this->data['css']['internal'],$key[0],1);
        }

        $key=array_keys($this->data['css']['external'],$css);
        if($key){
            array_splice($this->data['css']['external'],$key[0],1);
        }
    }
9130
protected function loadCss($css, $options=array())
    {
        $location = (isset($options['location'])) ? $options['location']:'internal';

        //after:file, before:file, first, last
        $position = (isset($options['position'])) ? $options['position']:'last';

        if(!in_array($css,$this->data['css'][$location])){
            if($position=='first' || $position=='last'){
                $key = $position;
                $file='';
            }else{
                list($key,$file) =  explode(':',$position);
            }

            switch($key){
                case 'first':
                    array_unshift($this->data['css'][$location],$css);
                break;

                case 'last':
                    $this->data['css'][$location][]=$css;
                break;

                case 'before':
                case 'after':
                    $varkey = array_keys($this->data['css'][$location],$file);
                    if($varkey){
                        $nextkey = ($key=='after') ? $varkey[0]+1 : $varkey[0];
                        array_splice($this->data['css'][$location],$nextkey,0,$css);
                    }else{
                        $this->data['css'][$location][]=$css;
                    }
                break;
            }
        }
    }
931483
protected function maybeFilterCssUrls($css)
    {
        if (!($css = (string) $css)) {
            return $css; // Nothing to do.
        }
        if (!$this->hook_api->hasFilter('css_url()')) {
            return $css; // No reason to do this.
        }
        $import_without_url_regex = '/(?P<import>@(?:\-(?:'.$this->regex_vendor_css_prefixes.')\-)?import\s*)(?P<open_encap>["\'])(?P<url>.+?)(?P<close_encap>\\2)/ui';
        $any_url_regex            = '/(?P<url_>url\s*)(?P<open_bracket>\(\s*)(?P<open_encap>["\']?)(?P<url>.+?)(?P<close_encap>\\3)(?P<close_bracket>\s*\))/ui';

        $css = preg_replace_callback($import_without_url_regex, [$this, 'filterCssUrlImportCb'], $css);
        $css = preg_replace_callback($any_url_regex, [$this, 'filterCssUrlCb'], $css);

        return $css;
    }
960209
public function setCss($css)
    {
        if (is_array($css))
            $css = implode(' ', $css);

        $this->css = $css;

        return $this;
    }