mirror of
https://github.com/mrclay/minify.git
synced 2025-09-10 06:00:42 +02:00
Compare commits
65 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
266ddd7d54 | ||
|
07ed67aa77 | ||
|
2bbcce054d | ||
|
9040437901 | ||
|
f954e1bd58 | ||
|
a8a77e6054 | ||
|
25065b1559 | ||
|
807f41903e | ||
|
b81ad2289a | ||
|
fecf395de3 | ||
|
2bd66ae3f9 | ||
|
4453f3a4cb | ||
|
f50353a952 | ||
|
bd7d1077b3 | ||
|
40f89b528c | ||
|
b1bbdccef0 | ||
|
258e495451 | ||
|
b97a1db01d | ||
|
3081a88dbd | ||
|
df7fddfa09 | ||
|
c580d24e1b | ||
|
f9c96b6a3c | ||
|
d3decb27e1 | ||
|
0038cdb5de | ||
|
5659799c42 | ||
|
57be61586e | ||
|
2198482600 | ||
|
c2f40feb0c | ||
|
5c300aca97 | ||
|
76c1edc6ff | ||
|
919fc10139 | ||
|
bb7fc74330 | ||
|
eb4c0f6541 | ||
|
b6ef6fa397 | ||
|
00b9f28630 | ||
|
be40d4f9b2 | ||
|
9ee5fb7701 | ||
|
7d60fb9d0f | ||
|
6236431c8f | ||
|
404664509c | ||
|
9ed7f9dc24 | ||
|
d9b392c474 | ||
|
004f6bf730 | ||
|
72ece76cdf | ||
|
bde7a41021 | ||
|
88aca4019d | ||
|
70952d88f9 | ||
|
6b274afd0b | ||
|
449f009b39 | ||
|
6a5b09a00e | ||
|
93a1edd34b | ||
|
a6531d3481 | ||
|
9de63f3acc | ||
|
ed239fbb8b | ||
|
332f4bc839 | ||
|
79e5a22321 | ||
|
80c01c6f02 | ||
|
b6e4b7f152 | ||
|
a1489b2d8a | ||
|
d041f763c9 | ||
|
8056a4a9fb | ||
|
e3555570ef | ||
|
a8304c5fb3 | ||
|
dfb97a5c85 | ||
|
4626f6c1e0 |
36
.travis.yml
36
.travis.yml
@@ -1,17 +1,26 @@
|
||||
language: php
|
||||
sudo: false
|
||||
dist: trusty
|
||||
|
||||
php:
|
||||
- 7.0
|
||||
- 5.6
|
||||
- 5.5
|
||||
- 5.4
|
||||
- hhvm
|
||||
|
||||
matrix:
|
||||
jobs:
|
||||
fast_finish: true
|
||||
allow_failures:
|
||||
- php: hhvm
|
||||
- php: 7.0
|
||||
- php: "7.4snapshot"
|
||||
- php: "nightly"
|
||||
include:
|
||||
- php: "5.3"
|
||||
dist: precise
|
||||
- php: "5.4"
|
||||
- php: "5.5"
|
||||
- php: "5.6"
|
||||
- php: "7.0"
|
||||
- php: "7.1"
|
||||
- php: "7.2"
|
||||
- php: "7.3"
|
||||
- php: "7.4snapshot"
|
||||
|
||||
env:
|
||||
- CLOSURE_VERSION: 20161024
|
||||
|
||||
services:
|
||||
- memcached
|
||||
@@ -25,13 +34,10 @@ install:
|
||||
- composer update --no-interaction --prefer-source
|
||||
|
||||
before_script:
|
||||
- wget -c https://dl.google.com/closure-compiler/compiler-latest.zip -O vendor/compiler-latest.zip
|
||||
- unzip -od vendor/closure-compiler vendor/compiler-latest.zip
|
||||
- ln -sfn ../$(echo vendor/closure-compiler/closure-compiler-*.jar) tests/compiler.jar
|
||||
- java -jar tests/compiler.jar --version
|
||||
- tests/dl-closure.sh
|
||||
|
||||
script:
|
||||
- composer validate
|
||||
- phpunit --verbose
|
||||
- vendor/bin/phpunit --verbose
|
||||
|
||||
# vim:ts=2:sw=2:et
|
||||
|
@@ -1,18 +1,42 @@
|
||||
## Version 3.0.0 (unreleased)
|
||||
* The project root is now what is deployed as `min`
|
||||
## Version 3.0.5 (2019-10-01)
|
||||
|
||||
- Fix syntax error in composer.json, #653
|
||||
|
||||
## Version 3.0.4 (2019-09-24)
|
||||
|
||||
* See git log for details
|
||||
|
||||
## Version 3.0.3 (2017-11-03)
|
||||
|
||||
* Fix closure-compiler's error "redirection limit reached". #618, #619
|
||||
|
||||
## Version 3.0.2 (2017-09-14)
|
||||
|
||||
* Fixes syntax error in Groups controller, #613
|
||||
* Better-maintained lessphp fork, #610
|
||||
* No longer corrupts some chars in some environments, #608
|
||||
|
||||
## Version 3.0.1 (2017-06-09)
|
||||
|
||||
* Update CSSmin to v4, #599, #590
|
||||
|
||||
## Version 3.0.0 (2017-04-03)
|
||||
* Improved CSS minification via Túbal Martín's CSSMin
|
||||
* Easier error identification (just see error_log)
|
||||
* Adds feature to serve static files directly
|
||||
* Installation requires use of Composer to install dependencies
|
||||
* Removes JSMin+ (unmaintained, high memory usage)
|
||||
* Removes DooDigestAuth
|
||||
* Removes Minify_Loader (uses Composer)
|
||||
* Removes Minify_Logger (uses Monolog)
|
||||
* Removes `$min_libPath` option
|
||||
* The Minify, source, and controller components have changed APIs
|
||||
* Better CSS minification via Túbal Martín's CSSMin
|
||||
* Add config option for simply concatenating files
|
||||
* Add config option for altering creation of Minify/MinApp objects
|
||||
* Adds config option for simply concatenating files
|
||||
* Adds config option for altering creation of Minify/MinApp objects
|
||||
* Missing spec no longer redirects, instead links to docs
|
||||
* Installation requires use of Composer to install dependencies
|
||||
* Minify::VERSION is an int that tracks the major version number
|
||||
* BREAKING: The project root is now what gets deployed as `min`
|
||||
* BREAKING: Removes JSMin
|
||||
* BREAKING: Removes JSMin+ (unmaintained, high memory usage)
|
||||
* BREAKING: Removes DooDigestAuth
|
||||
* BREAKING: Removes Minify_Loader (uses Composer)
|
||||
* BREAKING: Removes Minify_Logger (uses Monolog)
|
||||
* BREAKING: Removes `$min_libPath` option
|
||||
* BREAKING: The Minify, source, and controller components have changed APIs
|
||||
|
||||
## Version 2.3.0 (2016-03-11)
|
||||
* Adds `$min_concatOnly` option to just concatenate files
|
||||
@@ -157,4 +181,4 @@
|
||||
* Replaced old JSMin library with a much faster custom implementation.
|
||||
|
||||
## Version 1.0.0 (2007-05-02)
|
||||
* First release.
|
||||
* First release.
|
12
README.md
12
README.md
@@ -21,20 +21,20 @@ Post to the [Google Group](http://groups.google.com/group/minify).
|
||||
|
||||
## Installation
|
||||
|
||||
See the [install guide](https://github.com/mrclay/minify/blob/master/docs/Install.wiki.md).
|
||||
See the [install guide](docs/Install.wiki.md).
|
||||
|
||||
## Configuration & Usage
|
||||
|
||||
(Using 2.x? [Here are the 2.x docs](https://github.com/mrclay/minify/tree/2.x/docs).)
|
||||
|
||||
See the [user guide](https://github.com/mrclay/minify/blob/master/docs/UserGuide.wiki.md).
|
||||
See the [user guide](docs/UserGuide.wiki.md).
|
||||
|
||||
Minify also comes with a [URI Builder application](https://github.com/mrclay/minify/blob/master/docs/BuilderApp.wiki.md) that can help you write URLs
|
||||
Minify also comes with a [URI Builder application](docs/BuilderApp.wiki.md) that can help you write URLs
|
||||
for use with Minify or configure groups of files.
|
||||
|
||||
See the [cookbook](https://github.com/mrclay/minify/blob/master/docs/CookBook.wiki.md) for more advanced options for minification.
|
||||
See the [cookbook](docs/CookBook.wiki.md) for more advanced options for minification.
|
||||
|
||||
More [docs are available](https://github.com/mrclay/minify/tree/master/docs).
|
||||
More [docs are available](docs).
|
||||
|
||||
## Unit Testing
|
||||
|
||||
@@ -43,7 +43,7 @@ More [docs are available](https://github.com/mrclay/minify/tree/master/docs).
|
||||
|
||||
## Warnings
|
||||
|
||||
* Minify is designed for efficiency, but, for very high traffic sites, it will probably serve files slower than your HTTPd due to the CGI overhead of PHP. See the [FAQ](https://github.com/mrclay/minify/blob/master/docs/FAQ.wiki.md#how-fast-is-it) and [CookBook](https://github.com/mrclay/minify/blob/master/docs/CookBook.wiki.md) for more info.
|
||||
* Minify is designed for efficiency, but, for very high traffic sites, it will probably serve files slower than your HTTPd due to the CGI overhead of PHP. See the [FAQ](docs/FAQ.wiki.md#how-fast-is-it) and [CookBook](docs/CookBook.wiki.md) for more info.
|
||||
* If you combine a lot of CSS, watch out for [IE's 4096 selectors-per-file limit](http://stackoverflow.com/a/9906889/3779), affects IE 6 through 9.
|
||||
* Minify *should* work fine with files encoded in UTF-8 or other 8-bit encodings like ISO 8859/Windows-1252. By default Minify appends ";charset=utf-8" to the Content-Type headers it sends.
|
||||
|
||||
|
@@ -20,28 +20,27 @@
|
||||
"classmap": ["lib/"]
|
||||
},
|
||||
"autoload-dev": {
|
||||
"classmap": ["tests/TestCase.php"]
|
||||
"psr-4": {"Minify\\Test\\": "tests/"}
|
||||
},
|
||||
"require": {
|
||||
"ext-pcre": "*",
|
||||
"intervention/httpauth": "~2.0",
|
||||
"monolog/monolog": "~1.1",
|
||||
"monolog/monolog": "~1.1|~2.0",
|
||||
"mrclay/jsmin-php": "~2",
|
||||
"mrclay/props-dic": "^2.2",
|
||||
"php": "^5.3.0 || ^7.0",
|
||||
"tubalmartin/cssmin": "~2.4.8-p5"
|
||||
"tubalmartin/cssmin": "~4",
|
||||
"marcusschwarz/lesserphp": "~0.5.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"firephp/firephp-core": "~0.4.0",
|
||||
"leafo/lessphp": "~0.4.0",
|
||||
"leafo/scssphp": "~0.6.6",
|
||||
"leafo/scssphp": "^0.3 || ^0.6 || ^0.7",
|
||||
"meenie/javascript-packer": "~1.1",
|
||||
"phpunit/phpunit": "4.8.*",
|
||||
"phpunit/phpunit": "^4.8.36",
|
||||
"tedivm/jshrink": "~1.1.0"
|
||||
},
|
||||
"suggest": {
|
||||
"firephp/firephp-core": "Use FirePHP for Log messages",
|
||||
"leafo/lessphp": "LESS support",
|
||||
"meenie/javascript-packer": "Keep track of the Packer PHP port using Composer"
|
||||
},
|
||||
"scripts": {
|
||||
|
@@ -26,7 +26,7 @@ Short answer: **use Minify 2.1.4+, use a pre-compressed version of your file, an
|
||||
|
||||
If the error is in your code, enable [debug mode](Debugging.wiki.md) while debugging your code in Firebug or your favorite browser's Javascript debugger. This will insert comments to allow you to keep track of the individual source locations in the combined file.
|
||||
|
||||
If you have Java on your web host, you can use the [wrapper for YUI Compressor](https://github.com/mrclay/minify/blob/master/lib/Minify/YUICompressor.php) instead of JSMin. [This thread](http://groups.google.com/group/minify/browse_thread/thread/f12f25f27e1256fe) shows how a user has done this.
|
||||
If you have Java on your web host, you can use the [wrapper for YUI Compressor](../lib/Minify/YUICompressor.php) instead of JSMin. [This thread](http://groups.google.com/group/minify/browse_thread/thread/f12f25f27e1256fe) shows how a user has done this.
|
||||
|
||||
## Javascript isn't being minified
|
||||
|
||||
@@ -48,7 +48,7 @@ Scriptaculous 1.8.2 (and probably all 1.x) has an [autoloader script](http://git
|
||||
|
||||
If you upload files using [Coda or Transmit](http://groups.google.com/group/coda-users/browse_thread/thread/572d2dc315ec02e7/) or from a Windows PC to a non-Windows server, your new files may end up with the wrong `mtime` (timestamp) on the server, confusing the cache system.
|
||||
|
||||
Setting the [$min\_uploaderHoursBehind option](https://github.com/mrclay/minify/blob/master/config.php#L171) in `config.php` can compensate for this.
|
||||
Setting the [$min\_uploaderHoursBehind option](../config.php#L171) in `config.php` can compensate for this.
|
||||
|
||||
WinSCP has a [Daylight Saving Time option](http://winscp.net/eng/docs/ui_login_environment#daylight_saving_time) that can prevent this issue.
|
||||
|
||||
|
@@ -39,7 +39,7 @@ $min_cachePath = new Minify_Cache_WinCache();
|
||||
|
||||
## Closure Compiler API Wrapper
|
||||
|
||||
An [experimental wrapper for Google's closure compiler API](https://github.com/mrclay/minify/blob/master/min/lib/Minify/JS/ClosureCompiler.php) is available for compressing Javascript. If the API fails for any reason, JSMin is used as the default backup minifier.
|
||||
An [experimental wrapper for Google's closure compiler API](../lib/Minify/JS/ClosureCompiler.php) is available for compressing Javascript. If the API fails for any reason, JSMin is used as the default backup minifier.
|
||||
```php
|
||||
$min_serveOptions['minifiers'][Minify::TYPE_JS] = array('Minify_JS_ClosureCompiler', 'minify');
|
||||
```
|
||||
|
@@ -47,7 +47,7 @@ $controller = new Minify_Controller_Files($env, $sourceFactory);
|
||||
|
||||
## Set up service and controller options
|
||||
|
||||
A single array is used for configuring both the behavior of `Minify::serve` (see the [default options](https://github.com/mrclay/minify/blob/master/lib/Minify.php#L73)) and the controller, which has its own option keys.
|
||||
A single array is used for configuring both the behavior of `Minify::serve` (see the [default options](../lib/Minify.php#L73)) and the controller, which has its own option keys.
|
||||
|
||||
The Files controller only needs one key: `files`: the array of sources to be combined and served.
|
||||
|
||||
|
@@ -4,7 +4,7 @@ The simple JSMin algorithm is the most reliable in PHP, but check the [CookBook]
|
||||
|
||||
## How fast is it?
|
||||
|
||||
If you [serve static files](https://github.com/mrclay/minify/blob/master/static/README.md), it's as fast as your web server, and you should do this for high-traffic sites.
|
||||
If you [serve static files](../static/README.md), it's as fast as your web server, and you should do this for high-traffic sites.
|
||||
|
||||
The PHP-based server is not as fast, but still performs well thanks to an internal cache. Tips:
|
||||
|
||||
|
@@ -36,12 +36,12 @@ cp ${MINIFY}quick-test.css ${MIN}
|
||||
|
||||
Edit `min/index.php` to remove the ``die()`` statement and adjust the `vendor` path as needed.
|
||||
|
||||
**Note:** This does not install the [URL builder](https://github.com/mrclay/minify/blob/master/docs/BuilderApp.wiki.md), but it's not necessary for operation.
|
||||
**Note:** This does not install the [URL builder](BuilderApp.wiki.md), but it's not necessary for operation.
|
||||
|
||||
## Verifing it works
|
||||
|
||||
You can verify it works via these two URLs:
|
||||
|
||||
|
||||
* http://example.org/min/?f=min/quick-test.js
|
||||
* http://example.org/min/?f=min/quick-test.css
|
||||
|
||||
@@ -56,6 +56,6 @@ Write the [Google Group](http://groups.google.com/group/minify) for help.
|
||||
|
||||
## More links
|
||||
|
||||
* [Usage instructions](https://github.com/mrclay/minify/blob/master/docs/UserGuide.wiki.md)
|
||||
* [Cookbook](https://github.com/mrclay/minify/blob/master/docs/CookBook.wiki.md) for more advanced options
|
||||
* [All docs](https://github.com/mrclay/minify/tree/master/docs)
|
||||
* [Usage instructions](UserGuide.wiki.md)
|
||||
* [Cookbook](CookBook.wiki.md) for more advanced options
|
||||
* [All docs](docs)
|
||||
|
@@ -79,8 +79,6 @@ Browse to http://example.com/min/builder/
|
||||
|
||||
The Minify URI Builder will help you create URIs you can use to minify existing files on your site. You can see screenshots and get a feel for this process from this [walkthrough on mrclay.org](http://mrclay.org/index.php/2008/09/19/minify-21-on-mrclayorg/)
|
||||
|
||||
More info here: https://github.com/mrclay/minify/blob/master/MIN.txt
|
||||
|
||||
You may want to disable the [BuilderApp](BuilderApp.wiki.md) when not in use.
|
||||
|
||||
# Far-future Expires headers
|
||||
@@ -110,9 +108,9 @@ Known issue: files with comment-like strings/regexps can cause problems in this
|
||||
|
||||
# Configuration
|
||||
|
||||
See [config.php](https://github.com/mrclay/minify/blob/master/config.php) for general config options.
|
||||
See [config.php](../config.php) for general config options.
|
||||
|
||||
[groupsConfig.php](https://github.com/mrclay/minify/blob/master/groupsConfig.php) holds preset groups of files to minify. (The builder application can help with this).
|
||||
[groupsConfig.php](../groupsConfig.php) holds preset groups of files to minify. (The builder application can help with this).
|
||||
|
||||
[CookBook](CookBook.wiki.md) shows how to customize settings between production/development environments, and between groups.
|
||||
|
||||
|
@@ -128,8 +128,8 @@ class HTTP_ConditionalGet
|
||||
$etagAppend = '';
|
||||
if (isset($spec['encoding'])) {
|
||||
$this->_stripEtag = true;
|
||||
$this->_headers['Vary'] = 'Accept-Encoding';
|
||||
if ('' !== $spec['encoding']) {
|
||||
$this->_headers['Vary'] = 'Accept-Encoding';
|
||||
if (0 === strpos($spec['encoding'], 'x-')) {
|
||||
$spec['encoding'] = substr($spec['encoding'], 2);
|
||||
}
|
||||
|
@@ -14,9 +14,6 @@ use Psr\Log\LoggerInterface;
|
||||
* This library was inspired by {@link mailto:flashkot@mail.ru jscsscomp by Maxim Martynyuk}
|
||||
* and by the article {@link http://www.hunlock.com/blogs/Supercharged_Javascript "Supercharged JavaScript" by Patrick Hunlock}.
|
||||
*
|
||||
* Requires PHP 5.1.0.
|
||||
* Tested on PHP 5.1.6.
|
||||
*
|
||||
* @package Minify
|
||||
* @author Ryan Grove <ryan@wonko.com>
|
||||
* @author Stephen Clay <steve@mrclay.org>
|
||||
@@ -48,14 +45,14 @@ class Minify
|
||||
*
|
||||
* @var Minify_CacheInterface
|
||||
*/
|
||||
private $cache = null;
|
||||
private $cache;
|
||||
|
||||
/**
|
||||
* Active controller for current request
|
||||
*
|
||||
* @var Minify_Controller_Base
|
||||
*/
|
||||
protected $controller = null;
|
||||
protected $controller;
|
||||
|
||||
/**
|
||||
* @var Minify_Env
|
||||
@@ -77,12 +74,12 @@ class Minify
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $options = null;
|
||||
protected $options;
|
||||
|
||||
/**
|
||||
* @var LoggerInterface|null
|
||||
*/
|
||||
protected $logger = null;
|
||||
protected $logger;
|
||||
|
||||
/**
|
||||
* @param Minify_CacheInterface $cache
|
||||
@@ -302,20 +299,20 @@ class Minify
|
||||
$cg->sendHeaders();
|
||||
|
||||
return;
|
||||
} else {
|
||||
return array(
|
||||
'success' => true,
|
||||
'statusCode' => 304,
|
||||
'content' => '',
|
||||
'headers' => $cg->getHeaders(),
|
||||
);
|
||||
}
|
||||
} else {
|
||||
// client will need output
|
||||
$headers = $cg->getHeaders();
|
||||
unset($cg);
|
||||
|
||||
return array(
|
||||
'success' => true,
|
||||
'statusCode' => 304,
|
||||
'content' => '',
|
||||
'headers' => $cg->getHeaders(),
|
||||
);
|
||||
}
|
||||
|
||||
// client will need output
|
||||
$headers = $cg->getHeaders();
|
||||
unset($cg);
|
||||
|
||||
if ($this->options['contentType'] === self::TYPE_CSS && $this->options['rewriteCssUris']) {
|
||||
$this->setupUriRewrites();
|
||||
}
|
||||
@@ -517,7 +514,6 @@ class Minify
|
||||
if ($file
|
||||
&& !isset($minifyOptions['currentDir'])
|
||||
&& !isset($minifyOptions['prependRelativePath'])) {
|
||||
|
||||
$minifyOptions['currentDir'] = dirname($file);
|
||||
$source->setMinifierOptions($minifyOptions);
|
||||
}
|
||||
|
@@ -2,23 +2,34 @@
|
||||
|
||||
namespace Minify;
|
||||
|
||||
use Minify_Cache_File;
|
||||
use Minify_CacheInterface;
|
||||
use Minify_Controller_MinApp;
|
||||
use Minify_ControllerInterface;
|
||||
use Minify_DebugDetector;
|
||||
use Minify_Env;
|
||||
use Minify_Source_Factory;
|
||||
use Props\Container;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use RuntimeException;
|
||||
use Monolog;
|
||||
use Minify;
|
||||
|
||||
/**
|
||||
* @property \Minify_CacheInterface $cache
|
||||
* @property \Minify\Config $config
|
||||
* @property Minify_CacheInterface $cache
|
||||
* @property Config $config
|
||||
* @property string $configPath
|
||||
* @property \Minify_ControllerInterface $controller
|
||||
* @property Minify_ControllerInterface $controller
|
||||
* @property string $dir
|
||||
* @property string $docRoot
|
||||
* @property \Minify_Env $env
|
||||
* @property \Monolog\Handler\ErrorLogHandler $errorLogHandler
|
||||
* @property Minify_Env $env
|
||||
* @property Monolog\Handler\ErrorLogHandler $errorLogHandler
|
||||
* @property array $groupsConfig
|
||||
* @property string $groupsConfigPath
|
||||
* @property \Psr\Log\LoggerInterface $logger
|
||||
* @property LoggerInterface $logger
|
||||
* @property \Minify $minify
|
||||
* @property array $serveOptions
|
||||
* @property \Minify_Source_Factory $sourceFactory
|
||||
* @property Minify_Source_Factory $sourceFactory
|
||||
* @property array $sourceFactoryOptions
|
||||
*/
|
||||
class App extends Container
|
||||
@@ -38,29 +49,29 @@ class App extends Container
|
||||
$this->cache = function (App $app) use ($that) {
|
||||
$config = $app->config;
|
||||
|
||||
if ($config->cachePath instanceof \Minify_CacheInterface) {
|
||||
if ($config->cachePath instanceof Minify_CacheInterface) {
|
||||
return $config->cachePath;
|
||||
}
|
||||
|
||||
if (!$config->cachePath || is_string($config->cachePath)) {
|
||||
return new \Minify_Cache_File($config->cachePath, $config->cacheFileLocking, $app->logger);
|
||||
return new Minify_Cache_File($config->cachePath, $config->cacheFileLocking, $app->logger);
|
||||
}
|
||||
|
||||
$type = $that->typeOf($config->cachePath);
|
||||
throw new \RuntimeException('$min_cachePath must be a path or implement Minify_CacheInterface.'
|
||||
throw new RuntimeException('$min_cachePath must be a path or implement Minify_CacheInterface.'
|
||||
. " Given $type");
|
||||
};
|
||||
|
||||
$this->config = function (App $app) {
|
||||
$config = (require $app->configPath);
|
||||
|
||||
if ($config instanceof \Minify\Config) {
|
||||
if ($config instanceof Minify\Config) {
|
||||
return $config;
|
||||
}
|
||||
|
||||
// copy from vars into properties
|
||||
|
||||
$config = new \Minify\Config();
|
||||
$config = new Minify\Config();
|
||||
|
||||
$propNames = array_keys(get_object_vars($config));
|
||||
|
||||
@@ -69,6 +80,11 @@ class App extends Container
|
||||
};
|
||||
$varNames = array_map($prefixer, $propNames);
|
||||
|
||||
$varDefinedChecker = function ($name) {
|
||||
return array_key_exists($name, get_defined_vars());
|
||||
};
|
||||
$varNames = array_filter($varNames, $varDefinedChecker);
|
||||
|
||||
$vars = compact($varNames);
|
||||
|
||||
foreach ($varNames as $varName) {
|
||||
@@ -94,17 +110,17 @@ class App extends Container
|
||||
$config = $app->config;
|
||||
|
||||
if (empty($config->factories['controller'])) {
|
||||
$ctrl = new \Minify_Controller_MinApp($app->env, $app->sourceFactory, $app->logger);
|
||||
$ctrl = new Minify_Controller_MinApp($app->env, $app->sourceFactory, $app->logger);
|
||||
} else {
|
||||
$ctrl = call_user_func($config->factories['controller'], $app);
|
||||
}
|
||||
|
||||
if ($ctrl instanceof \Minify_ControllerInterface) {
|
||||
if ($ctrl instanceof Minify_ControllerInterface) {
|
||||
return $ctrl;
|
||||
}
|
||||
|
||||
$type = $that->typeOf($ctrl);
|
||||
throw new \RuntimeException('$min_factories["controller"] callable must return an implementation'
|
||||
throw new RuntimeException('$min_factories["controller"] callable must return an implementation'
|
||||
." of Minify_CacheInterface. Returned $type");
|
||||
};
|
||||
|
||||
@@ -118,13 +134,13 @@ class App extends Container
|
||||
};
|
||||
|
||||
$this->env = function (App $app) {
|
||||
return new \Minify_Env($app->config->envArgs);
|
||||
return new Minify_Env($app->config->envArgs);
|
||||
};
|
||||
|
||||
$this->errorLogHandler = function (App $app) {
|
||||
$format = "%channel%.%level_name%: %message% %context% %extra%";
|
||||
$handler = new \Monolog\Handler\ErrorLogHandler();
|
||||
$handler->setFormatter(new \Monolog\Formatter\LineFormatter($format));
|
||||
$handler = new Monolog\Handler\ErrorLogHandler();
|
||||
$handler->setFormatter(new Monolog\Formatter\LineFormatter($format));
|
||||
|
||||
return $handler;
|
||||
};
|
||||
@@ -138,11 +154,11 @@ class App extends Container
|
||||
$this->logger = function (App $app) use ($that) {
|
||||
$value = $app->config->errorLogger;
|
||||
|
||||
if ($value instanceof \Psr\Log\LoggerInterface) {
|
||||
if ($value instanceof LoggerInterface) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
$logger = new \Monolog\Logger('minify');
|
||||
$logger = new Monolog\Logger('minify');
|
||||
|
||||
if (!$value) {
|
||||
return $logger;
|
||||
@@ -150,12 +166,12 @@ class App extends Container
|
||||
|
||||
if ($value === true || $value instanceof \FirePHP) {
|
||||
$logger->pushHandler($app->errorLogHandler);
|
||||
$logger->pushHandler(new \Monolog\Handler\FirePHPHandler());
|
||||
$logger->pushHandler(new Monolog\Handler\FirePHPHandler());
|
||||
|
||||
return $logger;
|
||||
}
|
||||
|
||||
if ($value instanceof \Monolog\Handler\HandlerInterface) {
|
||||
if ($value instanceof Monolog\Handler\HandlerInterface) {
|
||||
$logger->pushHandler($value);
|
||||
|
||||
return $logger;
|
||||
@@ -163,14 +179,14 @@ class App extends Container
|
||||
|
||||
// BC
|
||||
if (is_object($value) && is_callable(array($value, 'log'))) {
|
||||
$handler = new \Minify\Logger\LegacyHandler($value);
|
||||
$handler = new Minify\Logger\LegacyHandler($value);
|
||||
$logger->pushHandler($handler);
|
||||
|
||||
return $logger;
|
||||
}
|
||||
|
||||
$type = $that->typeOf($value);
|
||||
throw new \RuntimeException('If set, $min_errorLogger must be a PSR-3 logger or a Monolog handler.'
|
||||
throw new RuntimeException('If set, $min_errorLogger must be a PSR-3 logger or a Monolog handler.'
|
||||
." Given $type");
|
||||
};
|
||||
|
||||
@@ -187,7 +203,7 @@ class App extends Container
|
||||
}
|
||||
|
||||
$type = $that->typeOf($minify);
|
||||
throw new \RuntimeException('$min_factories["minify"] callable must return a Minify object.'
|
||||
throw new RuntimeException('$min_factories["minify"] callable must return a Minify object.'
|
||||
." Returned $type");
|
||||
};
|
||||
|
||||
@@ -207,7 +223,7 @@ class App extends Container
|
||||
}
|
||||
|
||||
if ($config->allowDebugFlag) {
|
||||
$ret['debug'] = \Minify_DebugDetector::shouldDebugRequest($env);
|
||||
$ret['debug'] = Minify_DebugDetector::shouldDebugRequest($env);
|
||||
}
|
||||
|
||||
if ($config->concatOnly) {
|
||||
@@ -228,7 +244,7 @@ class App extends Container
|
||||
};
|
||||
|
||||
$this->sourceFactory = function (App $app) {
|
||||
return new \Minify_Source_Factory($app->env, $app->sourceFactoryOptions, $app->cache);
|
||||
return new Minify_Source_Factory($app->env, $app->sourceFactoryOptions, $app->cache);
|
||||
};
|
||||
|
||||
$this->sourceFactoryOptions = function (App $app) {
|
||||
|
@@ -80,7 +80,6 @@ class Minify_Build
|
||||
*
|
||||
* @param array $sources array of Minify_Source objects and/or file paths
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
public function __construct($sources)
|
||||
{
|
||||
|
@@ -89,9 +89,10 @@ class Minify_CSS
|
||||
$currentDir = $options['currentDir'];
|
||||
$docRoot = $options['docRoot'];
|
||||
$symlinks = $options['symlinks'];
|
||||
|
||||
return Minify_CSS_UriRewriter::rewrite($css, $currentDir, $docRoot, $symlinks);
|
||||
} else {
|
||||
return Minify_CSS_UriRewriter::prepend($css, $options['prependRelativePath']);
|
||||
}
|
||||
|
||||
return Minify_CSS_UriRewriter::prepend($css, $options['prependRelativePath']);
|
||||
}
|
||||
}
|
||||
|
@@ -217,6 +217,7 @@ class Minify_CSS_Compressor
|
||||
if (preg_match($pattern, $m, $n)) {
|
||||
// end hack mode after this comment, but preserve the hack and comment content
|
||||
$this->_inHack = false;
|
||||
|
||||
return "/*/{$n[1]}/**/";
|
||||
}
|
||||
}
|
||||
@@ -224,18 +225,21 @@ class Minify_CSS_Compressor
|
||||
if (substr($m, -1) === '\\') { // comment ends like \*/
|
||||
// begin hack mode and preserve hack
|
||||
$this->_inHack = true;
|
||||
|
||||
return '/*\\*/';
|
||||
}
|
||||
|
||||
if ($m !== '' && $m[0] === '/') { // comment looks like /*/ foo */
|
||||
// begin hack mode and preserve hack
|
||||
$this->_inHack = true;
|
||||
|
||||
return '/*/*/';
|
||||
}
|
||||
|
||||
if ($this->_inHack) {
|
||||
// a regular comment ends hack mode but should be preserved
|
||||
$this->_inHack = false;
|
||||
|
||||
return '/**/';
|
||||
}
|
||||
|
||||
|
@@ -52,7 +52,6 @@ class Minify_CSS_UriRewriter
|
||||
|
||||
// normalize symlinks in order to map to link
|
||||
foreach ($symlinks as $link => $target) {
|
||||
|
||||
$link = ($link === '//') ? self::$_docRoot : str_replace('//', self::$_docRoot . '/', $link);
|
||||
$link = strtr($link, '/', DIRECTORY_SEPARATOR);
|
||||
|
||||
@@ -272,6 +271,7 @@ class Minify_CSS_UriRewriter
|
||||
\\s*
|
||||
\\) # )
|
||||
/x';
|
||||
|
||||
return preg_replace($pattern, 'url($1)', $css);
|
||||
}
|
||||
|
||||
@@ -337,6 +337,7 @@ class Minify_CSS_UriRewriter
|
||||
private static function _owlifySvgPaths($css)
|
||||
{
|
||||
$pattern = '~\b((?:clip-path|mask|-webkit-mask)\s*\:\s*)url(\(\s*#\w+\s*\))~';
|
||||
|
||||
return preg_replace($pattern, '$1owl$2', $css);
|
||||
}
|
||||
|
||||
@@ -351,6 +352,7 @@ class Minify_CSS_UriRewriter
|
||||
private static function _unOwlify($css)
|
||||
{
|
||||
$pattern = '~\b((?:clip-path|mask|-webkit-mask)\s*\:\s*)owl~';
|
||||
|
||||
return preg_replace($pattern, '$1url', $css);
|
||||
}
|
||||
}
|
||||
|
@@ -4,6 +4,8 @@
|
||||
* @package Minify
|
||||
*/
|
||||
|
||||
use tubalmartin\CssMin\Minifier as CSSmin;
|
||||
|
||||
/**
|
||||
* Wrapper for CSSmin
|
||||
*
|
||||
@@ -76,11 +78,11 @@ class Minify_CSSmin
|
||||
,$options['docRoot']
|
||||
,$options['symlinks']
|
||||
);
|
||||
} else {
|
||||
return Minify_CSS_UriRewriter::prepend(
|
||||
$css
|
||||
,$options['prependRelativePath']
|
||||
);
|
||||
}
|
||||
|
||||
return Minify_CSS_UriRewriter::prepend(
|
||||
$css
|
||||
,$options['prependRelativePath']
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@@ -62,7 +62,7 @@ class Minify_Cache_APC implements Minify_CacheInterface
|
||||
if (function_exists('mb_strlen') && ((int)ini_get('mbstring.func_overload') & 2)) {
|
||||
return mb_strlen($this->_data, '8bit');
|
||||
} else {
|
||||
return strlen($this->_data);;
|
||||
return strlen($this->_data);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,6 +124,7 @@ class Minify_Cache_APC implements Minify_CacheInterface
|
||||
$ret = apc_fetch($id);
|
||||
if (false === $ret) {
|
||||
$this->_id = null;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@@ -109,6 +109,7 @@ class Minify_Cache_File implements Minify_CacheInterface
|
||||
{
|
||||
if (!$this->locking) {
|
||||
readfile($this->path . '/' . $id);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@@ -38,14 +38,14 @@ class Minify_ClosureCompiler
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public static $jarFile = null;
|
||||
public static $jarFile;
|
||||
|
||||
/**
|
||||
* Writable temp directory. This must be set before calling minifyJs().
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public static $tempDir = null;
|
||||
public static $tempDir;
|
||||
|
||||
/**
|
||||
* Filepath of "java" executable (may be needed if not in shell's PATH)
|
||||
@@ -129,7 +129,7 @@ class Minify_ClosureCompiler
|
||||
$this->getOptionsCommandLine($userOptions)
|
||||
);
|
||||
|
||||
return join(' ', $args) . ' ' . escapeshellarg($tmpFile);
|
||||
return implode(' ', $args) . ' ' . escapeshellarg($tmpFile);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -48,7 +48,7 @@ class Minify_Controller_Groups extends Minify_Controller_Files
|
||||
if (isset($server['ORIG_PATH_INFO'])) {
|
||||
$pathInfo = substr($server['ORIG_PATH_INFO'], 1);
|
||||
} elseif (isset($server['PATH_INFO'])) {
|
||||
$pathInfo = substr($server['PATH_INFO'], 1)
|
||||
$pathInfo = substr($server['PATH_INFO'], 1);
|
||||
} else {
|
||||
$pathInfo = false;
|
||||
}
|
||||
|
@@ -102,10 +102,10 @@ class Minify_Env
|
||||
return $path;
|
||||
}
|
||||
|
||||
protected $server = null;
|
||||
protected $get = null;
|
||||
protected $post = null;
|
||||
protected $cookie = null;
|
||||
protected $server;
|
||||
protected $get;
|
||||
protected $post;
|
||||
protected $cookie;
|
||||
|
||||
/**
|
||||
* Compute $_SERVER['DOCUMENT_ROOT'] for IIS using SCRIPT_FILENAME and SCRIPT_NAME.
|
||||
|
@@ -99,52 +99,52 @@ class Minify_HTML
|
||||
|
||||
// replace SCRIPTs (and minify) with placeholders
|
||||
$this->_html = preg_replace_callback(
|
||||
'/(\\s*)<script(\\b[^>]*?>)([\\s\\S]*?)<\\/script>(\\s*)/i'
|
||||
'/(\\s*)<script(\\b[^>]*?>)([\\s\\S]*?)<\\/script>(\\s*)/iu'
|
||||
,array($this, '_removeScriptCB')
|
||||
,$this->_html);
|
||||
|
||||
// replace STYLEs (and minify) with placeholders
|
||||
$this->_html = preg_replace_callback(
|
||||
'/\\s*<style(\\b[^>]*>)([\\s\\S]*?)<\\/style>\\s*/i'
|
||||
'/\\s*<style(\\b[^>]*>)([\\s\\S]*?)<\\/style>\\s*/iu'
|
||||
,array($this, '_removeStyleCB')
|
||||
,$this->_html);
|
||||
|
||||
// remove HTML comments (not containing IE conditional comments).
|
||||
$this->_html = preg_replace_callback(
|
||||
'/<!--([\\s\\S]*?)-->/'
|
||||
'/<!--([\\s\\S]*?)-->/u'
|
||||
,array($this, '_commentCB')
|
||||
,$this->_html);
|
||||
|
||||
// replace PREs with placeholders
|
||||
$this->_html = preg_replace_callback('/\\s*<pre(\\b[^>]*?>[\\s\\S]*?<\\/pre>)\\s*/i'
|
||||
$this->_html = preg_replace_callback('/\\s*<pre(\\b[^>]*?>[\\s\\S]*?<\\/pre>)\\s*/iu'
|
||||
,array($this, '_removePreCB')
|
||||
,$this->_html);
|
||||
|
||||
// replace TEXTAREAs with placeholders
|
||||
$this->_html = preg_replace_callback(
|
||||
'/\\s*<textarea(\\b[^>]*?>[\\s\\S]*?<\\/textarea>)\\s*/i'
|
||||
'/\\s*<textarea(\\b[^>]*?>[\\s\\S]*?<\\/textarea>)\\s*/iu'
|
||||
,array($this, '_removeTextareaCB')
|
||||
,$this->_html);
|
||||
|
||||
// trim each line.
|
||||
// @todo take into account attribute values that span multiple lines.
|
||||
$this->_html = preg_replace('/^\\s+|\\s+$/m', '', $this->_html);
|
||||
$this->_html = preg_replace('/^\\s+|\\s+$/mu', '', $this->_html);
|
||||
|
||||
// remove ws around block/undisplayed elements
|
||||
$this->_html = preg_replace('/\\s+(<\\/?(?:area|article|aside|base(?:font)?|blockquote|body'
|
||||
.'|canvas|caption|center|col(?:group)?|dd|dir|div|dl|dt|fieldset|figcaption|figure|footer|form'
|
||||
.'|frame(?:set)?|h[1-6]|head|header|hgroup|hr|html|legend|li|link|main|map|menu|meta|nav'
|
||||
.'|ol|opt(?:group|ion)|output|p|param|section|t(?:able|body|head|d|h||r|foot|itle)'
|
||||
.'|ul|video)\\b[^>]*>)/i', '$1', $this->_html);
|
||||
.'|ul|video)\\b[^>]*>)/iu', '$1', $this->_html);
|
||||
|
||||
// remove ws outside of all elements
|
||||
$this->_html = preg_replace(
|
||||
'/>(\\s(?:\\s*))?([^<]+)(\\s(?:\s*))?</'
|
||||
'/>(\\s(?:\\s*))?([^<]+)(\\s(?:\s*))?</u'
|
||||
,'>$1$2$3<'
|
||||
,$this->_html);
|
||||
|
||||
// use newlines before 1st attribute in open tags (to limit line lengths)
|
||||
$this->_html = preg_replace('/(<[a-z\\-]+)\\s+([^>]+>)/i', "$1\n$2", $this->_html);
|
||||
$this->_html = preg_replace('/(<[a-z\\-]+)\\s+([^>]+>)/iu', "$1\n$2", $this->_html);
|
||||
|
||||
// fill placeholders
|
||||
$this->_html = str_replace(
|
||||
@@ -177,11 +177,11 @@ class Minify_HTML
|
||||
return $placeholder;
|
||||
}
|
||||
|
||||
protected $_isXhtml = null;
|
||||
protected $_replacementHash = null;
|
||||
protected $_isXhtml;
|
||||
protected $_replacementHash;
|
||||
protected $_placeholders = array();
|
||||
protected $_cssMinifier = null;
|
||||
protected $_jsMinifier = null;
|
||||
protected $_cssMinifier;
|
||||
protected $_jsMinifier;
|
||||
|
||||
protected function _removePreCB($m)
|
||||
{
|
||||
@@ -198,7 +198,7 @@ class Minify_HTML
|
||||
$openStyle = "<style{$m[1]}";
|
||||
$css = $m[2];
|
||||
// remove HTML comments
|
||||
$css = preg_replace('/(?:^\\s*<!--|-->\\s*$)/', '', $css);
|
||||
$css = preg_replace('/(?:^\\s*<!--|-->\\s*$)/u', '', $css);
|
||||
|
||||
// remove CDATA section markers
|
||||
$css = $this->_removeCdata($css);
|
||||
@@ -226,7 +226,7 @@ class Minify_HTML
|
||||
|
||||
// remove HTML comments (and ending "//" if present)
|
||||
if ($this->_jsCleanComments) {
|
||||
$js = preg_replace('/(?:^\\s*<!--\\s*|\\s*(?:\\/\\/)?\\s*-->\\s*$)/', '', $js);
|
||||
$js = preg_replace('/(?:^\\s*<!--\\s*|\\s*(?:\\/\\/)?\\s*-->\\s*$)/u', '', $js);
|
||||
}
|
||||
|
||||
// remove CDATA section markers
|
||||
@@ -253,6 +253,6 @@ class Minify_HTML
|
||||
|
||||
protected function _needsCdata($str)
|
||||
{
|
||||
return ($this->_isXhtml && preg_match('/(?:[<&]|\\-\\-|\\]\\]>)/', $str));
|
||||
return ($this->_isXhtml && preg_match('/(?:[<&]|\\-\\-|\\]\\]>)/u', $str));
|
||||
}
|
||||
}
|
||||
|
@@ -32,15 +32,15 @@ class Minify_ImportProcessor
|
||||
}
|
||||
|
||||
// allows callback funcs to know the current directory
|
||||
private $_currentDir = null;
|
||||
private $_currentDir;
|
||||
|
||||
// allows callback funcs to know the directory of the file that inherits this one
|
||||
private $_previewsDir = null;
|
||||
private $_previewsDir;
|
||||
|
||||
// allows _importCB to write the fetched content back to the obj
|
||||
private $_importedContent = '';
|
||||
|
||||
private static $_isCss = null;
|
||||
private static $_isCss;
|
||||
|
||||
/**
|
||||
* @param String $currentDir
|
||||
@@ -182,7 +182,7 @@ class Minify_ImportProcessor
|
||||
private function truepath($path)
|
||||
{
|
||||
// whether $path is unix or not
|
||||
$unipath = (strlen($path) == 0) || ($path{0} != '/');
|
||||
$unipath = ('' === $path) || ($path{0} !== '/');
|
||||
|
||||
// attempts to detect if path is relative in which case, add cwd
|
||||
if (strpos($path, ':') === false && $unipath) {
|
||||
@@ -194,10 +194,10 @@ class Minify_ImportProcessor
|
||||
$parts = array_filter(explode(DIRECTORY_SEPARATOR, $path), 'strlen');
|
||||
$absolutes = array();
|
||||
foreach ($parts as $part) {
|
||||
if ('.' == $part) {
|
||||
if ('.' === $part) {
|
||||
continue;
|
||||
}
|
||||
if ('..' == $part) {
|
||||
if ('..' === $part) {
|
||||
array_pop($absolutes);
|
||||
} else {
|
||||
$absolutes[] = $part;
|
||||
|
@@ -54,7 +54,7 @@ class Minify_JS_ClosureCompiler
|
||||
/**
|
||||
* @var string $url URL of compiler server. defaults to Google's
|
||||
*/
|
||||
protected $serviceUrl = 'http://closure-compiler.appspot.com/compile';
|
||||
protected $serviceUrl = 'https://closure-compiler.appspot.com/compile';
|
||||
|
||||
/**
|
||||
* @var int $maxBytes The maximum JS size that can be sent to the compiler server in bytes
|
||||
@@ -174,6 +174,9 @@ class Minify_JS_ClosureCompiler
|
||||
$contents = file_get_contents($this->serviceUrl, false, stream_context_create(array(
|
||||
'http' => array(
|
||||
'method' => 'POST',
|
||||
'compilation_level' => 'SIMPLE',
|
||||
'output_format' => 'text',
|
||||
'output_info' => 'compiled_code',
|
||||
'header' => "Content-type: application/x-www-form-urlencoded\r\nConnection: close\r\n",
|
||||
'content' => $postBody,
|
||||
'max_redirects' => 0,
|
||||
|
@@ -49,7 +49,7 @@ class Minify_Lines
|
||||
$newLines = array();
|
||||
|
||||
while (null !== ($line = array_shift($lines))) {
|
||||
if (('' !== $id) && (0 == $i % 50)) {
|
||||
if (('' !== $id) && (0 === $i % 50)) {
|
||||
if ($inComment) {
|
||||
array_push($newLines, '', "/* {$id} *|", '');
|
||||
} else {
|
||||
|
@@ -63,7 +63,7 @@ class Minify_NailgunClosureCompiler extends Minify_ClosureCompiler
|
||||
$server = array(
|
||||
self::$javaExecutable,
|
||||
'-server',
|
||||
'-cp', join(':', $classPath),
|
||||
'-cp', implode(':', $classPath),
|
||||
self::NG_SERVER,
|
||||
);
|
||||
|
||||
@@ -101,9 +101,9 @@ class Minify_NailgunClosureCompiler extends Minify_ClosureCompiler
|
||||
|
||||
private function startServer()
|
||||
{
|
||||
$serverCommand = join(' ', $this->getServerCommandLine());
|
||||
$serverCommand = implode(' ', $this->getServerCommandLine());
|
||||
$psCommand = $this->shell("ps -o cmd= -C " . self::$javaExecutable);
|
||||
if (array_search($serverCommand, $psCommand) !== false) {
|
||||
if (in_array($serverCommand, $psCommand, true)) {
|
||||
// already started!
|
||||
return;
|
||||
}
|
||||
|
@@ -19,12 +19,12 @@ class Minify_Source implements Minify_SourceInterface
|
||||
/**
|
||||
* @var int time of last modification
|
||||
*/
|
||||
protected $lastModified = null;
|
||||
protected $lastModified;
|
||||
|
||||
/**
|
||||
* @var callback minifier function specifically for this source.
|
||||
*/
|
||||
protected $minifier = null;
|
||||
protected $minifier;
|
||||
|
||||
/**
|
||||
* @var array minification options specific to this source.
|
||||
@@ -34,27 +34,27 @@ class Minify_Source implements Minify_SourceInterface
|
||||
/**
|
||||
* @var string full path of file
|
||||
*/
|
||||
protected $filepath = null;
|
||||
protected $filepath;
|
||||
|
||||
/**
|
||||
* @var string HTTP Content Type (Minify requires one of the constants Minify::TYPE_*)
|
||||
*/
|
||||
protected $contentType = null;
|
||||
protected $contentType;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $content = null;
|
||||
protected $content;
|
||||
|
||||
/**
|
||||
* @var callable
|
||||
*/
|
||||
protected $getContentFunc = null;
|
||||
protected $getContentFunc;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $id = null;
|
||||
protected $id;
|
||||
|
||||
/**
|
||||
* Create a Minify_Source
|
||||
@@ -137,7 +137,7 @@ class Minify_Source implements Minify_SourceInterface
|
||||
$minifier = 'Minify::nullMinifier';
|
||||
}
|
||||
if ($minifier !== null && !is_callable($minifier, true)) {
|
||||
throw new \InvalidArgumentException('minifier must be null or a valid callable');
|
||||
throw new InvalidArgumentException('minifier must be null or a valid callable');
|
||||
}
|
||||
$this->minifier = $minifier;
|
||||
}
|
||||
@@ -180,8 +180,13 @@ class Minify_Source implements Minify_SourceInterface
|
||||
} else {
|
||||
$content = file_get_contents($this->filepath);
|
||||
}
|
||||
|
||||
// remove UTF-8 BOM if present
|
||||
return ("\xEF\xBB\xBF" === substr($content, 0, 3)) ? substr($content, 3) : $content;
|
||||
if (strpos($content, "\xEF\xBB\xBF") === 0) {
|
||||
return substr($content, 3);
|
||||
}
|
||||
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -208,7 +213,6 @@ class Minify_Source implements Minify_SourceInterface
|
||||
if ($this->filepath
|
||||
&& !isset($this->minifyOptions['currentDir'])
|
||||
&& !isset($this->minifyOptions['prependRelativePath'])) {
|
||||
|
||||
$this->minifyOptions['currentDir'] = dirname($this->filepath);
|
||||
}
|
||||
}
|
||||
|
@@ -38,7 +38,7 @@ class Minify_YUICompressor
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public static $jarFile = null;
|
||||
public static $jarFile;
|
||||
|
||||
/**
|
||||
* Writable temp directory. This must be set before calling minifyJs()
|
||||
@@ -46,7 +46,7 @@ class Minify_YUICompressor
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public static $tempDir = null;
|
||||
public static $tempDir;
|
||||
|
||||
/**
|
||||
* Filepath of "java" executable (may be needed if not in shell's PATH)
|
||||
|
@@ -1,5 +1,9 @@
|
||||
<?php
|
||||
|
||||
namespace Minify\Test;
|
||||
|
||||
use HTTP_ConditionalGet;
|
||||
|
||||
class HTTPConditionalGetTest extends TestCase
|
||||
{
|
||||
public function TestData()
|
||||
|
@@ -1,9 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace Minify\Test;
|
||||
|
||||
use HTTP_Encoder;
|
||||
|
||||
class HTTPEncoderTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @dataProvider testToIe6Data
|
||||
* @dataProvider ToIe6DataProvider
|
||||
* @preserveGlobals
|
||||
*/
|
||||
public function testToIe6($ua, $ae, $exp, $desc)
|
||||
@@ -16,7 +20,7 @@ class HTTPEncoderTest extends TestCase
|
||||
$this->assertSame($exp, $ret, $desc);
|
||||
}
|
||||
|
||||
public function testToIe6Data()
|
||||
public function ToIe6DataProvider()
|
||||
{
|
||||
return array(
|
||||
array(
|
||||
@@ -65,7 +69,7 @@ class HTTPEncoderTest extends TestCase
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider testEncodeNonIeData
|
||||
* @dataProvider EncodeNonIeDataProvider
|
||||
*/
|
||||
public function testEncodeNonIe($ua, $ae, $exp, $desc)
|
||||
{
|
||||
@@ -77,7 +81,7 @@ class HTTPEncoderTest extends TestCase
|
||||
$this->assertSame($exp, $ret, $desc);
|
||||
}
|
||||
|
||||
public function testEncodeNonIeData()
|
||||
public function EncodeNonIeDataProvider()
|
||||
{
|
||||
return array(
|
||||
array(
|
||||
@@ -104,7 +108,7 @@ class HTTPEncoderTest extends TestCase
|
||||
|
||||
$encodingTests = array(
|
||||
array('method' => 'deflate', 'inv' => 'gzinflate', 'exp' => 32268),
|
||||
array('method' => 'gzip', 'inv' => '_gzdecode', 'exp' => 32286),
|
||||
array('method' => 'gzip', 'inv' => __NAMESPACE__ . '\\_gzdecode', 'exp' => 32286),
|
||||
array('method' => 'compress', 'inv' => 'gzuncompress', 'exp' => 32325),
|
||||
);
|
||||
|
||||
@@ -117,7 +121,7 @@ class HTTPEncoderTest extends TestCase
|
||||
$ret = $this->countBytes($e->getContent());
|
||||
|
||||
// test uncompression
|
||||
$roundTrip = @call_user_func($test['inv'], $e->getContent());
|
||||
$roundTrip = call_user_func($test['inv'], $e->getContent());
|
||||
$desc = "{$test['method']} : uncompress possible";
|
||||
$this->assertSame($variedContent, $roundTrip, $desc);
|
||||
|
||||
|
@@ -1,8 +1,11 @@
|
||||
<?php
|
||||
|
||||
namespace Minify\Test;
|
||||
|
||||
use Exception;
|
||||
use JSMin\JSMin;
|
||||
|
||||
class JsMinTest extends TestCase
|
||||
class JSMinTest extends TestCase
|
||||
{
|
||||
public function test1()
|
||||
{
|
||||
@@ -54,7 +57,8 @@ class JsMinTest extends TestCase
|
||||
* @param string $label
|
||||
* @param string $expClass
|
||||
* @param string $expMessage
|
||||
* @dataProvider testJSMinExceptionData
|
||||
*
|
||||
* @dataProvider JSMinExceptionDataProvider
|
||||
*/
|
||||
public function testJSMinException($js, $label, $expClass, $expMessage)
|
||||
{
|
||||
@@ -68,7 +72,7 @@ class JsMinTest extends TestCase
|
||||
$this->assertTrue($eClass === $expClass && $eMsg === $expMessage, 'Throw on ' . $label);
|
||||
}
|
||||
|
||||
public function testJSMinExceptionData()
|
||||
public function JSMinExceptionDataProvider()
|
||||
{
|
||||
// $js, $label, $expClass, $expMessage
|
||||
return array(
|
||||
|
@@ -1,6 +1,11 @@
|
||||
<?php
|
||||
|
||||
class JsClosureCompilerTest extends PHPUnit_Framework_TestCase
|
||||
namespace Minify\Test;
|
||||
|
||||
use Minify_JS_ClosureCompiler;
|
||||
use Minify_JS_ClosureCompiler_Exception;
|
||||
|
||||
class JsClosureCompilerTest extends TestCase
|
||||
{
|
||||
public function test1()
|
||||
{
|
||||
@@ -27,7 +32,8 @@ class JsClosureCompilerTest extends PHPUnit_Framework_TestCase
|
||||
$this->compile($src);
|
||||
} catch (Minify_JS_ClosureCompiler_Exception $e) {
|
||||
}
|
||||
$this->assertInstanceOf('Minify_JS_ClosureCompiler_Exception', $e, 'Throws Minify_JS_ClosureCompiler_Exception');
|
||||
$this->assertInstanceOf('Minify_JS_ClosureCompiler_Exception', $e,
|
||||
'Throws Minify_JS_ClosureCompiler_Exception');
|
||||
}
|
||||
|
||||
// Test maximum byte size check (default)
|
||||
@@ -40,7 +46,8 @@ class JsClosureCompilerTest extends PHPUnit_Framework_TestCase
|
||||
$this->compile($src);
|
||||
} catch (Minify_JS_ClosureCompiler_Exception $e) {
|
||||
}
|
||||
$this->assertInstanceOf('Minify_JS_ClosureCompiler_Exception', $e, 'Throws Minify_JS_ClosureCompiler_Exception');
|
||||
$this->assertInstanceOf('Minify_JS_ClosureCompiler_Exception', $e,
|
||||
'Throws Minify_JS_ClosureCompiler_Exception');
|
||||
|
||||
$expected = 'POST content larger than ' . Minify_JS_ClosureCompiler::DEFAULT_MAX_BYTES . ' bytes';
|
||||
$this->assertEquals($expected, $e->getMessage(), 'Message must tell how big maximum byte size is');
|
||||
@@ -69,7 +76,8 @@ class JsClosureCompilerTest extends PHPUnit_Framework_TestCase
|
||||
));
|
||||
} catch (Minify_JS_ClosureCompiler_Exception $e) {
|
||||
}
|
||||
$this->assertInstanceOf('Minify_JS_ClosureCompiler_Exception', $e, 'Throws Minify_JS_ClosureCompiler_Exception');
|
||||
$this->assertInstanceOf('Minify_JS_ClosureCompiler_Exception', $e,
|
||||
'Throws Minify_JS_ClosureCompiler_Exception');
|
||||
|
||||
$expected = 'POST content larger than ' . $allowedBytes . ' bytes';
|
||||
$this->assertEquals($expected, $e->getMessage(), 'Message must tell how big maximum byte size is');
|
||||
@@ -88,7 +96,8 @@ class JsClosureCompilerTest extends PHPUnit_Framework_TestCase
|
||||
));
|
||||
} catch (Minify_JS_ClosureCompiler_Exception $e) {
|
||||
}
|
||||
$this->assertInstanceOf('Minify_JS_ClosureCompiler_Exception', $e, 'Throws Minify_JS_ClosureCompiler_Exception');
|
||||
$this->assertInstanceOf('Minify_JS_ClosureCompiler_Exception', $e,
|
||||
'Throws Minify_JS_ClosureCompiler_Exception');
|
||||
}
|
||||
|
||||
public function test7()
|
||||
|
@@ -1,5 +1,9 @@
|
||||
<?php
|
||||
|
||||
namespace Minify\Test;
|
||||
|
||||
use Minify_HTML_Helper;
|
||||
|
||||
class LessSourceTest extends TestCase
|
||||
{
|
||||
public function setUp()
|
||||
|
@@ -1,5 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace Minify\Test;
|
||||
|
||||
use Minify_Build;
|
||||
use Minify_Source;
|
||||
|
||||
class MinifyBuildTest extends TestCase
|
||||
{
|
||||
public function test()
|
||||
|
@@ -1,5 +1,9 @@
|
||||
<?php
|
||||
|
||||
namespace Minify\Test;
|
||||
|
||||
use Minify_CSS_UriRewriter;
|
||||
|
||||
class MinifyCSSUriRewriterTest extends TestCase
|
||||
{
|
||||
public function setUp()
|
||||
|
@@ -1,5 +1,9 @@
|
||||
<?php
|
||||
|
||||
namespace Minify\Test;
|
||||
|
||||
use Minify_Cache_APC;
|
||||
|
||||
class MinifyCacheAPCTest extends TestCase
|
||||
{
|
||||
public function setUp()
|
||||
|
@@ -1,5 +1,9 @@
|
||||
<?php
|
||||
|
||||
namespace Minify\Test;
|
||||
|
||||
use Minify_Cache_File;
|
||||
|
||||
class MinifyCacheFileTest extends TestCase
|
||||
{
|
||||
public function test1()
|
||||
|
@@ -1,5 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace Minify\Test;
|
||||
|
||||
use Memcache;
|
||||
use Minify_Cache_Memcache;
|
||||
|
||||
class MinifyCacheMemcacheTest extends TestCase
|
||||
{
|
||||
/** @var Memcache */
|
||||
|
@@ -1,5 +1,9 @@
|
||||
<?php
|
||||
|
||||
namespace Minify\Test;
|
||||
|
||||
use Minify_Cache_WinCache;
|
||||
|
||||
class MinifyCacheWinCacheTest extends TestCase
|
||||
{
|
||||
public function setUp()
|
||||
|
@@ -1,5 +1,9 @@
|
||||
<?php
|
||||
|
||||
namespace Minify\Test;
|
||||
|
||||
use Minify_Cache_ZendPlatform;
|
||||
|
||||
class MinifyCacheZendPlatformTest extends TestCase
|
||||
{
|
||||
public function setUp()
|
||||
|
@@ -1,5 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace Minify\Test;
|
||||
|
||||
use Exception;
|
||||
use Minify_ClosureCompiler;
|
||||
|
||||
class MinifyClosureCompilerTest extends TestCase
|
||||
{
|
||||
public static function setupBeforeClass()
|
||||
|
@@ -1,5 +1,9 @@
|
||||
<?php
|
||||
|
||||
namespace Minify\Test;
|
||||
|
||||
use Minify_CommentPreserver;
|
||||
|
||||
class MinifyCommentPreserverTest extends TestCase
|
||||
{
|
||||
public function test()
|
||||
|
@@ -1,5 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace Minify\Test;
|
||||
|
||||
use Minify_HTML_Helper;
|
||||
use Minify_Source;
|
||||
|
||||
class MinifyHTMLHelperTest extends TestCase
|
||||
{
|
||||
private $realDocRoot;
|
||||
@@ -40,8 +45,10 @@ class MinifyHTMLHelperTest extends TestCase
|
||||
$expected = "/myApp/min/?g=css&{$maxTime}";
|
||||
$actual = Minify_HTML_Helper::getUri('css', array(
|
||||
'rewriteWorks' => false
|
||||
, 'minAppUri' => '/myApp/min/'
|
||||
, 'groupsConfigFile' => self::$test_files . '/htmlHelper_groupsConfig.php'
|
||||
,
|
||||
'minAppUri' => '/myApp/min/'
|
||||
,
|
||||
'groupsConfigFile' => self::$test_files . '/htmlHelper_groupsConfig.php'
|
||||
));
|
||||
$this->assertEquals($expected, $actual, 'existing group');
|
||||
|
||||
@@ -67,7 +74,8 @@ class MinifyHTMLHelperTest extends TestCase
|
||||
));
|
||||
$output = Minify_mtime(array(
|
||||
$obj
|
||||
, 'css'
|
||||
,
|
||||
'css'
|
||||
), self::$test_files . '/htmlHelper_groupsConfig.php');
|
||||
$this->assertEquals($maxTime, $output, 'utils.php : Minify_mtime w/ obj & group');
|
||||
}
|
||||
|
@@ -1,5 +1,9 @@
|
||||
<?php
|
||||
|
||||
namespace Minify\Test;
|
||||
|
||||
use Minify_HTML;
|
||||
|
||||
class MinifyHTMLTest extends TestCase
|
||||
{
|
||||
public function test1()
|
||||
|
@@ -1,5 +1,9 @@
|
||||
<?php
|
||||
|
||||
namespace Minify\Test;
|
||||
|
||||
use Minify_ImportProcessor;
|
||||
|
||||
class MinifyImportProcessorTest extends TestCase
|
||||
{
|
||||
public function test()
|
||||
@@ -19,6 +23,7 @@ class MinifyImportProcessorTest extends TestCase
|
||||
realpath($linDir . '/lib/css/example.css'),
|
||||
);
|
||||
|
||||
$this->assertEquals($expectedIncludes, Minify_ImportProcessor::$filesIncluded, 'included right files in right order');
|
||||
$this->assertEquals($expectedIncludes, Minify_ImportProcessor::$filesIncluded,
|
||||
'included right files in right order');
|
||||
}
|
||||
}
|
||||
|
@@ -1,5 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace Minify\Test;
|
||||
|
||||
use Minify;
|
||||
use Minify_Cache_Null;
|
||||
use Minify_Controller_Files;
|
||||
use Minify_Env;
|
||||
use Minify_Source_Factory;
|
||||
|
||||
class MinifyLinesTest extends TestCase
|
||||
{
|
||||
public function test_lines()
|
||||
|
@@ -1,5 +1,11 @@
|
||||
<?php
|
||||
|
||||
namespace Minify\Test;
|
||||
|
||||
use Exception;
|
||||
use Minify_ClosureCompiler;
|
||||
use Minify_NailgunClosureCompiler;
|
||||
|
||||
class MinifyNailgunClosureCompilerTest extends TestCase
|
||||
{
|
||||
public static function setupBeforeClass()
|
||||
|
@@ -1,5 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace Minify\Test;
|
||||
|
||||
use Minify;
|
||||
use Minify_Cache_Null;
|
||||
use Minify_Controller_Files;
|
||||
use Minify_Env;
|
||||
use Minify_Source_Factory;
|
||||
|
||||
class MinifyTest extends TestCase
|
||||
{
|
||||
public function test_Minify()
|
||||
@@ -37,7 +45,6 @@ class MinifyTest extends TestCase
|
||||
'content' => '',
|
||||
'headers' => array(
|
||||
'Expires' => gmdate('D, d M Y H:i:s \G\M\T', $_SERVER['REQUEST_TIME'] + 1800),
|
||||
'Vary' => 'Accept-Encoding',
|
||||
'Last-Modified' => gmdate('D, d M Y H:i:s \G\M\T', $lastModified),
|
||||
'ETag' => "\"pub{$lastModified}\"",
|
||||
'Cache-Control' => 'max-age=1800',
|
||||
@@ -146,7 +153,8 @@ class MinifyTest extends TestCase
|
||||
));
|
||||
$output = $output['content'];
|
||||
|
||||
$this->assertFalse(strpos($output, $defaultOptions['importWarning']), 'Issue 89 : don\'t warn about valid imports');
|
||||
$this->assertFalse(strpos($output, $defaultOptions['importWarning']),
|
||||
'Issue 89 : don\'t warn about valid imports');
|
||||
|
||||
// Test Issue 132
|
||||
if (function_exists('mb_strlen') && ((int)ini_get('mbstring.func_overload') & 2)) {
|
||||
@@ -156,7 +164,8 @@ class MinifyTest extends TestCase
|
||||
'encodeOutput' => false,
|
||||
));
|
||||
|
||||
$this->assertEquals(77, $output['headers']['Content-Length'], 'Issue 132 : mbstring.func_overload shouldn\'t cause incorrect Content-Length');
|
||||
$this->assertEquals(77, $output['headers']['Content-Length'],
|
||||
'Issue 132 : mbstring.func_overload shouldn\'t cause incorrect Content-Length');
|
||||
}
|
||||
|
||||
// Test minifying CSS and responding with Etag/Last-Modified
|
||||
|
@@ -1,5 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace Minify\Test;
|
||||
|
||||
use Exception;
|
||||
use Minify_YUICompressor;
|
||||
|
||||
class MinifyYuiCSSTest extends TestCase
|
||||
{
|
||||
public static function setupBeforeClass()
|
||||
@@ -13,7 +18,8 @@ class MinifyYuiCSSTest extends TestCase
|
||||
Minify_YUICompressor::$tempDir = sys_get_temp_dir();
|
||||
}
|
||||
|
||||
public function setUp() {
|
||||
public function setUp()
|
||||
{
|
||||
$this->assertHasJar();
|
||||
}
|
||||
|
||||
@@ -49,7 +55,7 @@ class MinifyYuiCSSTest extends TestCase
|
||||
{
|
||||
$this->assertNotEmpty(Minify_YUICompressor::$jarFile);
|
||||
try {
|
||||
$this->assertFileExists(Minify_YUICompressor::$jarFile , "Have YUI yuicompressor.jar");
|
||||
$this->assertFileExists(Minify_YUICompressor::$jarFile, "Have YUI yuicompressor.jar");
|
||||
} catch (Exception $e) {
|
||||
$this->markTestSkipped($e->getMessage());
|
||||
}
|
||||
|
@@ -1,13 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace Minify\Test;
|
||||
|
||||
use Minify_HTML_Helper;
|
||||
|
||||
class ScssSourceTest extends TestCase
|
||||
{
|
||||
public function setUp()
|
||||
{
|
||||
if (version_compare(PHP_VERSION, '5.4.0', '<')) {
|
||||
$this->markTestSkipped('scssphp is not compatible with this PHP version.');
|
||||
}
|
||||
|
||||
$this->realDocRoot = $_SERVER['DOCUMENT_ROOT'];
|
||||
$_SERVER['DOCUMENT_ROOT'] = self::$document_root;
|
||||
}
|
||||
|
@@ -1,6 +1,10 @@
|
||||
<?php
|
||||
|
||||
class TestCase extends PHPUnit_Framework_TestCase
|
||||
namespace Minify\Test;
|
||||
|
||||
use Minify_CacheInterface;
|
||||
|
||||
abstract class TestCase extends \PHPUnit\Framework\TestCase
|
||||
{
|
||||
/** @var string */
|
||||
protected static $document_root;
|
||||
|
@@ -8,7 +8,7 @@ name="robots" content="all" /><title>css Zen Garden: The Beauty in CSS Design</t
|
||||
is.mac=is.ua.indexOf('mac')>=0;if(is.ua.indexOf('opera')>=0){is.ie=is.ns=false;is.opera=true;}
|
||||
if(is.ua.indexOf('gecko')>=0){is.ie=is.ns=false;is.gecko=true;}</script> <script type="text/javascript">/*<![CDATA[*/var i=0;while(++i<10)
|
||||
{}/*]]>*/</script> <script type="text/javascript">i=1;</script> <script type="text/javascript">/*<![CDATA[*/(i<1);/*]]>*/</script> <!--[if IE 6]><style type="text/css">/*<![CDATA[*//*! copyright: you'll need CDATA for this < & */
|
||||
body{background:white}/*]]>*/</style><![endif]--><style type="text/css" title="currentStyle" media="screen">@import "/001/001.css";/*\*//**/css hack{display:none;display:none}</style><link
|
||||
body{background:#fff}/*]]>*/</style><![endif]--><style type="text/css" title="currentStyle" media="screen">@import "/001/001.css";css hack{display:none;display:none}</style><link
|
||||
rel="Shortcut Icon"
|
||||
type="image/x-icon"
|
||||
href="http://www.csszengarden.com/favicon.ico" /><link
|
||||
|
@@ -8,7 +8,7 @@ name="robots" content="all"><title>css Zen Garden: The Beauty in CSS Design</tit
|
||||
is.mac=is.ua.indexOf('mac')>=0;if(is.ua.indexOf('opera')>=0){is.ie=is.ns=false;is.opera=true;}
|
||||
if(is.ua.indexOf('gecko')>=0){is.ie=is.ns=false;is.gecko=true;}</script> <script type="text/javascript">var i=0;while(++i<10)
|
||||
{}</script> <script type="text/javascript">i=1;</script> <script type="text/javascript">(i<1);</script> <!--[if IE 6]><style type="text/css">/*! copyright: you'll need CDATA for this < & */
|
||||
body{background:white}</style><![endif]--><style type="text/css" title="currentStyle" media="screen">@import "/001/001.css";/*\*//**/css hack{display:none;display:none}</style><link
|
||||
body{background:#fff}</style><![endif]--><style type="text/css" title="currentStyle" media="screen">@import "/001/001.css";css hack{display:none;display:none}</style><link
|
||||
rel="Shortcut Icon"
|
||||
type="image/x-icon"
|
||||
href="http://www.csszengarden.com/favicon.ico"><link
|
||||
|
16
tests/dl-closure.sh
Executable file
16
tests/dl-closure.sh
Executable file
@@ -0,0 +1,16 @@
|
||||
#!/bin/sh
|
||||
set -xe
|
||||
|
||||
: ${CLOSURE_VERSION:=20161024}
|
||||
|
||||
wget -c https://dl.google.com/closure-compiler/compiler-$CLOSURE_VERSION.zip -O vendor/compiler-$CLOSURE_VERSION.zip
|
||||
unzip -od vendor/closure-compiler vendor/compiler-$CLOSURE_VERSION.zip
|
||||
ln -sfn ../vendor/closure-compiler/closure-compiler-v$CLOSURE_VERSION.jar tests/compiler.jar
|
||||
|
||||
# test that version matches
|
||||
out=$(java -jar tests/compiler.jar --version)
|
||||
|
||||
version=$(echo "$out" | awk '/Version:/{print $NF}')
|
||||
version=${version#v}
|
||||
|
||||
test "$version" = "$CLOSURE_VERSION"
|
Reference in New Issue
Block a user