Changeset 2928234
- Timestamp:
- 06/19/2023 08:53:19 PM (3 years ago)
- Location:
- optimize-scripts-styles
- Files:
-
- 14 edited
-
assets/banner-1544x500.jpg (modified) (previous)
-
assets/banner-772x250.jpg (modified) (previous)
-
assets/icon-128x128.png (modified) (previous)
-
assets/icon-256x256.png (modified) (previous)
-
trunk/library/functions.php (modified) (1 diff)
-
trunk/library/includes/minify/src/CSS.php (modified) (19 diffs)
-
trunk/library/includes/minify/src/Exception.php (modified) (2 diffs)
-
trunk/library/includes/minify/src/Exceptions/BasicException.php (modified) (3 diffs)
-
trunk/library/includes/minify/src/Exceptions/FileImportException.php (modified) (2 diffs)
-
trunk/library/includes/minify/src/Exceptions/IOException.php (modified) (2 diffs)
-
trunk/library/includes/minify/src/JS.php (modified) (20 diffs)
-
trunk/library/includes/minify/src/Minify.php (modified) (16 diffs)
-
trunk/readme.txt (modified) (2 diffs)
-
trunk/sp-optimize-scripts.php (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
optimize-scripts-styles/trunk/library/functions.php
r2577281 r2928234 751 751 */ 752 752 // returns false if the file doesn't exist 753 function get_path_from_src( $src ) { 754 return realpath( '.' . str_replace( get_bloginfo('url'), '', preg_replace( '/\?.*/', '', $src ) ) ); 753 function get_path_from_src( $src ) { 754 // break the blog URL apart to replace all parts separately 755 $protocols = ['https://', 'http://']; 756 $blog_uri = str_replace( $protocols, '', get_bloginfo('url') ); 757 $path = str_replace( array_merge( $protocols, [$blog_uri] ), '', preg_replace( '/\?.*/', '', $src ) ); 758 // grab the file system path 759 $realpath = realpath( '.' . $path ); 760 return $realpath; 755 761 } 756 762 -
optimize-scripts-styles/trunk/library/includes/minify/src/CSS.php
r2251707 r2928234 1 1 <?php 2 2 3 /** 3 * CSS Minifier 4 * CSS Minifier. 4 5 * 5 6 * Please report bugs on https://github.com/matthiasmullie/minify/issues … … 13 14 14 15 use MatthiasMullie\Minify\Exceptions\FileImportException; 16 use MatthiasMullie\PathConverter\Converter; 15 17 use MatthiasMullie\PathConverter\ConverterInterface; 16 use MatthiasMullie\PathConverter\Converter;17 18 18 19 /** 19 * CSS minifier 20 * CSS minifier. 20 21 * 21 22 * Please report bugs on https://github.com/matthiasmullie/minify/issues 22 23 * 23 * @package Minify24 24 * @author Matthias Mullie <[email protected]> 25 25 * @author Tijs Verkoyen <[email protected]> … … 45 45 'svg' => 'data:image/svg+xml', 46 46 'woff' => 'data:application/x-font-woff', 47 'woff2' => 'data:application/x-font-woff2', 48 'avif' => 'data:image/avif', 49 'apng' => 'data:image/apng', 50 'webp' => 'data:image/webp', 47 51 'tif' => 'image/tiff', 48 52 'tiff' => 'image/tiff', … … 94 98 95 99 // add to top 96 $content = implode(';', $matches[2]) .';'.trim($content, ';');100 $content = implode(';', $matches[2]) . ';' . trim($content, ';'); 97 101 } 98 102 … … 103 107 * Combine CSS from import statements. 104 108 * 105 * @import's will be loaded and their content merged into the original file,106 * to save HTTP requests.109 * Import statements will be loaded and their content merged into the original 110 * file, to save HTTP requests. 107 111 * 108 112 * @param string $source The file to combine imports for … … 201 205 foreach ($matches as $match) { 202 206 // get the path for the file that will be imported 203 $importPath = dirname($source) .'/'.$match['path'];207 $importPath = dirname($source) . '/' . $match['path']; 204 208 205 209 // only replace the import with the content if we can grab the … … 212 216 // import chain. 213 217 if (in_array($importPath, $parents)) { 214 throw new FileImportException('Failed to import file "' .$importPath.'": circular reference detected.');218 throw new FileImportException('Failed to import file "' . $importPath . '": circular reference detected.'); 215 219 } 216 220 217 221 // grab referenced file & minify it (which may include importing 218 222 // yet other @import statements recursively) 219 $minifier = new s tatic($importPath);223 $minifier = new self($importPath); 220 224 $minifier->setMaxImportSize($this->maxImportSize); 221 225 $minifier->setImportExtensions($this->importExtensions); … … 224 228 // check if this is only valid for certain media 225 229 if (!empty($match['media'])) { 226 $importContent = '@media ' .$match['media'].'{'.$importContent.'}';230 $importContent = '@media ' . $match['media'] . '{' . $importContent . '}'; 227 231 } 228 232 … … 263 267 // get the path for the file that will be imported 264 268 $path = $match[2]; 265 $path = dirname($source) .'/'.$path;269 $path = dirname($source) . '/' . $path; 266 270 267 271 // only replace the import with the content if we're able to get … … 274 278 // build replacement 275 279 $search[] = $match[0]; 276 $replace[] = 'url(' .$this->importExtensions[$extension].';base64,'.$importContent.')';280 $replace[] = 'url(' . $this->importExtensions[$extension] . ';base64,' . $importContent . ')'; 277 281 } 278 282 } … … 290 294 * 291 295 * @param string[optional] $path Path to write the data to 292 * @param string[] $parents Parent paths, for circular reference checks296 * @param string[] $parents Parent paths, for circular reference checks 293 297 * 294 298 * @return string The minified data … … 308 312 $this->extractStrings(); 309 313 $this->stripComments(); 310 $this->extractCalcs(); 314 $this->extractMath(); 315 $this->extractCustomProperties(); 311 316 $css = $this->replace($css); 312 317 … … 465 470 $search[] = $match[0]; 466 471 if ($type === 'url') { 467 $replace[] = 'url(' .$url.')';472 $replace[] = 'url(' . $url . ')'; 468 473 } elseif ($type === 'import') { 469 $replace[] = '@import "' .$url.'"';474 $replace[] = '@import "' . $url . '"'; 470 475 } 471 476 } … … 526 531 527 532 return preg_replace_callback( 528 '/(?<=[: ])(' .implode('|', array_keys($colors)).')(?=[; }])/i',533 '/(?<=[: ])(' . implode('|', array_keys($colors)) . ')(?=[; }])/i', 529 534 function ($match) use ($colors) { 530 535 return $colors[strtoupper($match[0])]; … … 549 554 550 555 $callback = function ($match) use ($weights) { 551 return $match[1] .$weights[$match[2]];556 return $match[1] . $weights[$match[2]]; 552 557 }; 553 558 554 return preg_replace_callback('/(font-weight\s*:\s*)(' .implode('|', array_keys($weights)).')(?=[;}])/', $callback, $content);559 return preg_replace_callback('/(font-weight\s*:\s*)(' . implode('|', array_keys($weights)) . ')(?=[;}])/', $callback, $content); 555 560 } 556 561 … … 584 589 // 0%, potentially other units as well. Only stripping 'px' for now. 585 590 // @see https://github.com/matthiasmullie/minify/issues/60 586 $content = preg_replace('/' .$before.'(-?0*(\.0+)?)(?<=0)px'.$after.'/', '\\1', $content);591 $content = preg_replace('/' . $before . '(-?0*(\.0+)?)(?<=0)px' . $after . '/', '\\1', $content); 587 592 588 593 // strip 0-digits (.0 -> 0) 589 $content = preg_replace('/' .$before.'\.0+'.$units.'?'.$after.'/', '0\\1', $content);594 $content = preg_replace('/' . $before . '\.0+' . $units . '?' . $after . '/', '0\\1', $content); 590 595 // strip trailing 0: 50.10 -> 50.1, 50.10px -> 50.1px 591 $content = preg_replace('/' .$before.'(-?[0-9]+\.[0-9]+)0+'.$units.'?'.$after.'/', '\\1\\2', $content);596 $content = preg_replace('/' . $before . '(-?[0-9]+\.[0-9]+)0+' . $units . '?' . $after . '/', '\\1\\2', $content); 592 597 // strip trailing 0: 50.00 -> 50, 50.00px -> 50px 593 $content = preg_replace('/' .$before.'(-?[0-9]+)\.0+'.$units.'?'.$after.'/', '\\1\\2', $content);598 $content = preg_replace('/' . $before . '(-?[0-9]+)\.0+' . $units . '?' . $after . '/', '\\1\\2', $content); 594 599 // strip leading 0: 0.1 -> .1, 01.1 -> 1.1 595 $content = preg_replace('/' .$before.'(-?)0+([0-9]*\.[0-9]+)'.$units.'?'.$after.'/', '\\1\\2\\3', $content);600 $content = preg_replace('/' . $before . '(-?)0+([0-9]*\.[0-9]+)' . $units . '?' . $after . '/', '\\1\\2\\3', $content); 596 601 597 602 // strip negative zeroes (-0 -> 0) & truncate zeroes (00 -> 0) 598 $content = preg_replace('/' .$before.'-?0+'.$units.'?'.$after.'/', '0\\1', $content);603 $content = preg_replace('/' . $before . '-?0+' . $units . '?' . $after . '/', '0\\1', $content); 599 604 600 605 // IE doesn't seem to understand a unitless flex-basis value (correct - … … 628 633 protected function stripComments() 629 634 { 630 // PHP only supports $this inside anonymous functions since 5.4 631 $minifier = $this; 632 $callback = function ($match) use ($minifier) { 633 $count = count($minifier->extracted); 634 $placeholder = '/*'.$count.'*/'; 635 $minifier->extracted[$placeholder] = $match[0]; 636 637 return $placeholder; 638 }; 639 $this->registerPattern('/\n?\/\*(!|.*?@license|.*?@preserve).*?\*\/\n?/s', $callback); 640 641 $this->registerPattern('/\/\*.*?\*\//s', ''); 635 $this->stripMultilineComments(); 642 636 } 643 637 … … 670 664 // selectors like `div.weird- p` 671 665 $pseudos = array('nth-child', 'nth-last-child', 'nth-last-of-type', 'nth-of-type'); 672 $content = preg_replace('/:(' .implode('|', $pseudos).')\(\s*([+-]?)\s*(.+?)\s*([+-]?)\s*(.*?)\s*\)/', ':$1($2$3$4$5)', $content);666 $content = preg_replace('/:(' . implode('|', $pseudos) . ')\(\s*([+-]?)\s*(.+?)\s*([+-]?)\s*(.*?)\s*\)/', ':$1($2$3$4$5)', $content); 673 667 674 668 // remove semicolon/whitespace followed by closing bracket … … 679 673 680 674 /** 681 * Replace all `calc()` occurrences. 682 */ 683 protected function extractCalcs() 684 { 675 * Replace all occurrences of functions that may contain math, where 676 * whitespace around operators needs to be preserved (e.g. calc, clamp). 677 */ 678 protected function extractMath() 679 { 680 $functions = array('calc', 'clamp', 'min', 'max'); 681 $pattern = '/\b(' . implode('|', $functions) . ')(\(.+?)(?=$|;|})/m'; 682 685 683 // PHP only supports $this inside anonymous functions since 5.4 686 684 $minifier = $this; 687 $callback = function ($match) use ($minifier) { 688 $length = strlen($match[1]); 685 $callback = function ($match) use ($minifier, $pattern, &$callback) { 686 $function = $match[1]; 687 $length = strlen($match[2]); 689 688 $expr = ''; 690 689 $opened = 0; 691 690 692 for ($i = 0; $i < $length; $i++) { 693 $char = $match[1][$i]; 691 // the regular expression for extracting math has 1 significant problem: 692 // it can't determine the correct closing parenthesis... 693 // instead, it'll match a larger portion of code to where it's certain that 694 // the calc() musts have ended, and we'll figure out which is the correct 695 // closing parenthesis here, by counting how many have opened 696 for ($i = 0; $i < $length; ++$i) { 697 $char = $match[2][$i]; 694 698 $expr .= $char; 695 699 if ($char === '(') { 696 $opened++;700 ++$opened; 697 701 } elseif ($char === ')' && --$opened === 0) { 698 702 break; 699 703 } 700 704 } 701 $rest = str_replace($expr, '', $match[1]); 702 $expr = trim(substr($expr, 1, -1)); 703 705 706 // now that we've figured out where the calc() starts and ends, extract it 704 707 $count = count($minifier->extracted); 705 $placeholder = 'calc('.$count.')'; 706 $minifier->extracted[$placeholder] = 'calc('.$expr.')'; 707 708 return $placeholder.$rest; 708 $placeholder = 'math(' . $count . ')'; 709 $minifier->extracted[$placeholder] = $function . '(' . trim(substr($expr, 1, -1)) . ')'; 710 711 // and since we've captured more code than required, we may have some leftover 712 // calc() in here too - go recursive on the remaining but of code to go figure 713 // that out and extract what is needed 714 $rest = $minifier->str_replace_first($function . $expr, '', $match[0]); 715 $rest = preg_replace_callback($pattern, $callback, $rest); 716 717 return $placeholder . $rest; 709 718 }; 710 719 711 $this->registerPattern('/calc(\(.+?)(?=$|;|}|calc\()/', $callback); 712 $this->registerPattern('/calc(\(.+?)(?=$|;|}|calc\()/m', $callback); 720 $this->registerPattern($pattern, $callback); 721 } 722 723 /** 724 * Replace custom properties, whose values may be used in scenarios where 725 * we wouldn't want them to be minified (e.g. inside calc). 726 */ 727 protected function extractCustomProperties() 728 { 729 // PHP only supports $this inside anonymous functions since 5.4 730 $minifier = $this; 731 $this->registerPattern( 732 '/(?<=^|[;}{])\s*(--[^:;{}"\'\s]+)\s*:([^;{}]+)/m', 733 function ($match) use ($minifier) { 734 $placeholder = '--custom-' . count($minifier->extracted) . ':0'; 735 $minifier->extracted[$placeholder] = $match[1] . ':' . trim($match[2]); 736 737 return $placeholder; 738 } 739 ); 713 740 } 714 741 -
optimize-scripts-styles/trunk/library/includes/minify/src/Exception.php
r2251707 r2928234 1 1 <?php 2 2 3 /** 3 * Base Exception 4 * Base Exception. 4 5 * 5 6 * @deprecated Use Exceptions\BasicException instead … … 7 8 * @author Matthias Mullie <[email protected]> 8 9 */ 10 9 11 namespace MatthiasMullie\Minify; 10 12 11 13 /** 12 * Base Exception Class 14 * Base Exception Class. 15 * 13 16 * @deprecated Use Exceptions\BasicException instead 14 17 * 15 * @package Minify16 18 * @author Matthias Mullie <[email protected]> 17 19 */ -
optimize-scripts-styles/trunk/library/includes/minify/src/Exceptions/BasicException.php
r2251707 r2928234 1 1 <?php 2 2 3 /** 3 * Basic exception 4 * Basic exception. 4 5 * 5 6 * Please report bugs on https://github.com/matthiasmullie/minify/issues … … 9 10 * @license MIT License 10 11 */ 12 11 13 namespace MatthiasMullie\Minify\Exceptions; 12 14 … … 14 16 15 17 /** 16 * Basic Exception Class 18 * Basic Exception Class. 17 19 * 18 * @package Minify\Exception19 20 * @author Matthias Mullie <[email protected]> 20 21 */ -
optimize-scripts-styles/trunk/library/includes/minify/src/Exceptions/FileImportException.php
r2251707 r2928234 1 1 <?php 2 2 3 /** 3 * File Import Exception 4 * File Import Exception. 4 5 * 5 6 * Please report bugs on https://github.com/matthiasmullie/minify/issues … … 9 10 * @license MIT License 10 11 */ 12 11 13 namespace MatthiasMullie\Minify\Exceptions; 12 14 13 15 /** 14 * File Import Exception Class 16 * File Import Exception Class. 15 17 * 16 * @package Minify\Exception17 18 * @author Matthias Mullie <[email protected]> 18 19 */ -
optimize-scripts-styles/trunk/library/includes/minify/src/Exceptions/IOException.php
r2251707 r2928234 1 1 <?php 2 2 3 /** 3 * IO Exception 4 * IO Exception. 4 5 * 5 6 * Please report bugs on https://github.com/matthiasmullie/minify/issues … … 9 10 * @license MIT License 10 11 */ 12 11 13 namespace MatthiasMullie\Minify\Exceptions; 12 14 13 15 /** 14 * IO Exception Class 16 * IO Exception Class. 15 17 * 16 * @package Minify\Exception17 18 * @author Matthias Mullie <[email protected]> 18 19 */ -
optimize-scripts-styles/trunk/library/includes/minify/src/JS.php
r2251707 r2928234 1 1 <?php 2 2 3 /** 3 * JavaScript minifier 4 * JavaScript minifier. 4 5 * 5 6 * Please report bugs on https://github.com/matthiasmullie/minify/issues … … 9 10 * @license MIT License 10 11 */ 12 11 13 namespace MatthiasMullie\Minify; 12 14 13 15 /** 14 * JavaScript Minifier Class 16 * JavaScript Minifier Class. 15 17 * 16 18 * Please report bugs on https://github.com/matthiasmullie/minify/issues 17 19 * 18 * @package Minify19 20 * @author Matthias Mullie <[email protected]> 20 21 * @author Tijs Verkoyen <[email protected]> … … 30 31 * pattern modifier (/u) set. 31 32 * 33 * @internal 34 * 32 35 * @var string 33 36 */ … … 125 128 public function __construct() 126 129 { 127 call_user_func_array(array(' parent', '__construct'), func_get_args());128 129 $dataDir = __DIR__ .'/../data/js/';130 call_user_func_array(array('\\MatthiasMullie\Minify\\Minify', '__construct'), func_get_args()); 131 132 $dataDir = __DIR__ . '/../data/js/'; 130 133 $options = FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES; 131 $this->keywordsReserved = file($dataDir .'keywords_reserved.txt', $options);132 $this->keywordsBefore = file($dataDir .'keywords_before.txt', $options);133 $this->keywordsAfter = file($dataDir .'keywords_after.txt', $options);134 $this->operators = file($dataDir .'operators.txt', $options);135 $this->operatorsBefore = file($dataDir .'operators_before.txt', $options);136 $this->operatorsAfter = file($dataDir .'operators_after.txt', $options);134 $this->keywordsReserved = file($dataDir . 'keywords_reserved.txt', $options); 135 $this->keywordsBefore = file($dataDir . 'keywords_before.txt', $options); 136 $this->keywordsAfter = file($dataDir . 'keywords_after.txt', $options); 137 $this->operators = file($dataDir . 'operators.txt', $options); 138 $this->operatorsBefore = file($dataDir . 'operators_before.txt', $options); 139 $this->operatorsAfter = file($dataDir . 'operators_after.txt', $options); 137 140 } 138 141 … … 175 178 176 179 // combine js: separating the scripts by a ; 177 $content .= $js .";";180 $content .= $js . ';'; 178 181 } 179 182 … … 196 199 protected function stripComments() 197 200 { 198 // PHP only supports $this inside anonymous functions since 5.4 199 $minifier = $this; 200 $callback = function ($match) use ($minifier) { 201 $count = count($minifier->extracted); 202 $placeholder = '/*'.$count.'*/'; 203 $minifier->extracted[$placeholder] = $match[0]; 204 205 return $placeholder; 206 }; 207 // multi-line comments 208 $this->registerPattern('/\n?\/\*(!|.*?@license|.*?@preserve).*?\*\/\n?/s', $callback); 209 $this->registerPattern('/\/\*.*?\*\//s', ''); 201 $this->stripMultilineComments(); 210 202 211 203 // single-line comments … … 236 228 $callback = function ($match) use ($minifier) { 237 229 $count = count($minifier->extracted); 238 $placeholder = '"' .$count.'"';230 $placeholder = '"' . $count . '"'; 239 231 $minifier->extracted[$placeholder] = $match[0]; 240 232 … … 255 247 // likely part of a division, not a regex) 256 248 $keywords = array('do', 'in', 'new', 'else', 'throw', 'yield', 'delete', 'return', 'typeof'); 257 $before = '( [=:,;\+\-\*\/\}\(\{\[&\|!]|^|'.implode('|', $keywords).')\s*';249 $before = '(^|[=:,;\+\-\*\?\/\}\(\{\[&\|!]|' . implode('|', $keywords) . ')\s*'; 258 250 $propertiesAndMethods = array( 259 251 // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp#Properties_2 … … 275 267 $delimiters = array_fill(0, count($propertiesAndMethods), '/'); 276 268 $propertiesAndMethods = array_map('preg_quote', $propertiesAndMethods, $delimiters); 277 $after = '(?=\s*([\.,; \)\}&\|+]|\/\/|$|\.('.implode('|', $propertiesAndMethods).')))';278 $this->registerPattern('/' .$before.'\K'.$pattern.$after.'/', $callback);269 $after = '(?=\s*([\.,;:\)\}&\|+]|\/\/|$|\.(' . implode('|', $propertiesAndMethods) . ')))'; 270 $this->registerPattern('/' . $before . '\K' . $pattern . $after . '/', $callback); 279 271 280 272 // regular expressions following a `)` are rather annoying to detect... … … 290 282 // it's quite likely not a regex 291 283 $before = '\)\s*'; 292 $after = '(?=\s*\.(' .implode('|', $propertiesAndMethods).'))';293 $this->registerPattern('/' .$before.'\K'.$pattern.$after.'/', $callback);284 $after = '(?=\s*\.(' . implode('|', $propertiesAndMethods) . '))'; 285 $this->registerPattern('/' . $before . '\K' . $pattern . $after . '/', $callback); 294 286 295 287 // 1 more edge case: a regex can be followed by a lot more operators or … … 299 291 $operators = $this->getOperatorsForRegex($this->operatorsBefore, '/'); 300 292 $operators += $this->getOperatorsForRegex($this->keywordsReserved, '/'); 301 $after = '(?=\s*\n\s*(' .implode('|', $operators).'))';302 $this->registerPattern('/' .$pattern.$after.'/', $callback);293 $after = '(?=\s*\n\s*(' . implode('|', $operators) . '))'; 294 $this->registerPattern('/' . $pattern . $after . '/', $callback); 303 295 } 304 296 … … 344 336 $content = preg_replace( 345 337 array( 346 '/(' .implode('|', $operatorsBefore).')\s+/',347 '/\s+(' .implode('|', $operatorsAfter).')/',338 '/(' . implode('|', $operatorsBefore) . ')\s+/', 339 '/\s+(' . implode('|', $operatorsAfter) . ')/', 348 340 ), 349 341 '\\1', … … 362 354 363 355 // collapse whitespace around reserved words into single space 364 $content = preg_replace('/(^|[;\}\s])\K(' .implode('|', $keywordsBefore).')\s+/', '\\2 ', $content);365 $content = preg_replace('/\s+(' .implode('|', $keywordsAfter).')(?=([;\{\s]|$))/', ' \\1', $content);356 $content = preg_replace('/(^|[;\}\s])\K(' . implode('|', $keywordsBefore) . ')\s+/', '\\2 ', $content); 357 $content = preg_replace('/\s+(' . implode('|', $keywordsAfter) . ')(?=([;\{\s]|$))/', ' \\1', $content); 366 358 367 359 /* … … 373 365 $operatorsDiffBefore = array_diff($operators, $operatorsBefore); 374 366 $operatorsDiffAfter = array_diff($operators, $operatorsAfter); 375 $content = preg_replace('/(' .implode('|', $operatorsDiffBefore).')[^\S\n]+/', '\\1', $content);376 $content = preg_replace('/[^\S\n]+(' .implode('|', $operatorsDiffAfter).')/', '\\1', $content);367 $content = preg_replace('/(' . implode('|', $operatorsDiffBefore) . ')[^\S\n]+/', '\\1', $content); 368 $content = preg_replace('/[^\S\n]+(' . implode('|', $operatorsDiffAfter) . ')/', '\\1', $content); 377 369 378 370 /* … … 406 398 * I'm going to double that semicolon (if any) so after the next line, 407 399 * which strips semicolons here & there, we're still left with this one. 408 */ 409 $content = preg_replace('/(for\([^;\{]*;[^;\{]*;[^;\{]*\));(\}|$)/s', '\\1;;\\2', $content); 400 * Note the special recursive construct in the three inner parts of the for: 401 * (\{([^\{\}]*(?-2))*[^\{\}]*\})? - it is intended to match inline 402 * functions bodies, e.g.: i<arr.map(function(e){return e}).length. 403 * Also note that the construct is applied only once and multiplied 404 * for each part of the for, otherwise it risks a catastrophic backtracking. 405 * The limitation is that it will not allow closures in more than one 406 * of the three parts for a specific for() case. 407 * REGEX throwing catastrophic backtracking: $content = preg_replace('/(for\([^;\{]*(\{([^\{\}]*(?-2))*[^\{\}]*\})?[^;\{]*;[^;\{]*(\{([^\{\}]*(?-2))*[^\{\}]*\})?[^;\{]*;[^;\{]*(\{([^\{\}]*(?-2))*[^\{\}]*\})?[^;\{]*\));(\}|$)/s', '\\1;;\\8', $content); 408 */ 409 $content = preg_replace('/(for\((?:[^;\{]*|[^;\{]*function[^;\{]*(\{([^\{\}]*(?-2))*[^\{\}]*\})?[^;\{]*);[^;\{]*;[^;\{]*\));(\}|$)/s', '\\1;;\\4', $content); 410 $content = preg_replace('/(for\([^;\{]*;(?:[^;\{]*|[^;\{]*function[^;\{]*(\{([^\{\}]*(?-2))*[^\{\}]*\})?[^;\{]*);[^;\{]*\));(\}|$)/s', '\\1;;\\4', $content); 411 $content = preg_replace('/(for\([^;\{]*;[^;\{]*;(?:[^;\{]*|[^;\{]*function[^;\{]*(\{([^\{\}]*(?-2))*[^\{\}]*\})?[^;\{]*)\));(\}|$)/s', '\\1;;\\4', $content); 412 410 413 $content = preg_replace('/(for\([^;\{]+\s+in\s+[^;\{]+\));(\}|$)/s', '\\1;;\\2', $content); 414 415 /* 416 * Do the same for the if's that don't have a body but are followed by ;} 417 */ 418 $content = preg_replace('/(\bif\s*\([^{;]*\));\}/s', '\\1;;}', $content); 419 411 420 /* 412 421 * Below will also keep `;` after a `do{}while();` along with `while();` … … 466 475 // don't confuse = with other assignment shortcuts (e.g. +=) 467 476 $chars = preg_quote('+-*\=<>%&|', $delimiter); 468 $operators['='] = '(?<![' .$chars.'])\=';477 $operators['='] = '(?<![' . $chars . '])\='; 469 478 470 479 return $operators; … … 488 497 // add word boundaries 489 498 array_walk($keywords, function ($value) { 490 return '\b' .$value.'\b';499 return '\b' . $value . '\b'; 491 500 }); 492 501 … … 525 534 * is not a valid character there. 526 535 */ 527 if (!preg_match('/^' .$minifier::REGEX_VARIABLE.'$/u', $property)) {536 if (!preg_match('/^' . $minifier::REGEX_VARIABLE . '$/u', $property)) { 528 537 return $match[0]; 529 538 } 530 539 531 return '.' .$property;540 return '.' . $property; 532 541 }; 533 542 … … 550 559 */ 551 560 $keywords = $this->getKeywordsForRegex($keywords); 552 $keywords = '(?<!' .implode(')(?<!', $keywords).')';553 554 return preg_replace_callback('/(?<=' .$previousChar.'|\])'.$keywords.'\[\s*(([\'"])[0-9]+\\2)\s*\]/u', $callback, $content);561 $keywords = '(?<!' . implode(')(?<!', $keywords) . ')'; 562 563 return preg_replace_callback('/(?<=' . $previousChar . '|\])' . $keywords . '\[\s*(([\'"])[0-9]+\\2)\s*\]/u', $callback, $content); 555 564 } 556 565 … … 576 585 } 577 586 578 return $match[1] .($match[2] === 'true' ? '!0' : '!1');587 return $match[1] . ($match[2] === 'true' ? '!0' : '!1'); 579 588 }; 580 589 $content = preg_replace_callback('/(^|.\s*)\b(true|false)\b(?!:)/', $callback, $content); -
optimize-scripts-styles/trunk/library/includes/minify/src/Minify.php
r2251707 r2928234 1 1 <?php 2 2 3 /** 3 * Abstract minifier class 4 * Abstract minifier class. 4 5 * 5 6 * Please report bugs on https://github.com/matthiasmullie/minify/issues … … 9 10 * @license MIT License 10 11 */ 12 11 13 namespace MatthiasMullie\Minify; 12 14 … … 19 21 * Please report bugs on https://github.com/matthiasmullie/minify/issues 20 22 * 21 * @package Minify22 23 * @author Matthias Mullie <[email protected]> 23 24 * @copyright Copyright (c) 2012, Matthias Mullie. All rights reserved … … 45 46 * without having to worry about potential "code-like" characters inside. 46 47 * 48 * @internal 49 * 47 50 * @var string[] 48 51 */ … … 106 109 * 107 110 * @return static 108 * 111 * 109 112 * @throws IOException 110 113 */ … … 129 132 // check if we can read the file 130 133 if (!$this->canImportFile($path)) { 131 throw new IOException('The file "' .$path.'" could not be opened for reading. Check if PHP has enough permissions.');134 throw new IOException('The file "' . $path . '" could not be opened for reading. Check if PHP has enough permissions.'); 132 135 } 133 136 … … 244 247 * Register a pattern to execute against the source content. 245 248 * 249 * If $replacement is a string, it must be plain text. Placeholders like $1 or \2 don't work. 250 * If you need that functionality, use a callback instead. 251 * 246 252 * @param string $pattern PCRE pattern 247 253 * @param string|callable $replacement Replacement value for matched pattern … … 253 259 254 260 $this->patterns[] = array($pattern, $replacement); 261 } 262 263 /** 264 * Both JS and CSS use the same form of multi-line comment, so putting the common code here. 265 */ 266 protected function stripMultilineComments() 267 { 268 // First extract comments we want to keep, so they can be restored later 269 // PHP only supports $this inside anonymous functions since 5.4 270 $minifier = $this; 271 $callback = function ($match) use ($minifier) { 272 $count = count($minifier->extracted); 273 $placeholder = '/*'.$count.'*/'; 274 $minifier->extracted[$placeholder] = $match[0]; 275 276 return $placeholder; 277 }; 278 $this->registerPattern('/ 279 # optional newline 280 \n? 281 282 # start comment 283 \/\* 284 285 # comment content 286 (?: 287 # either starts with an ! 288 ! 289 | 290 # or, after some number of characters which do not end the comment 291 (?:(?!\*\/).)*? 292 293 # there is either a @license or @preserve tag 294 @(?:license|preserve) 295 ) 296 297 # then match to the end of the comment 298 .*?\*\/\n? 299 300 /ixs', $callback); 301 302 // Then strip all other comments 303 $this->registerPattern('/\/\*.*?\*\//s', ''); 255 304 } 256 305 … … 269 318 protected function replace($content) 270 319 { 271 $processed = ''; 320 $contentLength = strlen($content); 321 $output = ''; 322 $processedOffset = 0; 272 323 $positions = array_fill(0, count($this->patterns), -1); 273 324 $matches = array(); 274 325 275 while ($ content) {326 while ($processedOffset < $contentLength) { 276 327 // find first match for all patterns 277 328 foreach ($this->patterns as $i => $pattern) { … … 286 337 // no need to re-run matches that are still in the part of the 287 338 // content that hasn't been processed 288 if ($positions[$i] >= 0) {339 if ($positions[$i] >= $processedOffset) { 289 340 continue; 290 341 } 291 342 292 343 $match = null; 293 if (preg_match($pattern, $content, $match, PREG_OFFSET_CAPTURE )) {344 if (preg_match($pattern, $content, $match, PREG_OFFSET_CAPTURE, $processedOffset)) { 294 345 $matches[$i] = $match; 295 346 … … 308 359 // no more matches to find: everything's been processed, break out 309 360 if (!$matches) { 310 $processed .= $content; 361 // output the remaining content 362 $output .= substr($content, $processedOffset); 311 363 break; 312 364 } … … 315 367 // only want to execute that one, since we're unsure if what the 316 368 // other found was not inside what the first found) 317 $ discardLength= min($positions);318 $firstPattern = array_search($ discardLength, $positions);319 $match = $matches[$firstPattern] [0][0];369 $matchOffset = min($positions); 370 $firstPattern = array_search($matchOffset, $positions); 371 $match = $matches[$firstPattern]; 320 372 321 373 // execute the pattern that matches earliest in the content string 322 list($pattern, $replacement) = $this->patterns[$firstPattern]; 323 $replacement = $this->replacePattern($pattern, $replacement, $content); 324 325 // figure out which part of the string was unmatched; that's the 326 // part we'll execute the patterns on again next 327 $content = (string) substr($content, $discardLength); 328 $unmatched = (string) substr($content, strpos($content, $match) + strlen($match)); 329 330 // move the replaced part to $processed and prepare $content to 331 // again match batch of patterns against 332 $processed .= substr($replacement, 0, strlen($replacement) - strlen($unmatched)); 333 $content = $unmatched; 334 335 // first match has been replaced & that content is to be left alone, 336 // the next matches will start after this replacement, so we should 337 // fix their offsets 338 foreach ($positions as $i => $position) { 339 $positions[$i] -= $discardLength + strlen($match); 340 } 341 } 342 343 return $processed; 344 } 345 346 /** 347 * This is where a pattern is matched against $content and the matches 348 * are replaced by their respective value. 349 * This function will be called plenty of times, where $content will always 350 * move up 1 character. 351 * 352 * @param string $pattern Pattern to match 374 list(, $replacement) = $this->patterns[$firstPattern]; 375 376 // add the part of the input between $processedOffset and the first match; 377 // that content wasn't matched by anything 378 $output .= substr($content, $processedOffset, $matchOffset - $processedOffset); 379 // add the replacement for the match 380 $output .= $this->executeReplacement($replacement, $match); 381 // advance $processedOffset past the match 382 $processedOffset = $matchOffset + strlen($match[0][0]); 383 } 384 385 return $output; 386 } 387 388 /** 389 * If $replacement is a callback, execute it, passing in the match data. 390 * If it's a string, just pass it through. 391 * 353 392 * @param string|callable $replacement Replacement value 354 * @param string $content Content to match pattern against393 * @param array $match Match data, in PREG_OFFSET_CAPTURE form 355 394 * 356 395 * @return string 357 396 */ 358 protected function replacePattern($pattern, $replacement, $content) 359 { 360 if (is_callable($replacement)) { 361 return preg_replace_callback($pattern, $replacement, $content, 1, $count); 362 } else { 363 return preg_replace($pattern, $replacement, $content, 1, $count); 364 } 397 protected function executeReplacement($replacement, $match) 398 { 399 if (!is_callable($replacement)) { 400 return $replacement; 401 } 402 // convert $match from the PREG_OFFSET_CAPTURE form to the form the callback expects 403 foreach ($match as &$matchItem) { 404 $matchItem = $matchItem[0]; 405 } 406 407 return $replacement($match); 365 408 } 366 409 … … 396 439 397 440 $count = count($minifier->extracted); 398 $placeholder = $match[1] .$placeholderPrefix.$count.$match[1];399 $minifier->extracted[$placeholder] = $match[1] .$match[2].$match[1];441 $placeholder = $match[1] . $placeholderPrefix . $count . $match[1]; 442 $minifier->extracted[$placeholder] = $match[1] . $match[2] . $match[1]; 400 443 401 444 return $placeholder; … … 414 457 * escaped (times 2) 415 458 */ 416 $this->registerPattern('/([' .$chars.'])(.*?(?<!\\\\)(\\\\\\\\)*+)\\1/s', $callback);459 $this->registerPattern('/([' . $chars . '])(.*?(?<!\\\\)(\\\\\\\\)*+)\\1/s', $callback); 417 460 } 418 461 … … 473 516 protected function openFileForWriting($path) 474 517 { 475 if ( ($handler = @fopen($path, 'w')) === false) {476 throw new IOException('The file "' .$path.'" could not be opened for writing. Check if PHP has enough permissions.');518 if ($path === '' || ($handler = @fopen($path, 'w')) === false) { 519 throw new IOException('The file "' . $path . '" could not be opened for writing. Check if PHP has enough permissions.'); 477 520 } 478 521 … … 491 534 protected function writeToFile($handler, $content, $path = '') 492 535 { 493 if (($result = @fwrite($handler, $content)) === false || ($result < strlen($content))) { 494 throw new IOException('The file "'.$path.'" could not be written to. Check your disk space and file permissions.'); 495 } 536 if ( 537 !is_resource($handler) || 538 ($result = @fwrite($handler, $content)) === false || 539 ($result < strlen($content)) 540 ) { 541 throw new IOException('The file "' . $path . '" could not be written to. Check your disk space and file permissions.'); 542 } 543 } 544 545 protected static function str_replace_first($search, $replace, $subject) 546 { 547 $pos = strpos($subject, $search); 548 if ($pos !== false) { 549 return substr_replace($subject, $replace, $pos, strlen($search)); 550 } 551 552 return $subject; 496 553 } 497 554 } -
optimize-scripts-styles/trunk/readme.txt
r2577281 r2928234 4 4 Tags: scripts, styles, optimize, optimization, minify, compress, seo, performance, combine 5 5 Requires at least: 4.0 6 Tested up to: 5.87 Requires PHP: 5.68 Stable tag: 1.9. 36 Tested up to: 6.2 7 Requires PHP: 7.4 8 Stable tag: 1.9.4 9 9 License: GPLv2 or later 10 10 License URI: https://www.gnu.org/licenses/gpl-2.0.html … … 90 90 91 91 == Changelog == 92 93 = 1.9.4 = 94 * PHP 8.2 compatibility 95 * Updated minify package to 1.3.71 96 * Fixed a bug with stylesheet dependencies 92 97 93 98 = 1.9.3 = -
optimize-scripts-styles/trunk/sp-optimize-scripts.php
r2577281 r2928234 4 4 * Plugin URI: https://www.seismicpixels.com/optimize-scripts-styles-for-wordpress/ 5 5 * Description: Provides a quick way to combine and minify all scripts and styles and cache them in your content folder. 6 * Version: 1.9. 36 * Version: 1.9.4 7 7 * Author: Seismic Pixels 8 8 * Author URI: https://www.seismicpixels.com 9 * Copyright 202 1Sean Michaud - Seismic Pixels, LLC9 * Copyright 2023 Sean Michaud - Seismic Pixels, LLC 10 10 */ 11 11 12 12 global $spos_version; 13 $spos_version = '1.9. 3';13 $spos_version = '1.9.4'; 14 14 15 15 global $spos_settings;
Note: See TracChangeset
for help on using the changeset viewer.