Skip to content

Commit

Permalink
Merge 70612c0 into 62dac3b
Browse files Browse the repository at this point in the history
  • Loading branch information
emadha committed Feb 8, 2018
2 parents 62dac3b + 70612c0 commit ed12953
Show file tree
Hide file tree
Showing 2 changed files with 140 additions and 55 deletions.
123 changes: 84 additions & 39 deletions src/CSS.php
Expand Up @@ -37,16 +37,16 @@ class CSS extends Minify
* @var string[] valid import extensions
*/
protected $importExtensions = array(
'gif' => 'data:image/gif',
'png' => 'data:image/png',
'jpe' => 'data:image/jpeg',
'jpg' => 'data:image/jpeg',
'gif' => 'data:image/gif',
'png' => 'data:image/png',
'jpe' => 'data:image/jpeg',
'jpg' => 'data:image/jpeg',
'jpeg' => 'data:image/jpeg',
'svg' => 'data:image/svg+xml',
'svg' => 'data:image/svg+xml',
'woff' => 'data:application/x-font-woff',
'tif' => 'image/tiff',
'tif' => 'image/tiff',
'tiff' => 'image/tiff',
'xbm' => 'image/x-xbitmap',
'xbm' => 'image/x-xbitmap',
);

/**
Expand Down Expand Up @@ -93,7 +93,7 @@ protected function moveImportsToTop($content)
}

// add to top
$content = implode(';', $matches[2]).';'.trim($content, ';');
$content = implode(';', $matches[2]) . ';' . trim($content, ';');
}

return $content;
Expand All @@ -105,8 +105,8 @@ protected function moveImportsToTop($content)
* @import's will be loaded and their content merged into the original file,
* to save HTTP requests.
*
* @param string $source The file to combine imports for
* @param string $content The CSS content to combine imports for
* @param string $source The file to combine imports for
* @param string $content The CSS content to combine imports for
* @param string[] $parents Parent paths, for circular reference checks
*
* @return string
Expand Down Expand Up @@ -200,7 +200,7 @@ protected function combineImports($source, $content, $parents)
// loop the matches
foreach ($matches as $match) {
// get the path for the file that will be imported
$importPath = dirname($source).'/'.$match['path'];
$importPath = dirname($source) . '/' . $match['path'];

// only replace the import with the content if we can grab the
// content of the file
Expand All @@ -211,7 +211,7 @@ protected function combineImports($source, $content, $parents)
// check if current file was not imported previously in the same
// import chain.
if (in_array($importPath, $parents)) {
throw new FileImportException('Failed to import file "'.$importPath.'": circular reference detected.');
throw new FileImportException('Failed to import file "' . $importPath . '": circular reference detected.');
}

// grab referenced file & minify it (which may include importing
Expand All @@ -221,7 +221,7 @@ protected function combineImports($source, $content, $parents)

// check if this is only valid for certain media
if (!empty($match['media'])) {
$importContent = '@media '.$match['media'].'{'.$importContent.'}';
$importContent = '@media ' . $match['media'] . '{' . $importContent . '}';
}

// add to replacement array
Expand All @@ -239,7 +239,7 @@ protected function combineImports($source, $content, $parents)
* @url(image.jpg) images will be loaded and their content merged into the
* original file, to save HTTP requests.
*
* @param string $source The file to import files for
* @param string $source The file to import files for
* @param string $content The CSS content to import files for
*
* @return string
Expand All @@ -260,7 +260,7 @@ protected function importFiles($source, $content)

// get the path for the file that will be imported
$path = $match[2];
$path = dirname($source).'/'.$path;
$path = dirname($source) . '/' . $path;

// only replace the import with the content if we're able to get
// the content of the file, and it's relatively small
Expand All @@ -271,7 +271,7 @@ protected function importFiles($source, $content)

// build replacement
$search[] = $match[0];
$replace[] = 'url('.$this->importExtensions[$extension].';base64,'.$importContent.')';
$replace[] = 'url(' . $this->importExtensions[$extension] . ';base64,' . $importContent . ')';
}
}

Expand All @@ -287,9 +287,10 @@ protected function importFiles($source, $content)
* Perform CSS optimizations.
*
* @param string[optional] $path Path to write the data to
* @param string[] $parents Parent paths, for circular reference checks
* @param string[] $parents Parent paths, for circular reference checks
*
* @return string The minified data
* @throws FileImportException
*/
public function execute($path = null, $parents = array())
{
Expand All @@ -303,15 +304,28 @@ public function execute($path = null, $parents = array())
* we should leave it alone. E.g.:
* p { content: "a test" }
*/

$this->extractStrings();
$this->stripComments();

if ($this->options['css-strip-comments'] === true)
$this->stripComments();

$css = $this->replace($css);

$css = $this->stripWhitespace($css);
$css = $this->shortenHex($css);
$css = $this->shortenZeroes($css);
$css = $this->shortenFontWeights($css);
$css = $this->stripEmptyTags($css);
if ($this->options['css-strip-whitespace'] === true)
$css = $this->stripWhitespace($css);

if ($this->options['css-shorten-hex'] === true)
$css = $this->shortenHex($css);

if ($this->options['css-shorten-zeroes'] === true)
$css = $this->shortenZeroes($css);

if ($this->options['css-shorten-font-weights'] === true)
$css = $this->shortenFontWeights($css);

if ($this->options['css-strip-empty-tags'] === true)
$css = $this->stripEmptyTags($css);

// restore the string we've extracted earlier
$css = $this->restoreExtractedData($css);
Expand All @@ -337,6 +351,37 @@ public function execute($path = null, $parents = array())

$content = $this->moveImportsToTop($content);

/*
* After getting the merged data of all css files
* this method here will remove duplicate css selectors
* for instance, a user might add two css files like default.css & default.css?v=1
* both files contain the same selectors "body {font-family: xxx}"
* this method will deal with those duplicates and remove them from the final content.
*/
$content = $this->removeDuplicates($content);

return $content;
}

/**
* Remove Duplicate CSS Selectors
* for example if there is duplicate body{font-size:13px}
* this method will return one selector
*
* @param $content
* @return string
*/
private function removeDuplicates($content)
{

// Collect Selectors
preg_match_all('/(?ims)([a-z0-9, \s\.\:#_\-@]+)\{([^\}]*)\}/', $content, $selectors);

if (isset($selectors[0]))

// return a unique array of selectors and implode it into a string
return implode(null, array_unique($selectors[0]));

return $content;
}

Expand All @@ -347,7 +392,7 @@ public function execute($path = null, $parents = array())
* (e.g. ../../images/image.gif, if the new CSS file is 1 folder deeper).
*
* @param ConverterInterface $converter Relative path converter
* @param string $content The CSS content to update relative urls for
* @param string $content The CSS content to update relative urls for
*
* @return string
*/
Expand Down Expand Up @@ -461,9 +506,9 @@ protected function move(ConverterInterface $converter, $content)
// build replacement
$search[] = $match[0];
if ($type === 'url') {
$replace[] = 'url('.$url.')';
$replace[] = 'url(' . $url . ')';
} elseif ($type === 'import') {
$replace[] = '@import "'.$url.'"';
$replace[] = '@import "' . $url . '"';
}
}

Expand Down Expand Up @@ -503,7 +548,7 @@ protected function shortenHex($content)
'#FFC0CB' => 'pink',
'#DDA0DD' => 'plum',
'#800080' => 'purple',
'#F00' => 'red',
'#F00' => 'red',
'#FA8072' => 'salmon',
'#A0522D' => 'sienna',
'#C0C0C0' => 'silver',
Expand All @@ -515,7 +560,7 @@ protected function shortenHex($content)
);

return preg_replace_callback(
'/(?<=[: ])('.implode(array_keys($colors), '|').')(?=[; }])/i',
'/(?<=[: ])(' . implode(array_keys($colors), '|') . ')(?=[; }])/i',
function ($match) use ($colors) {
return $colors[strtoupper($match[0])];
},
Expand All @@ -534,14 +579,14 @@ protected function shortenFontWeights($content)
{
$weights = array(
'normal' => 400,
'bold' => 700,
'bold' => 700,
);

$callback = function ($match) use ($weights) {
return $match[1].$weights[$match[2]];
return $match[1] . $weights[$match[2]];
};

return preg_replace_callback('/(font-weight\s*:\s*)('.implode('|', array_keys($weights)).')(?=[;}])/', $callback, $content);
return preg_replace_callback('/(font-weight\s*:\s*)(' . implode('|', array_keys($weights)) . ')(?=[;}])/', $callback, $content);
}

/**
Expand Down Expand Up @@ -577,19 +622,19 @@ protected function shortenZeroes($content)
// practice, Webkit (especially Safari) seems to stumble over at least
// 0%, potentially other units as well. Only stripping 'px' for now.
// @see https://github.com/matthiasmullie/minify/issues/60
$content = preg_replace('/'.$before.'(-?0*(\.0+)?)(?<=0)px'.$after.'/', '\\1', $content);
$content = preg_replace('/' . $before . '(-?0*(\.0+)?)(?<=0)px' . $after . '/', '\\1', $content);

// strip 0-digits (.0 -> 0)
$content = preg_replace('/'.$before.'\.0+'.$units.'?'.$after.'/', '0\\1', $content);
$content = preg_replace('/' . $before . '\.0+' . $units . '?' . $after . '/', '0\\1', $content);
// strip trailing 0: 50.10 -> 50.1, 50.10px -> 50.1px
$content = preg_replace('/'.$before.'(-?[0-9]+\.[0-9]+)0+'.$units.'?'.$after.'/', '\\1\\2', $content);
$content = preg_replace('/' . $before . '(-?[0-9]+\.[0-9]+)0+' . $units . '?' . $after . '/', '\\1\\2', $content);
// strip trailing 0: 50.00 -> 50, 50.00px -> 50px
$content = preg_replace('/'.$before.'(-?[0-9]+)\.0+'.$units.'?'.$after.'/', '\\1\\2', $content);
$content = preg_replace('/' . $before . '(-?[0-9]+)\.0+' . $units . '?' . $after . '/', '\\1\\2', $content);
// strip leading 0: 0.1 -> .1, 01.1 -> 1.1
$content = preg_replace('/'.$before.'(-?)0+([0-9]*\.[0-9]+)'.$units.'?'.$after.'/', '\\1\\2\\3', $content);
$content = preg_replace('/' . $before . '(-?)0+([0-9]*\.[0-9]+)' . $units . '?' . $after . '/', '\\1\\2\\3', $content);

// strip negative zeroes (-0 -> 0) & truncate zeroes (00 -> 0)
$content = preg_replace('/'.$before.'-?0+'.$units.'?'.$after.'/', '0\\1', $content);
$content = preg_replace('/' . $before . '-?0+' . $units . '?' . $after . '/', '0\\1', $content);

// IE doesn't seem to understand a unitless flex-basis value (correct -
// it goes against the spec), so let's add it in again (make it `%`,
Expand Down Expand Up @@ -655,7 +700,7 @@ protected function stripWhitespace($content)
// not in things like `calc(3px + 2px)`, shorthands like `3px -2px`, or
// selectors like `div.weird- p`
$pseudos = array('nth-child', 'nth-last-child', 'nth-last-of-type', 'nth-of-type');
$content = preg_replace('/:('.implode('|', $pseudos).')\(\s*([+-]?)\s*(.+?)\s*([+-]?)\s*(.*?)\s*\)/', ':$1($2$3$4$5)', $content);
$content = preg_replace('/:(' . implode('|', $pseudos) . ')\(\s*([+-]?)\s*(.+?)\s*([+-]?)\s*(.*?)\s*\)/', ':$1($2$3$4$5)', $content);

// remove semicolon/whitespace followed by closing bracket
$content = str_replace(';}', '}', $content);
Expand Down Expand Up @@ -690,7 +735,7 @@ protected function findCalcs($content)
}
}

$results['calc('.count($results).')'] = 'calc'.$expr;
$results['calc(' . count($results) . ')'] = 'calc' . $expr;
}

return $results;
Expand Down

0 comments on commit ed12953

Please sign in to comment.