Does bulk of the minification
@param string $css
@param int|bool $linebreak_pos
@return string
512855
private function minify($css, $linebreak_pos)
    {
        // strings are safe, now wrestle the comments
        for ($i = 0, $max = count($this->comments); $i < $max; $i++) {

            $token = $this->comments[$i];
            $placeholder = '/' . self::COMMENT . $i . '___/';

            // ! in the first position of the comment means preserve
            // so push to the preserved tokens keeping the !
            if (substr($token, 0, 1) === '!') {
                $this->preserved_tokens[] = $token;
                $token_tring = self::TOKEN . (count($this->preserved_tokens) - 1) . '___';
                $css = preg_replace($placeholder, $token_tring, $css, 1);
                // Preserve new lines for /*! important comments
                $css = preg_replace('/\s*[\n\r\f]+\s*(\/\*'. $token_tring .')/S', self::NL.'$1', $css);
                $css = preg_replace('/('. $token_tring .'\*\/)\s*[\n\r\f]+\s*/S', '$1'.self::NL, $css);
                continue;
            }

            // \ in the last position looks like hack for Mac/IE5
            // shorten that to /*\*/ and the next one to /**/
            if (substr($token, (strlen($token) - 1), 1) === '\\') {
                $this->preserved_tokens[] = '\\';
                $css = preg_replace($placeholder,  self::TOKEN . (count($this->preserved_tokens) - 1) . '___', $css, 1);
                $i = $i + 1; // attn: advancing the loop
                $this->preserved_tokens[] = '';
                $css = preg_replace('/' . self::COMMENT . $i . '___/',  self::TOKEN . (count($this->preserved_tokens) - 1) . '___', $css, 1);
                continue;
            }

            // keep empty comments after child selectors (IE7 hack)
            // e.g. html >/**/ body
            if (strlen($token) === 0) {
                $start_index = $this->index_of($css, $this->str_slice($placeholder, 1, -1));
                if ($start_index > 2) {
                    if (substr($css, $start_index - 3, 1) === '>') {
                        $this->preserved_tokens[] = '';
                        $css = preg_replace($placeholder,  self::TOKEN . (count($this->preserved_tokens) - 1) . '___', $css, 1);
                    }
                }
            }

            // in all other cases kill the comment
            $css = preg_replace('/\/\*' . $this->str_slice($placeholder, 1, -1) . '\*\//', '', $css, 1);
        }


        // Normalize all whitespace strings to single spaces. Easier to work with that way.
        $css = preg_replace('/\s+/', ' ', $css);

        // Shorten & preserve calculations calc(...) since spaces are important
        $css = preg_replace_callback('/calc(\((?:[^\(\)]+|(?1))*\))/i', array($this, 'replace_calc'), $css);

        // Replace positive sign from numbers preceded by : or a white-space before the leading space is removed
        // +1.2em to 1.2em, +.8px to .8px, +2% to 2%
        $css = preg_replace('/((?<!\\\\)\:|\s)\+(\.?\d+)/S', '$1$2', $css);

        // Remove leading zeros from integer and float numbers preceded by : or a white-space
        // 000.6 to .6, -0.8 to -.8, 0050 to 50, -01.05 to -1.05
        $css = preg_replace('/((?<!\\\\)\:|\s)(\-?)0+(\.?\d+)/S', '$1$2$3', $css);

        // Remove trailing zeros from float numbers preceded by : or a white-space
        // -6.0100em to -6.01em, .0100 to .01, 1.200px to 1.2px
        $css = preg_replace('/((?<!\\\\)\:|\s)(\-?)(\d?\.\d+?)0+([^\d])/S', '$1$2$3$4', $css);

        // Remove trailing .0 -> -9.0 to -9
        $css = preg_replace('/((?<!\\\\)\:|\s)(\-?\d+)\.0([^\d])/S', '$1$2$3', $css);

        // Replace 0 length numbers with 0
        $css = preg_replace('/((?<!\\\\)\:|\s)\-?\.?0+([^\d])/S', '${1}0$2', $css);

        // Remove the spaces before the things that should not have spaces before them.
        // But, be careful not to turn "p :link {...}" into "p:link{...}"
        // Swap out any pseudo-class colons with the token, and then swap back.
        $css = preg_replace_callback('/(?:^|\})(?:(?:[^\{\:])+\:)+(?:[^\{]*\{)/', array($this, 'replace_colon'), $css);
        $css = preg_replace('/\s+([\!\{\}\;\:\>\+\(\)\]\~\=,])/', '$1', $css);
        $css = preg_replace('/' . self::CLASSCOLON . '/', ':', $css);

        // retain space for special IE6 cases
        $css = preg_replace('/\:first\-(line|letter)(\{|,)/i', ':first-$1 $2', $css);

        // no space after the end of a preserved comment
        $css = preg_replace('/\*\/ /', '*/', $css);

        // Put the space back in some cases, to support stuff like
        // @media screen and (-webkit-min-device-pixel-ratio:0){
        $css = preg_replace('/\band\(/i', 'and (', $css);

        // Remove the spaces after the things that should not have spaces after them.
        $css = preg_replace('/([\!\{\}\:;\>\+\(\[\~\=,])\s+/S', '$1', $css);

        // remove unnecessary semicolons
        $css = preg_replace('/;+\}/', '}', $css);

        // Fix for issue: #2528146
        // Restore semicolon if the last property is prefixed with a `*` (lte IE7 hack)
        // to avoid issues on Symbian S60 3.x browsers.
        $css = preg_replace('/(\*[a-z0-9\-]+\s*\:[^;\}]+)(\})/', '$1;$2', $css);

        // Replace 0 length units 0(px,em,%) with 0.
        $css = preg_replace('/((?<!\\\\)\:|\s)\-?0(?:em|ex|ch|rem|vw|vh|vm|vmin|cm|mm|in|px|pt|pc|%)/iS', '${1}0', $css);

        // Replace 0 0; or 0 0 0; or 0 0 0 0; with 0.
        $css = preg_replace('/\:0(?: 0){1,3}(;|\})/', ':0$1', $css);

        // Fix for issue: #2528142
        // Replace text-shadow:0; with text-shadow:0 0 0;
        $css = preg_replace_callback(
                   '/(text-shadow\:0)(;|\})/i',
                   function($m) {
                       return strtolower($m[1] . ' 0 0' . $m[2]);
                   },
                   $css
               );

        // Replace background-position:0; with background-position:0 0;
        // same for transform-origin
        $css = preg_replace_callback(
                   '/(background\-position|(?:webkit|moz|o|ms|)\-?transform\-origin)\:0(;|\})/iS',
                   function($m) {
                       return strtolower($m[1] . ':0 0' . $m[2]);
                   },
                   $css
               );

        // Shorten colors from rgb(51,102,153) to #336699, rgb(100%,0%,0%) to #ff0000 (sRGB color space)
        // Shorten colors from hsl(0, 100%, 50%) to #ff0000 (sRGB color space)
        // This makes it more likely that it'll get further compressed in the next step.
        $css = preg_replace_callback('/rgb\s*\(\s*([0-9,\s\-\.\%]+)\s*\)(.{1})/i', array($this, 'rgb_to_hex'), $css);
        $css = preg_replace_callback('/hsl\s*\(\s*([0-9,\s\-\.\%]+)\s*\)(.{1})/i', array($this, 'hsl_to_hex'), $css);

        // Shorten colors from #AABBCC to #ABC or short color name.
        $css = $this->compress_hex_colors($css);

        // border: none to border:0, outline: none to outline:0
        $css = preg_replace_callback(
                   '/(border\-?(?:top|right|bottom|left|)|outline)\:none(;|\})/iS',
                   function($m) {
                       return strtolower($m[1] . ':0' . $m[2]);
                   },
                   $css
               );

        // shorter opacity IE filter
        $css = preg_replace('/progid\:DXImageTransform\.Microsoft\.Alpha\(Opacity\=/i', 'alpha(opacity=', $css);

        // Remove empty rules.
        $css = preg_replace('/[^\};\{\/]+\{\}/S', '', $css);

        // Some source control tools don't like it when files containing lines longer
        // than, say 8000 characters, are checked in. The linebreak option is used in
        // that case to split long lines after a specific column.
        if ($linebreak_pos !== FALSE && (int) $linebreak_pos >= 0) {
            $linebreak_pos = (int) $linebreak_pos;
            $start_index = $i = 0;
            while ($i < strlen($css)) {
                $i++;
                if ($css[$i - 1] === '}' && $i - $start_index > $linebreak_pos) {
                    $css = $this->str_slice($css, 0, $i) . "\n" . $this->str_slice($css, $i);
                    $start_index = $i;
                }
            }
        }

        // Replace multiple semi-colons in a row by a single one
        // See SF bug #1980989
        $css = preg_replace('/;;+/', ';', $css);

        // Restore new lines for /*! important comments
        $css = preg_replace('/'. self::NL .'/', "\n", $css);

        // restore preserved comments and strings
        for ($i = 0, $max = count($this->preserved_tokens); $i < $max; $i++) {
            $css = preg_replace('/' . self::TOKEN . $i . '___/', $this->preserved_tokens[$i], $css, 1);
        }

        // Trim the final string (for any leading or trailing white spaces)
        return trim($css);
    }
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;
    }
8569
protected function maybeCompressCssCode($css)
    {
        if (($benchmark = !empty($this->options['benchmark']) && $this->options['benchmark'] === 'details')) {
            $time = microtime(true);
        }
        $css = (string) $css; // Force string value.

        if (isset($this->options['compress_css_code'])) {
            if (!$this->options['compress_css_code']) {
                $disabled = true; // Disabled flag.
            }
        }
        if (!$css || !empty($disabled)) {
            goto finale; // Nothing to do.
        }
        if (strlen($css) > 1000000) {
            // Exclude VERY large files. Too time-consuming.
            // Should really be compressed ahead-of-time anyway.
            goto finale; // Don't compress HUGE files.
        }
        try { // Catch CSS compression-related exceptions.
            if (!($compressed_css = \WebSharks\CssMinifier\Core::compress($css))) {
                // `E_USER_NOTICE` to avoid a show-stopping problem.
                trigger_error('CSS compression failure.', E_USER_NOTICE);
            } else {
                $css = $this->stripUtf8Bom($compressed_css);
            } // Use compressed CSS file.
        } catch (\Exception $exception) {
            trigger_error($exception->getMessage(), E_USER_NOTICE);
        }
        finale: // Target point; finale/return value.

        if ($css) {
            $css = trim($css);
        }
        if ($benchmark && !empty($time) && $css && empty($disabled)) {
            $this->benchmark->addTime(
                __FUNCTION__,
                $time, // Caller, start time, task performed.
                sprintf('compressing CSS w/ checksum: `%1$s`', md5($css))
            );
        }
        return $css;
    }
478729
def line_break(s, length=76):
    
    x = '\n'.join(s[pos:pos + length] for pos in range(0, len(s), length))
    return x
256388
public function setCss($css, array $options = array())
    {
        $options['asset'] = $css;
        $options['type'] = 'css';

        return $this->asset->set($options);
    }
1305452
def wrap_css_lines(css, line_length):
    """"""

    lines = []
    line_start = 0
    for i, char in enumerate(css):
        # It's safe to break after `}` characters.
        if char == '}' and (i - line_start >= line_length):
            lines.append(css[line_start:i + 1])
            line_start = i + 1

    if line_start < len(css):
        lines.append(css[line_start:])
    return '\n'.join(lines)
765225
public static function parse_css($styles='') {
		ref\cast::string($styles, true);

		// Remove comments.
		while (false !== ($start = mb::strpos($styles, '/*'))) {
			if (false !== ($end = mb::strpos($styles, '*/'))) {
				$styles = \str_replace(
					mb::substr($styles, $start, ($end - $start + 2)),
					'',
					$styles
				);
			}
			else {
				$styles = mb::substr($styles, 0, $start);
			}
		}

		// A few more types of comment wrappers we might see.
		$styles = \str_replace(
			array('<!--', '//-->', '-->', '//<![CDATA[', '//]]>', '<![CDATA[', ']]>'),
			'',
			$styles
		);

		// Standardize quoting.
		ref\sanitize::quotes($styles);
		$styles = \str_replace("'", '"', $styles);

		// Whitespace.
		ref\sanitize::whitespace($styles, 0);

		// Early bail.
		if (! $styles) {
			return array();
		}

		// Substitute brackets for unlikely characters to make parsing easier
		// hopefully nobody's using braille in their stylesheets...
		$styles = \preg_replace('/\{(?![^"]*"(?:(?:[^"]*"){2})*[^"]*$)/u', '⠁', $styles);
		$styles = \preg_replace('/\}(?![^"]*"(?:(?:[^"]*"){2})*[^"]*$)/u', '⠈', $styles);

		// Put spaces behind and after parentheses.
		$styles = \preg_replace(
			'/\s*(\()\s*(?![^"]*"(?:(?:[^"]*"){2})*[^"]*$)/u',
			' (',
			$styles
		);
		$styles = \preg_replace(
			'/\s*(\))\s*(?![^"]*"(?:(?:[^"]*"){2})*[^"]*$)/u',
			') ',
			$styles
		);

		// Make sure {} have no whitespace on either end.
		$styles = \preg_replace('/\s*(⠁|⠈|@)\s*/u', '$1', $styles);

		// Push @ rules to their own lines.
		$styles = \str_replace('@', "\n@", $styles);
		$styles = \explode("\n", $styles);
		$styles = \array_map('trim', $styles);

		// Push all rulesets to their own lines (leaving @media-type ones on their own for now).
		foreach ($styles as $k=>$v) {
			// @rule.
			if (0 === \strpos($styles[$k], '@')) {
				// Nested, like @media.
				if (false !== \strpos($styles[$k], '⠈⠈')) {
					$styles[$k] = \preg_replace('/(⠈{2,})/u', "$1\n", $styles[$k]);
				}
				// Not nested, but has properties, like @font-face.
				elseif (false !== \strpos($styles[$k], '⠈')) {
					$styles[$k] = \str_replace('⠈', "⠈\n", $styles[$k]);
				}
				// Just a line, like @import.
				elseif (\preg_match('/;(?![^"]*"(?:(?:[^"]*"){2})*[^"]*$)/', $styles[$k])) {
					$styles[$k] = \preg_replace(
						'/;(?![^"]*"(?:(?:[^"]*"){2})*[^"]*$)/u',
						";\n",
						$styles[$k],
						1
					);
				}

				$tmp = \explode("\n", $styles[$k]);
				$length = \count($tmp);
				for ($x = 1; $x < $length; ++$x) {
					$tmp[$x] = \str_replace('⠈', "⠈\n", $tmp[$x]);
				}
				$styles[$k] = \implode("\n", $tmp);
			}// end @.
			else {
				$styles[$k] = \str_replace('⠈', "⠈\n", $styles[$k]);
			}
		}
		$styles = \implode("\n", $styles);

		// One more quick formatting thing, we can get rid of spaces
		// between closing) and punctuation.
		$styles = \preg_replace(
			'/\)\s(,|;)(?![^"]*"(?:(?:[^"]*"){2})*[^"]*$)/u',
			')$1',
			$styles
		);

		// And between RGB/URL stuff.
		$styles = \preg_replace('/(url|rgba?)\s+\(/', '$1(', $styles);

		$styles = \explode("\n", $styles);
		$styles = \array_filter($styles, 'strlen');

		$out = array();

		// One more time around!
		foreach ($styles as $k=>$v) {
			$styles[$k] = \trim($styles[$k]);

			// Nested rule.
			if (
				(0 === \strpos($styles[$k], '@')) &&
				(false !== \strpos($styles[$k], '⠈⠈'))
			) {
				$tmp = constants::CSS_NESTED;

				// What kind of @ is this?
				\preg_match_all('/^@([a-z\-]+)/ui', $styles[$k], $matches);
				$tmp['@'] = mb::strtolower($matches[1][0]);

				// Find the outermost bit.
				if (false === ($start = mb::strpos($styles[$k], '⠁'))) {
					continue;
				}

				$tmp['selector'] = mb::strtolower(
					\trim(
						mb::substr($styles[$k], 0, $start)
					),
					false,
					true
				);
				$chunk = mb::substr($styles[$k], $start + 1, -1);
				$chunk = \str_replace(array('⠁', '⠈'), array('{', '}'), $chunk);
				$tmp['nest'] = static::parse_css($chunk);

				// And build the raw.
				$tmp['raw'] = $tmp['selector'] . '{';
				foreach ($tmp['nest'] as $n) {
					$tmp['raw'] .= $n['raw'];
				}
				$tmp['raw'] .= '}';
			}// end @.
			else {
				$tmp = constants::CSS_FLAT;

				if (0 === \strpos($styles[$k], '@')) {
					// What kind of @ is this?
					\preg_match_all('/^@([a-z\-]+)/ui', $styles[$k], $matches);
					$tmp['@'] = mb::strtolower($matches[1][0], false);
				}

				// A normal {k:v, k:v}.
				\preg_match_all('/^([^⠁]+)⠁([^⠈]*)⠈/u', $styles[$k], $matches);
				if (\count($matches[0])) {
					// Sorting out selectors is easy.
					$tmp['selectors'] = \explode(',', $matches[1][0]);
					$tmp['selectors'] = \array_map('trim', $tmp['selectors']);

					// Rules a little trickier.
					$rules = \explode(';', $matches[2][0]);
					$rules = \array_map('trim', $rules);
					$rules = \array_filter($rules, 'strlen');
					if (! \count($rules)) {
						continue;
					}

					foreach ($rules as $k2=>$v2) {
						$rules[$k2] = \rtrim($rules[$k2], ';') . ';';
						if (\preg_match(
							'/:(?![^"]*"(?:(?:[^"]*"){2})*[^"]*$)/',
							$rules[$k2]
						)) {
							$rules[$k2] = \preg_replace(
								'/:(?![^"]*"(?:(?:[^"]*"){2})*[^"]*$)/u',
								"\n",
								$rules[$k2],
								1
							);
							list($key, $value) = \explode("\n", $rules[$k2]);
							$key = mb::strtolower(\trim($key), false);
							$value = \trim($value);
							$tmp['rules'][$key] = $value;
						}
						else {
							$tmp['rules']['__NONE__'] = $value;
						}
					}

					// Build the raw.
					$tmp['raw'] = \implode(',', $tmp['selectors']) . '{';
					foreach ($tmp['rules'] as $k=>$v) {
						if ('__NONE__' === $k) {
							$tmp['raw'] .= $v;
						}
						else {
							$tmp['raw'] .= "$k:$v";
						}
					}
					$tmp['raw'] .= '}';
				}
				// Who knows?
				else {
					$styles[$k] = \str_replace(array('⠁', '⠈'), array('{', '}'), $styles[$k]);
					$styles[$k] = \trim(\rtrim(\trim($styles[$k]), ';'));
					if (\substr($styles[$k], -1) !== '}') {
						$styles[$k] .= ';';
					}
					$tmp['rules'][] = $styles[$k];
					$tmp['raw'] = $styles[$k];
				}
			}

			$out[] = $tmp;
		}

		return $out;
	}
516734
protected function getNormalizedPosition($pos)
    {
        if ($pos >= strlen($this->account) || $pos < -strlen($this->account)) {
            throw new ValidatorOutOfBoundsException("Cannot access offset $pos in String $this->account");

        }

        if ($pos >= 0) {
            return $pos;

        }
        return strlen($this->account) + $pos;
    }
1244353
public function text_first($css)
    {
        $nodes = $this->_document->getQuery()->css($css, $this->_node);
        return $nodes ? $nodes->item(0)->textContent : null;
    }
648680
private static function fixBackgroundPosition($css) {
		$replaced = preg_replace_callback(
			self::$patterns['bg_horizontal_percentage'],
			array('self', 'calculateNewBackgroundPosition'),
			$css
		);
		if ($replaced !== null) {
			// preg_replace_callback() sometimes returns null
			$css = $replaced;
		}
		$replaced = preg_replace_callback(
			self::$patterns['bg_horizontal_percentage_x'],
			array('self', 'calculateNewBackgroundPosition'),
			$css
		);
		if ($replaced !== null) {
			$css = $replaced;
		}

		return $css;
	}
395088
private static function fixShadows($css) {
		$css = preg_replace_callback(self::$patterns['box_shadow'], function ($matches) {
			return $matches[1] . self::flipSign($matches[2]);
		}, $css);

		$css = preg_replace_callback(self::$patterns['text_shadow1'], function ($matches) {
			return $matches[1] . $matches[2] . $matches[3] . self::flipSign($matches[4]);
		}, $css);

		$css = preg_replace_callback(self::$patterns['text_shadow2'], function ($matches) {
			return $matches[1] . $matches[2] . $matches[3] . self::flipSign($matches[4]);
		}, $css);

		$css = preg_replace_callback(self::$patterns['text_shadow3'], function ($matches) {
			return $matches[1] . self::flipSign($matches[2]);
		}, $css);

		return $css;
	}
963910
function(css) {
  css = css
    // remove comments
    .replace(/\/\*[^\0]*?\*\//g, '')
    // trim space before characters
    .replace(/\s+({|})/g, '$1')
    // trim space after characters
    .replace(/(;|,|:|{|}|^)\s+/g, '$1')
    // trim combinators
    .replace(/\s+(>|\+|~)\s+/g, '$1')
    // remove escaped newlines and spaces
    .replace(/\\\r?\n\s+/g, '')
    // remove trailing semicolons in rules
    .replace(/;(})/g, '$1');

  return css;
}
405630
protected function _convert( $css ) {
		$css = $this->_clean( $css );
		$css = explode( '}', $css );
		$css = array_filter( $css, 'strlen' );

		foreach ( $css as $key => $val ) {
			$css[ $key ] = explode( '{', $val );
		}

		foreach ( $css as $key => $css_block ) {
			$css[ $key ] = $this->_create_css_block( $css_block );
		}

		return $css;
	}
713040
public function extract_first($css, $rules)
    {
        $nodes = $this->_document->getQuery()->css($css);

        if ($nodes) {
            return (new static($this->_document, $nodes->item(0)))->extract($rules);
        } else {
            return [];
        }
    }
1200366
protected function getEmphasisByBlock($regexp, $pos)
	{
		$block    = [];
		$blocks   = [];
		$breakPos = $this->text->indexOf("\x17", $pos);

		preg_match_all($regexp, $this->text, $matches, PREG_OFFSET_CAPTURE, $pos);
		foreach ($matches[0] as $m)
		{
			$matchPos = $m[1];
			$matchLen = strlen($m[0]);

			// Test whether we've just passed the limits of a block
			if ($matchPos > $breakPos)
			{
				$blocks[] = $block;
				$block    = [];
				$breakPos = $this->text->indexOf("\x17", $matchPos);
			}

			// Test whether we should ignore this markup
			if (!$this->ignoreEmphasis($matchPos, $matchLen))
			{
				$block[] = [$matchPos, $matchLen];
			}
		}
		$blocks[] = $block;

		return $blocks;
	}
278385
public function get($css = null, $compress = true)
    {
        if (null === $css) {
            foreach ((array) $this->_list as $src) {
                if (!file_exists($src)) {
                    continue;
                }

                $css .= file_get_contents($src);
            }
        }

        $this->_list = [];

        return $compress ? $this->parse($css) : $css;
    }
234612
public function getByPosition($pos)
    {
        switch ($pos) {
            case 0:
                return $this->getId();
                break;
            case 1:
                return $this->getLocale();
                break;
            case 2:
                return $this->getLabel();
                break;
            default:
                return null;
                break;
        } // switch()
    }