Add lazyloading and PNG support

This commit is contained in:
philipp lang 2021-09-14 02:13:29 +02:00
parent b6d80009f5
commit 00aa2469a7
7 changed files with 80 additions and 9 deletions

View File

@ -97,10 +97,11 @@ class Plugin extends PluginBase
public function registerMarkupTags() { public function registerMarkupTags() {
return [ return [
'filters' => [ 'filters' => [
'resize' => fn ($media, $size = 'original', $sizes = null) => app(CacheManager::class)->get( 'resize' => fn ($media, $size = 'original', $sizes = null, $options = []) => app(CacheManager::class)->get(
new MediaPath($media), new MediaPath($media),
$size, $size,
$sizes, $sizes,
$options,
) )
] ]
]; ];

View File

@ -16,11 +16,11 @@ class CacheManager
$this->tagGenerator = $tagGenerator; $this->tagGenerator = $tagGenerator;
} }
public function get(MediaPath $path, string $size, ?string $sizes): string public function get(MediaPath $path, string $size, ?string $sizes, array $options = []): string
{ {
return Cache::tags($this->pathTag($path, $size))->rememberForever( return Cache::tags($this->pathTag($path, $size))->rememberForever(
$this->cacheKey($path, $size), $this->cacheKey($path, $size),
fn () => $this->tagGenerator->generate($path, $size, $sizes) fn () => $this->tagGenerator->generate($path, $size, $sizes, $options)
); );
} }

View File

@ -17,6 +17,9 @@ class TagGenerator {
public array $breakpoints; public array $breakpoints;
public $path; public $path;
private CompressorFactory $compressorFactory; private CompressorFactory $compressorFactory;
private $defaultOptions = [
'lazy' => false,
];
public function __construct(CompressorFactory $compressorFactory) public function __construct(CompressorFactory $compressorFactory)
{ {
@ -62,8 +65,9 @@ class TagGenerator {
: null; : null;
} }
public function generate(MediaPath $path, ?string $ratio = 'original', $sizes = null): string public function generate(MediaPath $path, ?string $ratio = 'original', $sizes = null, array $options = []): string
{ {
$options = array_merge($this->defaultOptions, $options);
$this->path = $path; $this->path = $path;
try { try {
@ -90,8 +94,8 @@ class TagGenerator {
'width' => $files->last()->get('width'), 'width' => $files->last()->get('width'),
'height' => $files->last()->get('height'), 'height' => $files->last()->get('height'),
'sizes' => $sizes->implode(', '), 'sizes' => $sizes->implode(', '),
'srcset' => $srcset->implode(', '), $options['lazy'] ? 'data-srcset' : 'srcset' => $srcset->implode(', '),
'src' => $files->last()->get('url'), $options['lazy'] ? 'data-src' : 'src' => $files->last()->get('url'),
])); ]));
} }

View File

@ -11,6 +11,7 @@ class Factory
public array $types = [ public array $types = [
'image/jpeg' => JpgCompressor::class, 'image/jpeg' => JpgCompressor::class,
'image/png' => PngCompressor::class,
]; ];
public function fromMedia(string $mediaPath): Compressor public function fromMedia(string $mediaPath): Compressor

View File

@ -0,0 +1,25 @@
<?php
namespace Aweos\Resizer\Compressors;
class PngCompressor extends Compressor {
public function make(string $path): array
{
$output = "/tmp/".str_slug(microtime());
$mimetype = mime_content_type($path);
system('imagemin '.escapeshellarg($path).' --plugin=pngquant > '.escapeshellarg($output));
system("mv ".escapeshellarg($output)." ".escapeshellarg($path));
return [
$path => [$path],
];
}
public function shouldGenerateVersions(): bool
{
return true;
}
}

View File

@ -38,6 +38,34 @@ class ImageTagTest extends TestCase
); );
} }
public function testItGeneratesLazyLoadingTags()
{
Setting::set('folders', ['pages']);
Setting::set('sizes', []);
Setting::set('breakpoints', [100]);
$this->media->put('/pages/test.jpg', UploadedFile::fake()->image('test.jpg', 500, 500)->get());
UploadedFile::fake()->image('test.jpg', 100, 100)->storeAs('uploads/public/c/pages', 'test-100x100.jpg', 'local');
$this->assertEquals(
'width="100" height="100" sizes="(max-width: 100px) 100px" data-srcset="/storage/uploads/public/c/pages/test-100x100.jpg 100w" data-src="/storage/uploads/public/c/pages/test-100x100.jpg"',
app(CacheManager::class)->get(new MediaPath('pages/test.jpg'), 'original', null, ['lazy' => true]),
);
}
public function testItGeneratesPngImages()
{
Setting::set('folders', ['pages']);
Setting::set('sizes', []);
Setting::set('breakpoints', [100,200]);
$this->media->put('/pages/test.png', UploadedFile::fake()->image('test.png', 500, 500)->get());
UploadedFile::fake()->image('test.png', 100, 100)->storeAs('uploads/public/c/pages', 'test-100x100.png', 'local');
$this->assertEquals(
'width="100" height="100" sizes="(max-width: 100px) 100px" srcset="/storage/uploads/public/c/pages/test-100x100.png 100w" src="/storage/uploads/public/c/pages/test-100x100.png"',
app(CacheManager::class)->get(new MediaPath('pages/test.png'), 'original', null),
);
}
public function testItSkipsImagesWithWrongAspectRatio() public function testItSkipsImagesWithWrongAspectRatio()
{ {
Setting::set('folders', ['pages']); Setting::set('folders', ['pages']);

View File

@ -171,18 +171,30 @@ class ResizerTest extends TestCase
$this->assertHasFile('pages/neu/test-100x80.jpg'); $this->assertHasFile('pages/neu/test-100x80.jpg');
} }
public function testDontGenerateSvgImage(): void public function testDontGenerateSvgImageVesions(): void
{ {
Setting::set('folders', [['folder' => '/pages']]); Setting::set('folders', [['folder' => '/pages']]);
Setting::set('sizes', []); Setting::set('sizes', []);
Setting::set('breakpoints', ['100']); Setting::set('breakpoints', ['100']);
$file = UploadedFile::fake()->image('test.jpg', 500, 400);
$media = MediaLibrary::instance(); $media = MediaLibrary::instance();
$media->put('/pages/test.svg', file_get_contents(__DIR__.'/stub/close.svg')); $media->put('/pages/test.svg', file_get_contents(__DIR__.'/stub/close.svg'));
Event::fire('media.file.upload', [null, '/pages/test.svg', null]); Event::fire('media.file.upload', [null, '/pages/test.svg', null]);
$this->assertFileCount(0, 'pages/neu'); $this->assertFileCount(1, 'pages');
}
public function testGeneratePngImage(): void
{
Setting::set('folders', [['folder' => '/pages']]);
Setting::set('sizes', []);
Setting::set('breakpoints', ['100']);
$media = MediaLibrary::instance();
$media->put('/pages/test.png', UploadedFile::fake()->image('test.png', 500, 500)->get());
Event::fire('media.file.upload', [null, '/pages/test.png', null]);
$this->assertHasFile('pages/test-100x100.png');
} }
} }