Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@
/.php-cs-fixer.cache
/composer.lock
/phpunit.xml
/tests/Fixtures/config/
Comment thread
smnandre marked this conversation as resolved.
/tests/Fixtures/var/
/vendor/
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
# CHANGELOG

## 1.3.0

- Add HTML support (`MinifierInterface::TYPE_HTML`)
- Add options support to `MinifierInterface::minify()` via the `OptionsInterface` DTO (BC-compatible, third argument)
Comment thread
smnandre marked this conversation as resolved.
Outdated

## 1.2.0

- Add Symfony 8 support
Comment thread
smnandre marked this conversation as resolved.

## 1.1.0

- Support for PHP 8.1.0 or higher
Expand Down
5 changes: 3 additions & 2 deletions src/Minifier/MinifierInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,10 @@ interface MinifierInterface
{
public const TYPE_CSS = 'css';
public const TYPE_JS = 'js';
public const TYPE_HTML = 'html';

/**
* @param self::TYPE_CSS|self::TYPE_JS $type
* @param self::TYPE_CSS|self::TYPE_JS|self::TYPE_HTML $type
*/
public function minify(string $input, string $type): string;
public function minify(string $input, string $type/* , ?\Sensiolabs\MinifyBundle\Minifier\Options\OptionsInterface $options = null */): string;
}
42 changes: 42 additions & 0 deletions src/Minifier/Options/HtmlOptions.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php

declare(strict_types=1);

/*
* This file is part of the SensioLabs MinifyBundle package.
*
* (c) Simon André - Sensiolabs
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Sensiolabs\MinifyBundle\Minifier\Options;

use Sensiolabs\MinifyBundle\Minifier\MinifierInterface;

final class HtmlOptions implements OptionsInterface
{
/**
* @param bool $keepDocumentTags preserve html, head and body tags
*/
public function __construct(
public readonly bool $keepDocumentTags = false,
) {
}

public function getType(): string
{
return MinifierInterface::TYPE_HTML;
}

public function toCliArgs(): array
{
$args = [];
if ($this->keepDocumentTags) {
$args[] = '--html-keep-document-tags';
}

return $args;
}
}
29 changes: 29 additions & 0 deletions src/Minifier/Options/OptionsInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

declare(strict_types=1);

/*
* This file is part of the SensioLabs MinifyBundle package.
*
* (c) Simon André - Sensiolabs
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Sensiolabs\MinifyBundle\Minifier\Options;

use Sensiolabs\MinifyBundle\Minifier\MinifierInterface;

interface OptionsInterface
Comment thread
smnandre marked this conversation as resolved.
{
/**
* @return MinifierInterface::TYPE_*
*/
public function getType(): string;

/**
* @return list<string>
*/
public function toCliArgs(): array;
}
4 changes: 2 additions & 2 deletions src/Minifier/TraceableMinifier.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public function __construct(
) {
}

public function minify(string $input, string $type): string
public function minify(string $input, string $type/* , ?\Sensiolabs\MinifyBundle\Minifier\Options\OptionsInterface $options = null */): string
{
$inputSize = strlen($input);
$this->logger->debug('Minify command input: {inputSize} kB', [
Expand All @@ -36,7 +36,7 @@ public function minify(string $input, string $type): string
]);

$timeStart = microtime(true);
$output = $this->minifier->minify($input, $type);
$output = $this->minifier->minify(...\func_get_args());
Comment thread
smnandre marked this conversation as resolved.
Outdated
$timeEnd = microtime(true);

$outputSize = strlen($output);
Expand Down
18 changes: 16 additions & 2 deletions src/Minify.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

use Sensiolabs\MinifyBundle\Exception\RuntimeException;
use Sensiolabs\MinifyBundle\Minifier\MinifierInterface;
use Sensiolabs\MinifyBundle\Minifier\Options\OptionsInterface;
use Symfony\Component\Process\Process;

/**
Expand All @@ -27,9 +28,22 @@ public function __construct(
) {
}

public function minify(string $input, string $type): string
public function minify(string $input, string $type/* , ?OptionsInterface $options = null */): string

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we add a comment / deprecartion here, this feels so legit i'd agree to release a 2.0 there if we generalise this

{
$process = new Process([$this->binaryPath, '--type', $type]);
$options = \func_num_args() > 2 ? \func_get_arg(2) : null;
if ($options !== null && !$options instanceof OptionsInterface) {
throw new RuntimeException(sprintf('Expected $options to be an instance of "%s", got "%s".', OptionsInterface::class, get_debug_type($options)));
}
if ($options !== null && $options->getType() !== $type) {
throw new RuntimeException(sprintf('Options type "%s" does not match minify type "%s".', $options->getType(), $type));
}

$args = [$this->binaryPath, '--type', $type];
if ($options !== null) {
$args = [...$args, ...$options->toCliArgs()];
}

$process = new Process($args);
$process->setInput($input);

try {
Expand Down
14 changes: 10 additions & 4 deletions tests/Fixtures/bin/fakify
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ if (!isset($argv[1]) || '--type' !== $argv[1] || !isset($argv[2])) {
echo 'ERROR: Missing type argument.';
exit(1);
}
if (!in_array($argv[2], ['css', 'js'])) {
if (!in_array($argv[2], ['css', 'js', 'html'])) {
echo 'ERROR: Invalid type argument.';
exit(1);
}
Expand All @@ -15,14 +15,20 @@ $input = file_get_contents('php://stdin');

if ('css' === $typeArg) {
file_put_contents('php://stdout', $input);


return;
}

if ('html' === $typeArg) {
$extraArgs = array_slice($argv, 3);
file_put_contents('php://stdout', $input.'|args='.implode(' ', $extraArgs));

return;
}

if ('js' === $typeArg) {
// file_put_contents('php://stdout', $input);
exit(20000000);

return;
}

41 changes: 41 additions & 0 deletions tests/Minifier/Options/HtmlOptionsTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php

declare(strict_types=1);

/*
* This file is part of the SensioLabs MinifyBundle package.
*
* (c) Simon André - Sensiolabs
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Sensiolabs\MinifyBundle\Tests\Minifier\Options;

use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\TestCase;
use Sensiolabs\MinifyBundle\Minifier\MinifierInterface;
use Sensiolabs\MinifyBundle\Minifier\Options\HtmlOptions;

#[CoversClass(HtmlOptions::class)]
class HtmlOptionsTest extends TestCase
{
public function testGetTypeReturnsHtml(): void
{
$this->assertSame(MinifierInterface::TYPE_HTML, (new HtmlOptions())->getType());
}

public function testToCliArgsIsEmptyByDefault(): void
{
$this->assertSame([], (new HtmlOptions())->toCliArgs());
}

public function testToCliArgsIncludesKeepDocumentTagsFlag(): void
{
$this->assertSame(
['--html-keep-document-tags'],
(new HtmlOptions(keepDocumentTags: true))->toCliArgs(),
);
}
}
15 changes: 15 additions & 0 deletions tests/Minifier/TraceableMinifierTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
use PHPUnit\Framework\TestCase;
use Psr\Log\LoggerInterface;
use Sensiolabs\MinifyBundle\Minifier\MinifierInterface;
use Sensiolabs\MinifyBundle\Minifier\Options\HtmlOptions;
use Sensiolabs\MinifyBundle\Minifier\TraceableMinifier;

#[CoversClass(TraceableMinifier::class)]
Expand Down Expand Up @@ -64,6 +65,20 @@ public function testMinifyHandlesEmptyInput(): void
$this->assertSame('', $traceableMinifier->minify('', 'css'));
}

public function testMinifyForwardsOptionsToInnerMinifier(): void
{
$options = new HtmlOptions(keepDocumentTags: true);

$minifier = $this->createMock(MinifierInterface::class);
$minifier->expects($this->once())
->method('minify')
->with('input content', 'html', $options)
->willReturn('minified content');

$traceableMinifier = new TraceableMinifier($minifier);
$this->assertSame('minified content', $traceableMinifier->minify('input content', 'html', $options));
}

public function testMinifyHandlesExceptionFromMinifier(): void
{
$this->expectException(\RuntimeException::class);
Expand Down
26 changes: 26 additions & 0 deletions tests/MinifyTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\TestCase;
use Sensiolabs\MinifyBundle\Exception\RuntimeException;
use Sensiolabs\MinifyBundle\Minifier\Options\HtmlOptions;
use Sensiolabs\MinifyBundle\Minify;
use Symfony\Component\Filesystem\Filesystem;

Expand Down Expand Up @@ -57,4 +58,29 @@ public function testMinifyThrowsRuntimeExceptionOnProcessFailure(): void

$minify->minify('input content', 'foo');
}

public function testMinifyForwardsOptionsCliArgs(): void
{
$minify = new Minify(self::FIXTURES_BINARY_PATH);
$output = $minify->minify('<html></html>', 'html', new HtmlOptions(keepDocumentTags: true));

$this->assertSame('<html></html>|args=--html-keep-document-tags', $output);
}

public function testMinifyPassesNoExtraArgsWhenOptionsHaveNoFlags(): void
{
$minify = new Minify(self::FIXTURES_BINARY_PATH);
$output = $minify->minify('<html></html>', 'html', new HtmlOptions());

$this->assertSame('<html></html>|args=', $output);
}

public function testMinifyThrowsWhenOptionsTypeDoesNotMatch(): void
{
$this->expectException(RuntimeException::class);
$this->expectExceptionMessage('Options type "html" does not match minify type "css".');

$minify = new Minify(self::FIXTURES_BINARY_PATH);
$minify->minify('input', 'css', new HtmlOptions());
}
}