← All changes
|
classes/external/php/yui-php-cssmin-bundled/Minifier.php
+46
-3
2.4.0
→
3.1.16
View file →
| @@ -28,13 +28,15 @@ | ||
| 28 | 28 | const COMMENT_TOKEN = '_CSSMIN_CMT_%d_'; |
| 29 | 29 | const COMMENT_TOKEN_START = '_CSSMIN_CMT_'; |
| 30 | 30 | const RULE_BODY_TOKEN = '_CSSMIN_RBT_%d_'; |
| 31 | 31 | const PRESERVED_TOKEN = '_CSSMIN_PTK_%d_'; |
| 32 | + const UNQUOTED_FONT_TOKEN = '_CSSMIN_UFT_%d_'; | |
| 32 | 33 | |
| 33 | 34 | // Token lists |
| 34 | 35 | private $comments = array(); |
| 35 | 36 | private $ruleBodies = array(); |
| 36 | 37 | private $preservedTokens = array(); |
| 38 | + private $unquotedFontTokens = array(); | |
| 37 | 39 | |
| 38 | 40 | // Output options |
| 39 | 41 | private $keepImportantComments = true; |
| 40 | 42 | private $keepSourceMapComment = false; |
| @@ -61,8 +63,9 @@ | ||
| 61 | 63 | private $shortenTwoZeroesRegex; |
| 62 | 64 | private $shortenThreeZeroesRegex; |
| 63 | 65 | private $shortenFourZeroesRegex; |
| 64 | 66 | private $unitsGroupRegex = '(?:ch|cm|em|ex|gd|in|mm|px|pt|pc|q|rem|vh|vmax|vmin|vw|%)'; |
| 67 | + private $unquotedFontsRegex = '/(font-family:|font:)([^\'"]+?)[^};]*/Si'; | |
| 65 | 68 | |
| 66 | 69 | /** |
| 67 | 70 | * @param bool|int $raisePhpLimits If true, PHP settings will be raised if needed |
| 68 | 71 | */ |
| @@ -286,8 +289,19 @@ | ||
| 286 | 289 | $this->ruleBodies[$tokenId] = $body; |
| 287 | 290 | return $tokenId; |
| 288 | 291 | } |
| 289 | 292 | |
| 293 | + private function registerUnquotedFontToken($body) | |
| 294 | + { | |
| 295 | + if (empty($body)) { | |
| 296 | + return ''; | |
| 297 | + } | |
| 298 | + | |
| 299 | + $tokenId = sprintf(self::UNQUOTED_FONT_TOKEN, count($this->unquotedFontTokens)); | |
| 300 | + $this->unquotedFontTokens[$tokenId] = $body; | |
| 301 | + return $tokenId; | |
| 302 | + } | |
| 303 | + | |
| 290 | 304 | /** |
| 291 | 305 | * Parses & minifies the given input CSS string |
| 292 | 306 | * @param string $css |
| 293 | 307 | * @return string |
| @@ -514,8 +528,13 @@ | ||
| 514 | 528 | $searchOffset = $substrOffset = 0; |
| 515 | 529 | |
| 516 | 530 | while (($blockStartPos = strpos($css, '{', $searchOffset)) !== false) { |
| 517 | 531 | $blockEndPos = strpos($css, '}', $blockStartPos); |
| 532 | + // When ending curly brace is missing, let's | |
| 533 | + // behave like there was one at the end of the block... | |
| 534 | + if ( false === $blockEndPos ) { | |
| 535 | + $blockEndPos = strlen($css) - 1; | |
| 536 | + } | |
| 518 | 537 | $nextBlockStartPos = strpos($css, '{', $blockStartPos + 1); |
| 519 | 538 | $ret .= substr($css, $substrOffset, $blockStartPos - $substrOffset); |
| 520 | 539 | |
| 521 | 540 | if ($nextBlockStartPos !== false && $nextBlockStartPos < $blockEndPos) { |
| @@ -585,10 +604,13 @@ | ||
| 585 | 604 | |
| 586 | 605 | // Shorten colors from rgb(51,102,153) to #336699, rgb(100%,0%,0%) to #ff0000 (sRGB color space) |
| 587 | 606 | // Shorten colors from hsl(0, 100%, 50%) to #ff0000 (sRGB color space) |
| 588 | 607 | // This makes it more likely that it'll get further compressed in the next step. |
| 608 | + // Only the plain three-component form is converted (comma- or space-separated). | |
| 609 | + // Colors with an alpha channel, i.e. rgb(0, 0, 0, .5) and rgb(0 0 0 / 50%), are | |
| 610 | + // left alone just like rgba()/hsla(): a 6-digit hex cannot carry the alpha. | |
| 589 | 611 | $body = preg_replace_callback( |
| 590 | - '/(rgb|hsl)\(([0-9,.% -]+)\)(.|$)/Si', | |
| 612 | + '/(rgb|hsl)\(\s*(-?[0-9.]+%?)\s*[, ]\s*(-?[0-9.]+%?)\s*[, ]\s*(-?[0-9.]+%?)\s*\)(.|$)/Si', | |
| 591 | 613 | array($this, 'shortenHslAndRgbToHexCallback'), |
| 592 | 614 | $body |
| 593 | 615 | ); |
| 594 | 616 | |
| @@ -599,8 +621,16 @@ | ||
| 599 | 621 | array($this, 'shortenHexColorsCallback'), |
| 600 | 622 | $body |
| 601 | 623 | ); |
| 602 | 624 | |
| 625 | + // Tokenize unquoted font names in order to hide them from | |
| 626 | + // color name replacements. | |
| 627 | + $body = preg_replace_callback( | |
| 628 | + $this->unquotedFontsRegex, | |
| 629 | + array($this, 'preserveUnquotedFontTokens'), | |
| 630 | + $body | |
| 631 | + ); | |
| 632 | + | |
| 603 | 633 | // Shorten long named colors with a shorter HEX counterpart: white -> #fff. |
| 604 | 634 | // Run at least 2 times to cover most cases |
| 605 | 635 | $body = preg_replace_callback( |
| 606 | 636 | array($this->namedToHexColorsRegex, $this->namedToHexColorsRegex), |
| @@ -607,8 +637,11 @@ | ||
| 607 | 637 | array($this, 'shortenNamedColorsCallback'), |
| 608 | 638 | $body |
| 609 | 639 | ); |
| 610 | 640 | |
| 641 | + // Restore unquoted font tokens now after colors have been changed. | |
| 642 | + $body = $this->restoreUnquotedFontTokens($body); | |
| 643 | + | |
| 611 | 644 | // Replace positive sign from numbers before the leading space is removed. |
| 612 | 645 | // +1.2em to 1.2em, +.8px to .8px, +2% to 2% |
| 613 | 646 | $body = preg_replace('/([ :,(])\+(\.?\d+)/S', '$1$2', $body); |
| 614 | 647 | |
| @@ -694,8 +727,18 @@ | ||
| 694 | 727 | |
| 695 | 728 | return $body; |
| 696 | 729 | } |
| 697 | 730 | |
| 731 | + private function preserveUnquotedFontTokens($matches) | |
| 732 | + { | |
| 733 | + return $this->registerUnquotedFontToken($matches[0]); | |
| 734 | + } | |
| 735 | + | |
| 736 | + private function restoreUnquotedFontTokens($body) | |
| 737 | + { | |
| 738 | + return strtr($body, $this->unquotedFontTokens); | |
| 739 | + } | |
| 740 | + | |
| 698 | 741 | /** |
| 699 | 742 | * Compresses At-rules and selectors. |
| 700 | 743 | * @param string $css the whole stylesheet with rule bodies tokenized. |
| 701 | 744 | * @return string |
| @@ -830,10 +873,10 @@ | ||
| 830 | 873 | */ |
| 831 | 874 | private function shortenHslAndRgbToHexCallback($matches) |
| 832 | 875 | { |
| 833 | 876 | $type = $matches[1]; |
| 834 | - $values = explode(',', $matches[2]); | |
| 835 | - $terminator = $matches[3]; | |
| 877 | + $values = array($matches[2], $matches[3], $matches[4]); | |
| 878 | + $terminator = $matches[5]; | |
| 836 | 879 | |
| 837 | 880 | if ($type === 'hsl') { |
| 838 | 881 | $values = Utils::hslToRgb($values); |
| 839 | 882 | } |