Plugin Directory

Changeset 2928234


Ignore:
Timestamp:
06/19/2023 08:53:19 PM (3 years ago)
Author:
seismicpixels
Message:

Updating to 1.9.4

Location:
optimize-scripts-styles
Files:
14 edited

Legend:

Unmodified
Added
Removed
  • optimize-scripts-styles/trunk/library/functions.php

    r2577281 r2928234  
    751751 */
    752752// 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 ) ) );
     753function 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;
    755761}
    756762
  • optimize-scripts-styles/trunk/library/includes/minify/src/CSS.php

    r2251707 r2928234  
    11<?php
     2
    23/**
    3  * CSS Minifier
     4 * CSS Minifier.
    45 *
    56 * Please report bugs on https://github.com/matthiasmullie/minify/issues
     
    1314
    1415use MatthiasMullie\Minify\Exceptions\FileImportException;
     16use MatthiasMullie\PathConverter\Converter;
    1517use MatthiasMullie\PathConverter\ConverterInterface;
    16 use MatthiasMullie\PathConverter\Converter;
    1718
    1819/**
    19  * CSS minifier
     20 * CSS minifier.
    2021 *
    2122 * Please report bugs on https://github.com/matthiasmullie/minify/issues
    2223 *
    23  * @package Minify
    2424 * @author Matthias Mullie <[email protected]>
    2525 * @author Tijs Verkoyen <[email protected]>
     
    4545        'svg' => 'data:image/svg+xml',
    4646        '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',
    4751        'tif' => 'image/tiff',
    4852        'tiff' => 'image/tiff',
     
    9498
    9599            // add to top
    96             $content = implode(';', $matches[2]).';'.trim($content, ';');
     100            $content = implode(';', $matches[2]) . ';' . trim($content, ';');
    97101        }
    98102
     
    103107     * Combine CSS from import statements.
    104108     *
    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.
    107111     *
    108112     * @param string   $source  The file to combine imports for
     
    201205        foreach ($matches as $match) {
    202206            // get the path for the file that will be imported
    203             $importPath = dirname($source).'/'.$match['path'];
     207            $importPath = dirname($source) . '/' . $match['path'];
    204208
    205209            // only replace the import with the content if we can grab the
     
    212216            // import chain.
    213217            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.');
    215219            }
    216220
    217221            // grab referenced file & minify it (which may include importing
    218222            // yet other @import statements recursively)
    219             $minifier = new static($importPath);
     223            $minifier = new self($importPath);
    220224            $minifier->setMaxImportSize($this->maxImportSize);
    221225            $minifier->setImportExtensions($this->importExtensions);
     
    224228            // check if this is only valid for certain media
    225229            if (!empty($match['media'])) {
    226                 $importContent = '@media '.$match['media'].'{'.$importContent.'}';
     230                $importContent = '@media ' . $match['media'] . '{' . $importContent . '}';
    227231            }
    228232
     
    263267                // get the path for the file that will be imported
    264268                $path = $match[2];
    265                 $path = dirname($source).'/'.$path;
     269                $path = dirname($source) . '/' . $path;
    266270
    267271                // only replace the import with the content if we're able to get
     
    274278                    // build replacement
    275279                    $search[] = $match[0];
    276                     $replace[] = 'url('.$this->importExtensions[$extension].';base64,'.$importContent.')';
     280                    $replace[] = 'url(' . $this->importExtensions[$extension] . ';base64,' . $importContent . ')';
    277281                }
    278282            }
     
    290294     *
    291295     * @param string[optional] $path    Path to write the data to
    292      * @param string[]         $parents Parent paths, for circular reference checks
     296     * @param string[] $parents Parent paths, for circular reference checks
    293297     *
    294298     * @return string The minified data
     
    308312            $this->extractStrings();
    309313            $this->stripComments();
    310             $this->extractCalcs();
     314            $this->extractMath();
     315            $this->extractCustomProperties();
    311316            $css = $this->replace($css);
    312317
     
    465470            $search[] = $match[0];
    466471            if ($type === 'url') {
    467                 $replace[] = 'url('.$url.')';
     472                $replace[] = 'url(' . $url . ')';
    468473            } elseif ($type === 'import') {
    469                 $replace[] = '@import "'.$url.'"';
     474                $replace[] = '@import "' . $url . '"';
    470475            }
    471476        }
     
    526531
    527532        return preg_replace_callback(
    528             '/(?<=[: ])('.implode('|', array_keys($colors)).')(?=[; }])/i',
     533            '/(?<=[: ])(' . implode('|', array_keys($colors)) . ')(?=[; }])/i',
    529534            function ($match) use ($colors) {
    530535                return $colors[strtoupper($match[0])];
     
    549554
    550555        $callback = function ($match) use ($weights) {
    551             return $match[1].$weights[$match[2]];
     556            return $match[1] . $weights[$match[2]];
    552557        };
    553558
    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);
    555560    }
    556561
     
    584589        // 0%, potentially other units as well. Only stripping 'px' for now.
    585590        // @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);
    587592
    588593        // 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);
    590595        // 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);
    592597        // 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);
    594599        // 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);
    596601
    597602        // 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);
    599604
    600605        // IE doesn't seem to understand a unitless flex-basis value (correct -
     
    628633    protected function stripComments()
    629634    {
    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();
    642636    }
    643637
     
    670664        // selectors like `div.weird- p`
    671665        $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);
    673667
    674668        // remove semicolon/whitespace followed by closing bracket
     
    679673
    680674    /**
    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
    685683        // PHP only supports $this inside anonymous functions since 5.4
    686684        $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]);
    689688            $expr = '';
    690689            $opened = 0;
    691690
    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];
    694698                $expr .= $char;
    695699                if ($char === '(') {
    696                     $opened++;
     700                    ++$opened;
    697701                } elseif ($char === ')' && --$opened === 0) {
    698702                    break;
    699703                }
    700704            }
    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
    704707            $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;
    709718        };
    710719
    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        );
    713740    }
    714741
  • optimize-scripts-styles/trunk/library/includes/minify/src/Exception.php

    r2251707 r2928234  
    11<?php
     2
    23/**
    3  * Base Exception
     4 * Base Exception.
    45 *
    56 * @deprecated Use Exceptions\BasicException instead
     
    78 * @author Matthias Mullie <[email protected]>
    89 */
     10
    911namespace MatthiasMullie\Minify;
    1012
    1113/**
    12  * Base Exception Class
     14 * Base Exception Class.
     15 *
    1316 * @deprecated Use Exceptions\BasicException instead
    1417 *
    15  * @package Minify
    1618 * @author Matthias Mullie <[email protected]>
    1719 */
  • optimize-scripts-styles/trunk/library/includes/minify/src/Exceptions/BasicException.php

    r2251707 r2928234  
    11<?php
     2
    23/**
    3  * Basic exception
     4 * Basic exception.
    45 *
    56 * Please report bugs on https://github.com/matthiasmullie/minify/issues
     
    910 * @license MIT License
    1011 */
     12
    1113namespace MatthiasMullie\Minify\Exceptions;
    1214
     
    1416
    1517/**
    16  * Basic Exception Class
     18 * Basic Exception Class.
    1719 *
    18  * @package Minify\Exception
    1920 * @author Matthias Mullie <[email protected]>
    2021 */
  • optimize-scripts-styles/trunk/library/includes/minify/src/Exceptions/FileImportException.php

    r2251707 r2928234  
    11<?php
     2
    23/**
    3  * File Import Exception
     4 * File Import Exception.
    45 *
    56 * Please report bugs on https://github.com/matthiasmullie/minify/issues
     
    910 * @license MIT License
    1011 */
     12
    1113namespace MatthiasMullie\Minify\Exceptions;
    1214
    1315/**
    14  * File Import Exception Class
     16 * File Import Exception Class.
    1517 *
    16  * @package Minify\Exception
    1718 * @author Matthias Mullie <[email protected]>
    1819 */
  • optimize-scripts-styles/trunk/library/includes/minify/src/Exceptions/IOException.php

    r2251707 r2928234  
    11<?php
     2
    23/**
    3  * IO Exception
     4 * IO Exception.
    45 *
    56 * Please report bugs on https://github.com/matthiasmullie/minify/issues
     
    910 * @license MIT License
    1011 */
     12
    1113namespace MatthiasMullie\Minify\Exceptions;
    1214
    1315/**
    14  * IO Exception Class
     16 * IO Exception Class.
    1517 *
    16  * @package Minify\Exception
    1718 * @author Matthias Mullie <[email protected]>
    1819 */
  • optimize-scripts-styles/trunk/library/includes/minify/src/JS.php

    r2251707 r2928234  
    11<?php
     2
    23/**
    3  * JavaScript minifier
     4 * JavaScript minifier.
    45 *
    56 * Please report bugs on https://github.com/matthiasmullie/minify/issues
     
    910 * @license MIT License
    1011 */
     12
    1113namespace MatthiasMullie\Minify;
    1214
    1315/**
    14  * JavaScript Minifier Class
     16 * JavaScript Minifier Class.
    1517 *
    1618 * Please report bugs on https://github.com/matthiasmullie/minify/issues
    1719 *
    18  * @package Minify
    1920 * @author Matthias Mullie <[email protected]>
    2021 * @author Tijs Verkoyen <[email protected]>
     
    3031     * pattern modifier (/u) set.
    3132     *
     33     * @internal
     34     *
    3235     * @var string
    3336     */
     
    125128    public function __construct()
    126129    {
    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/';
    130133        $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);
    137140    }
    138141
     
    175178
    176179            // combine js: separating the scripts by a ;
    177             $content .= $js.";";
     180            $content .= $js . ';';
    178181        }
    179182
     
    196199    protected function stripComments()
    197200    {
    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();
    210202
    211203        // single-line comments
     
    236228        $callback = function ($match) use ($minifier) {
    237229            $count = count($minifier->extracted);
    238             $placeholder = '"'.$count.'"';
     230            $placeholder = '"' . $count . '"';
    239231            $minifier->extracted[$placeholder] = $match[0];
    240232
     
    255247        // likely part of a division, not a regex)
    256248        $keywords = array('do', 'in', 'new', 'else', 'throw', 'yield', 'delete', 'return',  'typeof');
    257         $before = '([=:,;\+\-\*\/\}\(\{\[&\|!]|^|'.implode('|', $keywords).')\s*';
     249        $before = '(^|[=:,;\+\-\*\?\/\}\(\{\[&\|!]|' . implode('|', $keywords) . ')\s*';
    258250        $propertiesAndMethods = array(
    259251            // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp#Properties_2
     
    275267        $delimiters = array_fill(0, count($propertiesAndMethods), '/');
    276268        $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);
    279271
    280272        // regular expressions following a `)` are rather annoying to detect...
     
    290282        // it's quite likely not a regex
    291283        $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);
    294286
    295287        // 1 more edge case: a regex can be followed by a lot more operators or
     
    299291        $operators = $this->getOperatorsForRegex($this->operatorsBefore, '/');
    300292        $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);
    303295    }
    304296
     
    344336        $content = preg_replace(
    345337            array(
    346                 '/('.implode('|', $operatorsBefore).')\s+/',
    347                 '/\s+('.implode('|', $operatorsAfter).')/',
     338                '/(' . implode('|', $operatorsBefore) . ')\s+/',
     339                '/\s+(' . implode('|', $operatorsAfter) . ')/',
    348340            ),
    349341            '\\1',
     
    362354
    363355        // 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);
    366358
    367359        /*
     
    373365        $operatorsDiffBefore = array_diff($operators, $operatorsBefore);
    374366        $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);
    377369
    378370        /*
     
    406398         * I'm going to double that semicolon (if any) so after the next line,
    407399         * 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
    410413        $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
    411420        /*
    412421         * Below will also keep `;` after a `do{}while();` along with `while();`
     
    466475        // don't confuse = with other assignment shortcuts (e.g. +=)
    467476        $chars = preg_quote('+-*\=<>%&|', $delimiter);
    468         $operators['='] = '(?<!['.$chars.'])\=';
     477        $operators['='] = '(?<![' . $chars . '])\=';
    469478
    470479        return $operators;
     
    488497        // add word boundaries
    489498        array_walk($keywords, function ($value) {
    490             return '\b'.$value.'\b';
     499            return '\b' . $value . '\b';
    491500        });
    492501
     
    525534             * is not a valid character there.
    526535             */
    527             if (!preg_match('/^'.$minifier::REGEX_VARIABLE.'$/u', $property)) {
     536            if (!preg_match('/^' . $minifier::REGEX_VARIABLE . '$/u', $property)) {
    528537                return $match[0];
    529538            }
    530539
    531             return '.'.$property;
     540            return '.' . $property;
    532541        };
    533542
     
    550559         */
    551560        $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);
    555564    }
    556565
     
    576585            }
    577586
    578             return $match[1].($match[2] === 'true' ? '!0' : '!1');
     587            return $match[1] . ($match[2] === 'true' ? '!0' : '!1');
    579588        };
    580589        $content = preg_replace_callback('/(^|.\s*)\b(true|false)\b(?!:)/', $callback, $content);
  • optimize-scripts-styles/trunk/library/includes/minify/src/Minify.php

    r2251707 r2928234  
    11<?php
     2
    23/**
    3  * Abstract minifier class
     4 * Abstract minifier class.
    45 *
    56 * Please report bugs on https://github.com/matthiasmullie/minify/issues
     
    910 * @license MIT License
    1011 */
     12
    1113namespace MatthiasMullie\Minify;
    1214
     
    1921 * Please report bugs on https://github.com/matthiasmullie/minify/issues
    2022 *
    21  * @package Minify
    2223 * @author Matthias Mullie <[email protected]>
    2324 * @copyright Copyright (c) 2012, Matthias Mullie. All rights reserved
     
    4546     * without having to worry about potential "code-like" characters inside.
    4647     *
     48     * @internal
     49     *
    4750     * @var string[]
    4851     */
     
    106109     *
    107110     * @return static
    108      * 
     111     *
    109112     * @throws IOException
    110113     */
     
    129132            // check if we can read the file
    130133            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.');
    132135            }
    133136
     
    244247     * Register a pattern to execute against the source content.
    245248     *
     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     *
    246252     * @param string          $pattern     PCRE pattern
    247253     * @param string|callable $replacement Replacement value for matched pattern
     
    253259
    254260        $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', '');
    255304    }
    256305
     
    269318    protected function replace($content)
    270319    {
    271         $processed = '';
     320        $contentLength = strlen($content);
     321        $output = '';
     322        $processedOffset = 0;
    272323        $positions = array_fill(0, count($this->patterns), -1);
    273324        $matches = array();
    274325
    275         while ($content) {
     326        while ($processedOffset < $contentLength) {
    276327            // find first match for all patterns
    277328            foreach ($this->patterns as $i => $pattern) {
     
    286337                // no need to re-run matches that are still in the part of the
    287338                // content that hasn't been processed
    288                 if ($positions[$i] >= 0) {
     339                if ($positions[$i] >= $processedOffset) {
    289340                    continue;
    290341                }
    291342
    292343                $match = null;
    293                 if (preg_match($pattern, $content, $match, PREG_OFFSET_CAPTURE)) {
     344                if (preg_match($pattern, $content, $match, PREG_OFFSET_CAPTURE, $processedOffset)) {
    294345                    $matches[$i] = $match;
    295346
     
    308359            // no more matches to find: everything's been processed, break out
    309360            if (!$matches) {
    310                 $processed .= $content;
     361                // output the remaining content
     362                $output .= substr($content, $processedOffset);
    311363                break;
    312364            }
     
    315367            // only want to execute that one, since we're unsure if what the
    316368            // 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];
    320372
    321373            // 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     *
    353392     * @param string|callable $replacement Replacement value
    354      * @param string          $content     Content to match pattern against
     393     * @param array           $match       Match data, in PREG_OFFSET_CAPTURE form
    355394     *
    356395     * @return string
    357396     */
    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);
    365408    }
    366409
     
    396439
    397440            $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];
    400443
    401444            return $placeholder;
     
    414457         * escaped (times 2)
    415458         */
    416         $this->registerPattern('/(['.$chars.'])(.*?(?<!\\\\)(\\\\\\\\)*+)\\1/s', $callback);
     459        $this->registerPattern('/([' . $chars . '])(.*?(?<!\\\\)(\\\\\\\\)*+)\\1/s', $callback);
    417460    }
    418461
     
    473516    protected function openFileForWriting($path)
    474517    {
    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.');
    477520        }
    478521
     
    491534    protected function writeToFile($handler, $content, $path = '')
    492535    {
    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;
    496553    }
    497554}
  • optimize-scripts-styles/trunk/readme.txt

    r2577281 r2928234  
    44Tags: scripts, styles, optimize, optimization, minify, compress, seo, performance, combine
    55Requires at least: 4.0
    6 Tested up to: 5.8
    7 Requires PHP: 5.6
    8 Stable tag: 1.9.3
     6Tested up to: 6.2
     7Requires PHP: 7.4
     8Stable tag: 1.9.4
    99License: GPLv2 or later
    1010License URI: https://www.gnu.org/licenses/gpl-2.0.html
     
    9090
    9191== 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
    9297
    9398= 1.9.3 =
  • optimize-scripts-styles/trunk/sp-optimize-scripts.php

    r2577281 r2928234  
    44 * Plugin URI: https://www.seismicpixels.com/optimize-scripts-styles-for-wordpress/
    55 * Description: Provides a quick way to combine and minify all scripts and styles and cache them in your content folder.
    6  * Version: 1.9.3
     6 * Version: 1.9.4
    77 * Author: Seismic Pixels
    88 * Author URI: https://www.seismicpixels.com
    9  * Copyright 2021 Sean Michaud - Seismic Pixels, LLC
     9 * Copyright 2023 Sean Michaud - Seismic Pixels, LLC
    1010*/
    1111
    1212global $spos_version;
    13 $spos_version = '1.9.3';
     13$spos_version = '1.9.4';
    1414
    1515global $spos_settings;
Note: See TracChangeset for help on using the changeset viewer.