Skip to content

Commit

Permalink
Merge pull request #5 from elephfront/more-minifier-methods
Browse files Browse the repository at this point in the history
Supports limiting the size of the embedded files as well as limiting …
  • Loading branch information
HavokInspiration committed Jul 12, 2017
2 parents f71696c + 14e1a76 commit 579dfe2
Show file tree
Hide file tree
Showing 15 changed files with 357 additions and 4 deletions.
4 changes: 3 additions & 1 deletion .stickler.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
linters:
phpcs:
standard: PSR2
extensions: '.php'
extensions: '.php'
csslint:
enable: false
111 changes: 111 additions & 0 deletions src/Task/CssMinify.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,14 @@
<?php
/**
* Copyright (c) Yves Piquel (http://www.havokinspiration.fr)
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright (c) Yves Piquel (http://www.havokinspiration.fr)
* @link http://github.com/elephfront/robo-css-minify
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
declare(strict_types=1);
namespace Elephfront\RoboCssMinify\Task;

Expand Down Expand Up @@ -68,6 +78,49 @@ class CssMinify extends BaseTask implements TaskInterface, Consumer
*/
protected $gzipLevel = 9;

/**
* Maximum file size (in kB) of file that will be embedded in the generated CSS content
*
* @var int
*/
protected $maxImportSize = 0;

/**
* List of file extensions that should be imported when the CSS is minified.
*
* @var array
*/
protected $importExtensions = [
'gif',
'png',
'jpe',
'jpg',
'jpeg',
'svg',
'woff',
'tif',
'tiff',
'xbm',
];

/**
* Mime types associated to extensions that should be imported when the CSS is minified.
*
* @var array
*/
protected $importExtensionsMimeTypes = [
'gif' => 'data:image/gif',
'png' => 'data:image/png',
'jpe' => 'data:image/jpeg',
'jpg' => 'data:image/jpeg',
'jpeg' => 'data:image/jpeg',
'svg' => 'data:image/svg+xml',
'woff' => 'data:application/x-font-woff',
'tif' => 'image/tiff',
'tiff' => 'image/tiff',
'xbm' => 'image/x-xbitmap',
];

/**
* Constructor. Will bind the destinations map.
*
Expand Down Expand Up @@ -102,6 +155,45 @@ public function enableGzip()
return $this;
}

/**
* Set the maximum file size (in kB) of file that will be embedded in the generated CSS content.
* Expects a positive integer. If a negative value is passed, the default of '5' will be applied.
*
* @param int $size The maximum file size (in kB) of file that will be embedded in the generated CSS content
* @return self
*/
public function setMaxImportSize(int $size)
{
if ($size < 0) {
$size = 0;
}

$this->maxImportSize = $size;

return $this;
}

/**
*
* @param array $extensions List of extensions to allow to be imported
* @return static
*/
public function setImportExtensions(array $extensions)
{
foreach ($extensions as $extension) {
if (!isset($this->importExtensionsMimeTypes[$extension])) {
$message = 'Unsupported file extension `%s`. Supported file extensions are `%s`';
throw new InvalidArgumentException(
sprintf($message, $extension, implode(array_keys($this->importExtensionsMimeTypes), ', '))
);
}
}

$this->importExtensions = $extensions;

return $this;
}

/**
* Set the level of compression to use when using the `gzip` option.
* Value should be between -1 and 9. If you use a value that is out of these bounds, will default to 9.
Expand Down Expand Up @@ -263,6 +355,9 @@ protected function execMinify(string $source, string $destination)
mkdir($destinationDirectory, 0755, true);
}

$this->minifier->setMaxImportSize($this->maxImportSize);
$this->minifier->setImportExtensions($this->compileImportExtensions());

if ($this->withGzip) {
$css = $this->minifier->gzip(null, $this->gzipLevel);
} else {
Expand Down Expand Up @@ -291,6 +386,22 @@ protected function execMinify(string $source, string $destination)
return true;
}

/**
* Compiles the file extensions to import to the format the minifier class is expecting.
*
* @return array Properly formatted extensions list.
*/
protected function compileImportExtensions()
{
$extensions = [];

foreach ($this->importExtensions as $extension) {
$extensions[$extension] = $this->importExtensionsMimeTypes[$extension];
}

return $extensions;
}

/**
* Gets the state from the previous task. Stores it in the `data` attribute of the object.
* This method is called before the task is run.
Expand Down
10 changes: 10 additions & 0 deletions src/Task/Loader/LoadCssMinifyTasksTrait.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,14 @@
<?php
/**
* Copyright (c) Yves Piquel (http://www.havokinspiration.fr)
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright (c) Yves Piquel (http://www.havokinspiration.fr)
* @link http://github.com/elephfront/robo-css-minify
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
declare(strict_types=1);
namespace Elephfront\RoboCssMinify\Task\Loader;

Expand Down
195 changes: 193 additions & 2 deletions tests/TestCase/Robo/Task/CssMinifyTest.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,14 @@
<?php
/**
* Copyright (c) Yves Piquel (http://www.havokinspiration.fr)
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright (c) Yves Piquel (http://www.havokinspiration.fr)
* @link http://github.com/elephfront/robo-css-minify
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
namespace Elephfront\RoboCssMinify\Tests;

use Elephfront\RoboCssMinify\Task\CssMinify;
Expand Down Expand Up @@ -115,7 +125,7 @@ public function testBasicMinification()
}

/**
* Test a basic minification (with a set source map)
* Test a basic minification with GZIP compression enabled
*
* @return void
*/
Expand Down Expand Up @@ -147,7 +157,8 @@ public function testBasicMinificationWithGzip()
}

/**
* Test a basic minification (with a set source map)
* Test a basic minification with GZIP compression enabled but an out of bound limit (will lead to the default value
* 9 to be used)
*
* @return void
*/
Expand Down Expand Up @@ -212,6 +223,186 @@ public function testBasicMinificationWithGzipAndCustomLevel()
);
}

/**
* Test a basic minification with embedded file in the result file.
*
* @return void
*/
public function testBasicMinificationWithImportedFiles()
{
$basePath = TESTS_ROOT . 'app' . DS . 'css' . DS;
$this->task
->setDestinationsMap([
$basePath . 'with-images.css' => $basePath . 'output.css'
]);
$result = $this->task->run();

$this->assertInstanceOf(Result::class, $result);
$this->assertEquals(Result::EXITCODE_OK, $result->getExitCode());

$this->assertEquals(
file_get_contents(TESTS_ROOT . 'comparisons' . DS . __FUNCTION__ . '.css'),
file_get_contents($basePath . 'output.css')
);

$source = $basePath . 'with-images.css';
$dest = $basePath . 'output.css';
$expectedLog = 'Minified CSS from <info>' . $source . '</info> to <info>' . $dest . '</info>';
$this->assertEquals(
$expectedLog,
$this->task->logger()->getLogs()[0]
);
}

/**
* Test a basic minification with embedded file in the result file with a limit in the import size.
*
* @return void
*/
public function testBasicMinificationWithImportedFilesLimitSize()
{
$basePath = TESTS_ROOT . 'app' . DS . 'css' . DS;
$this->task
->setDestinationsMap([
$basePath . 'with-images.css' => $basePath . 'output.css'
])
->setMaxImportSize(10);
$result = $this->task->run();

$this->assertInstanceOf(Result::class, $result);
$this->assertEquals(Result::EXITCODE_OK, $result->getExitCode());

$this->assertEquals(
file_get_contents(TESTS_ROOT . 'comparisons' . DS . __FUNCTION__ . '.css'),
file_get_contents($basePath . 'output.css')
);

$source = $basePath . 'with-images.css';
$dest = $basePath . 'output.css';
$expectedLog = 'Minified CSS from <info>' . $source . '</info> to <info>' . $dest . '</info>';
$this->assertEquals(
$expectedLog,
$this->task->logger()->getLogs()[0]
);
}

/**
* Test a basic minification with embedded file in the result file with a negative value in the limit size will use
* the default.
*
* @return void
*/
public function testBasicMinificationWithImportedFilesLimitSizeWithNegative()
{
$basePath = TESTS_ROOT . 'app' . DS . 'css' . DS;
$this->task
->setDestinationsMap([
$basePath . 'with-images.css' => $basePath . 'output.css'
])
->setMaxImportSize(-15);
$result = $this->task->run();

$this->assertInstanceOf(Result::class, $result);
$this->assertEquals(Result::EXITCODE_OK, $result->getExitCode());

$this->assertEquals(
file_get_contents(TESTS_ROOT . 'comparisons' . DS . 'testBasicMinificationWithImportedFiles.css'),
file_get_contents($basePath . 'output.css')
);

$source = $basePath . 'with-images.css';
$dest = $basePath . 'output.css';
$expectedLog = 'Minified CSS from <info>' . $source . '</info> to <info>' . $dest . '</info>';
$this->assertEquals(
$expectedLog,
$this->task->logger()->getLogs()[0]
);
}

/**
* Test a basic minification with embedded files in the result but with specific extensions provided.
*
* @return void
*/
public function testBasicMinificationWithImportedFilesWithSpecificExtensions()
{
$basePath = TESTS_ROOT . 'app' . DS . 'css' . DS;
$this->task
->setDestinationsMap([
$basePath . 'with-images.css' => $basePath . 'output.css'
])
->setImportExtensions(['jpg']);
$result = $this->task->run();

$this->assertInstanceOf(Result::class, $result);
$this->assertEquals(Result::EXITCODE_OK, $result->getExitCode());

$this->assertEquals(
file_get_contents(TESTS_ROOT . 'comparisons' . DS . __FUNCTION__ . '.css'),
file_get_contents($basePath . 'output.css')
);

$source = $basePath . 'with-images.css';
$dest = $basePath . 'output.css';
$expectedLog = 'Minified CSS from <info>' . $source . '</info> to <info>' . $dest . '</info>';
$this->assertEquals(
$expectedLog,
$this->task->logger()->getLogs()[0]
);
}

/**
* Test that specifying an unsupported extension will throw an exception
*
* @expectedException \InvalidArgumentException
* @expectedExceptionMessage Unsupported file extension `zip`. Supported file extensions are `gif, png, jpe, jpg,
* jpeg, svg, woff, tif, tiff, xbm`
* @return void
*/
public function testBasicMinificationWithImportedFilesWithUnsupportedExtensions()
{
$basePath = TESTS_ROOT . 'app' . DS . 'css' . DS;
$this->task
->setDestinationsMap([
$basePath . 'with-images.css' => $basePath . 'output.css'
])
->setImportExtensions(['zip']);
$this->task->run();
}

/**
* Test a basic minification with embedded files in the result but with specific extensions provided.
*
* @return void
*/
public function testBasicMinificationWithImportedFilesLimitSizeAndExtensions()
{
$basePath = TESTS_ROOT . 'app' . DS . 'css' . DS;
$this->task
->setDestinationsMap([
$basePath . 'with-images.css' => $basePath . 'output.css'
])
->setImportExtensions(['jpg'])
->setMaxImportSize(10);
$result = $this->task->run();

$this->assertInstanceOf(Result::class, $result);
$this->assertEquals(Result::EXITCODE_OK, $result->getExitCode());

$this->assertEquals(
file_get_contents(TESTS_ROOT . 'comparisons' . DS . __FUNCTION__ . '.css'),
file_get_contents($basePath . 'output.css')
);

$source = $basePath . 'with-images.css';
$dest = $basePath . 'output.css';
$expectedLog = 'Minified CSS from <info>' . $source . '</info> to <info>' . $dest . '</info>';
$this->assertEquals(
$expectedLog,
$this->task->logger()->getLogs()[0]
);
}

/**
* Test an import with the writeFile feature disabled.
*
Expand Down
Loading

0 comments on commit 579dfe2

Please sign in to comment.