Skip to content

Commit d1f26e7

Browse files
committed
Add HTML support (with options!)
1 parent 7315d94 commit d1f26e7

11 files changed

Lines changed: 194 additions & 10 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,6 @@
22
/.php-cs-fixer.cache
33
/composer.lock
44
/phpunit.xml
5+
/tests/Fixtures/config/
56
/tests/Fixtures/var/
67
/vendor/

CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
11
# CHANGELOG
22

3+
## 1.3.0
4+
5+
- Add HTML support (`MinifierInterface::TYPE_HTML`)
6+
- Add options support to `MinifierInterface::minify()` via the `OptionsInterface` DTO (BC-compatible, third argument)
7+
8+
## 1.2.0
9+
10+
- Add Symfony 8 support
11+
312
## 1.1.0
413

514
- Support for PHP 8.1.0 or higher

src/Minifier/MinifierInterface.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,10 @@ interface MinifierInterface
2020
{
2121
public const TYPE_CSS = 'css';
2222
public const TYPE_JS = 'js';
23+
public const TYPE_HTML = 'html';
2324

2425
/**
25-
* @param self::TYPE_CSS|self::TYPE_JS $type
26+
* @param self::TYPE_CSS|self::TYPE_JS|self::TYPE_HTML $type
2627
*/
27-
public function minify(string $input, string $type): string;
28+
public function minify(string $input, string $type/* , ?\Sensiolabs\MinifyBundle\Minifier\Options\OptionsInterface $options = null */): string;
2829
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/*
6+
* This file is part of the SensioLabs MinifyBundle package.
7+
*
8+
* (c) Simon André - Sensiolabs
9+
*
10+
* For the full copyright and license information, please view the LICENSE
11+
* file that was distributed with this source code.
12+
*/
13+
14+
namespace Sensiolabs\MinifyBundle\Minifier\Options;
15+
16+
use Sensiolabs\MinifyBundle\Minifier\MinifierInterface;
17+
18+
final class HtmlOptions implements OptionsInterface
19+
{
20+
/**
21+
* @param bool $keepDocumentTags preserve html, head and body tags
22+
*/
23+
public function __construct(
24+
public readonly bool $keepDocumentTags = false,
25+
) {
26+
}
27+
28+
public function getType(): string
29+
{
30+
return MinifierInterface::TYPE_HTML;
31+
}
32+
33+
public function toCliArgs(): array
34+
{
35+
$args = [];
36+
if ($this->keepDocumentTags) {
37+
$args[] = '--html-keep-document-tags';
38+
}
39+
40+
return $args;
41+
}
42+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/*
6+
* This file is part of the SensioLabs MinifyBundle package.
7+
*
8+
* (c) Simon André - Sensiolabs
9+
*
10+
* For the full copyright and license information, please view the LICENSE
11+
* file that was distributed with this source code.
12+
*/
13+
14+
namespace Sensiolabs\MinifyBundle\Minifier\Options;
15+
16+
use Sensiolabs\MinifyBundle\Minifier\MinifierInterface;
17+
18+
interface OptionsInterface
19+
{
20+
/**
21+
* @return MinifierInterface::TYPE_*
22+
*/
23+
public function getType(): string;
24+
25+
/**
26+
* @return list<string>
27+
*/
28+
public function toCliArgs(): array;
29+
}

src/Minifier/TraceableMinifier.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ public function __construct(
2727
) {
2828
}
2929

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

3838
$timeStart = microtime(true);
39-
$output = $this->minifier->minify($input, $type);
39+
$output = $this->minifier->minify(...\func_get_args());
4040
$timeEnd = microtime(true);
4141

4242
$outputSize = strlen($output);

src/Minify.php

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
use Sensiolabs\MinifyBundle\Exception\RuntimeException;
1717
use Sensiolabs\MinifyBundle\Minifier\MinifierInterface;
18+
use Sensiolabs\MinifyBundle\Minifier\Options\OptionsInterface;
1819
use Symfony\Component\Process\Process;
1920

2021
/**
@@ -27,9 +28,22 @@ public function __construct(
2728
) {
2829
}
2930

30-
public function minify(string $input, string $type): string
31+
public function minify(string $input, string $type/* , ?OptionsInterface $options = null */): string
3132
{
32-
$process = new Process([$this->binaryPath, '--type', $type]);
33+
$options = \func_num_args() > 2 ? \func_get_arg(2) : null;
34+
if ($options !== null && !$options instanceof OptionsInterface) {
35+
throw new RuntimeException(sprintf('Expected $options to be an instance of "%s", got "%s".', OptionsInterface::class, get_debug_type($options)));
36+
}
37+
if ($options !== null && $options->getType() !== $type) {
38+
throw new RuntimeException(sprintf('Options type "%s" does not match minify type "%s".', $options->getType(), $type));
39+
}
40+
41+
$args = [$this->binaryPath, '--type', $type];
42+
if ($options !== null) {
43+
$args = [...$args, ...$options->toCliArgs()];
44+
}
45+
46+
$process = new Process($args);
3347
$process->setInput($input);
3448

3549
try {

tests/Fixtures/bin/fakify

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ if (!isset($argv[1]) || '--type' !== $argv[1] || !isset($argv[2])) {
55
echo 'ERROR: Missing type argument.';
66
exit(1);
77
}
8-
if (!in_array($argv[2], ['css', 'js'])) {
8+
if (!in_array($argv[2], ['css', 'js', 'html'])) {
99
echo 'ERROR: Invalid type argument.';
1010
exit(1);
1111
}
@@ -15,14 +15,20 @@ $input = file_get_contents('php://stdin');
1515

1616
if ('css' === $typeArg) {
1717
file_put_contents('php://stdout', $input);
18-
18+
19+
return;
20+
}
21+
22+
if ('html' === $typeArg) {
23+
$extraArgs = array_slice($argv, 3);
24+
file_put_contents('php://stdout', $input.'|args='.implode(' ', $extraArgs));
25+
1926
return;
2027
}
2128

2229
if ('js' === $typeArg) {
2330
// file_put_contents('php://stdout', $input);
2431
exit(20000000);
25-
32+
2633
return;
2734
}
28-
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/*
6+
* This file is part of the SensioLabs MinifyBundle package.
7+
*
8+
* (c) Simon André - Sensiolabs
9+
*
10+
* For the full copyright and license information, please view the LICENSE
11+
* file that was distributed with this source code.
12+
*/
13+
14+
namespace Sensiolabs\MinifyBundle\Tests\Minifier\Options;
15+
16+
use PHPUnit\Framework\Attributes\CoversClass;
17+
use PHPUnit\Framework\TestCase;
18+
use Sensiolabs\MinifyBundle\Minifier\MinifierInterface;
19+
use Sensiolabs\MinifyBundle\Minifier\Options\HtmlOptions;
20+
21+
#[CoversClass(HtmlOptions::class)]
22+
class HtmlOptionsTest extends TestCase
23+
{
24+
public function testGetTypeReturnsHtml(): void
25+
{
26+
$this->assertSame(MinifierInterface::TYPE_HTML, (new HtmlOptions())->getType());
27+
}
28+
29+
public function testToCliArgsIsEmptyByDefault(): void
30+
{
31+
$this->assertSame([], (new HtmlOptions())->toCliArgs());
32+
}
33+
34+
public function testToCliArgsIncludesKeepDocumentTagsFlag(): void
35+
{
36+
$this->assertSame(
37+
['--html-keep-document-tags'],
38+
(new HtmlOptions(keepDocumentTags: true))->toCliArgs(),
39+
);
40+
}
41+
}

tests/Minifier/TraceableMinifierTest.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
use PHPUnit\Framework\TestCase;
1818
use Psr\Log\LoggerInterface;
1919
use Sensiolabs\MinifyBundle\Minifier\MinifierInterface;
20+
use Sensiolabs\MinifyBundle\Minifier\Options\HtmlOptions;
2021
use Sensiolabs\MinifyBundle\Minifier\TraceableMinifier;
2122

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

68+
public function testMinifyForwardsOptionsToInnerMinifier(): void
69+
{
70+
$options = new HtmlOptions(keepDocumentTags: true);
71+
72+
$minifier = $this->createMock(MinifierInterface::class);
73+
$minifier->expects($this->once())
74+
->method('minify')
75+
->with('input content', 'html', $options)
76+
->willReturn('minified content');
77+
78+
$traceableMinifier = new TraceableMinifier($minifier);
79+
$this->assertSame('minified content', $traceableMinifier->minify('input content', 'html', $options));
80+
}
81+
6782
public function testMinifyHandlesExceptionFromMinifier(): void
6883
{
6984
$this->expectException(\RuntimeException::class);

0 commit comments

Comments
 (0)