Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: thumbnails #185

Merged
merged 3 commits into from
Dec 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
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
8 changes: 6 additions & 2 deletions config/services.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -82,10 +82,14 @@ services:
class: Sigwin\YASSG\Bridge\Symfony\HttpKernel\Fragment\RelativeUrlInlineFragmentRenderer
decorates: fragment.renderer.inline

sigwin_yassg.file_decoder.caching_file_decoder:
sigwin_yassg.file_decoder.thumbnail_queue_file_decoder:
class: Sigwin\YASSG\Decoder\CachingFileDecoder
decorates: 'Sigwin\YASSG\FileDecoder'

decoration_priority: 200
sigwin_yassg.file_decoder.caching_file_decoder:
class: Sigwin\YASSG\Decoder\ThumbnailQueueFileDecoder
decorates: 'Sigwin\YASSG\FileDecoder'
decoration_priority: 100
Sigwin\YASSG\FileDecoder:
class: Sigwin\YASSG\Decoder\CompositeFileDecoder
arguments:
Expand Down
27 changes: 27 additions & 0 deletions psalm.baseline.xml
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,19 @@
<code>PaginatorExtension</code>
</UnusedClass>
</file>
<file src="src/Bridge/Twig/Extension/ThumbnailExtension.php">
<MixedArgument>
<code><![CDATA[$GLOBALS['YASSG_BASEDIR']]]></code>
<code><![CDATA[$context['_path']]]></code>
</MixedArgument>
<PossiblyUndefinedStringArrayOffset>
<code><![CDATA[$GLOBALS['YASSG_BASEDIR']]]></code>
<code><![CDATA[$context['_path']]]></code>
</PossiblyUndefinedStringArrayOffset>
<UnusedClass>
<code>ThumbnailExtension</code>
</UnusedClass>
</file>
<file src="src/Collection.php">
<PossiblyUnusedMethod>
<code>column</code>
Expand Down Expand Up @@ -536,7 +549,16 @@
<code>MarkdownFileDecoder</code>
</UnusedClass>
</file>
<file src="src/Decoder/ThumbnailQueueFileDecoder.php">
<UnusedClass>
<code>ThumbnailQueueFileDecoder</code>
</UnusedClass>
</file>
<file src="src/Decoder/YamlFileDecoder.php">
<MixedReturnTypeCoercion>
<code>$data</code>
<code>array</code>
</MixedReturnTypeCoercion>
<UnusedClass>
<code>YamlFileDecoder</code>
</UnusedClass>
Expand Down Expand Up @@ -648,6 +670,11 @@
<code>array</code>
</PossiblyUnusedReturnValue>
</file>
<file src="src/ThumbnailQueue.php">
<PossiblyUnusedMethod>
<code>__construct</code>
</PossiblyUnusedMethod>
</file>
<file src="tests/functional/site/src/Bridge/Symfony/EventSubscriber.php">
<UnusedClass>
<code>EventSubscriber</code>
Expand Down
47 changes: 47 additions & 0 deletions src/Bridge/Twig/Extension/ThumbnailExtension.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<?php

declare(strict_types=1);

/*
* This file is part of the Sigwin Yassg project.
*
* (c) sigwin.hr
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/

namespace Sigwin\YASSG\Bridge\Twig\Extension;

use Sigwin\YASSG\ThumbnailQueue;
use Symfony\Component\Asset\Packages;
use Twig\Extension\AbstractExtension;
use Twig\TwigFunction;

final class ThumbnailExtension extends AbstractExtension
{
public function __construct(private readonly Packages $packages, private readonly ThumbnailQueue $thumbnailQueue) {}

public function getFunctions(): array
{
return [
new TwigFunction('yassg_thumbnail', function (array $context, string $path): string {
if (str_starts_with($path, './')) {
$newPath = realpath(\dirname($context['_path']).'/'.$path);
if ($newPath === false) {
throw new \RuntimeException('Invalid thumbnail path '.$path);
}
$path = $newPath;
}

$relative = str_replace($GLOBALS['YASSG_BASEDIR'], '', $path);
$this->thumbnailQueue->add([
'source' => $path,
'destination' => $relative,
]);

return $this->packages->getUrl(ltrim($relative, '/'));
}, ['needs_context' => true]),
];
}
}
2 changes: 1 addition & 1 deletion src/Decoder/CachingFileDecoder.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public function decode(\SplFileInfo $file): array

$item = $this->cachePoolItem->getItem($key);
if ($item->isHit()) {
/** @var array $value */
/** @var array<string, string> $value */
$value = $item->get();

return $value;
Expand Down
7 changes: 6 additions & 1 deletion src/Decoder/MarkdownFileDecoder.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
use League\CommonMark\ConverterInterface;
use League\CommonMark\Extension\FrontMatter\FrontMatterProviderInterface;
use Sigwin\YASSG\FileDecoder;
use Sigwin\YASSG\ThumbnailQueue;
use Symfony\Component\Yaml\Exception\ParseException;
use Symfony\Component\Yaml\Yaml;
use Twig\Environment;
Expand All @@ -26,7 +27,7 @@

private const EXTENSIONS = ['md', 'markdown'];

public function __construct(private ConverterInterface $converter, private Environment $twig) {}
public function __construct(private ConverterInterface $converter, private Environment $twig, private ThumbnailQueue $thumbnailQueue) {}

public function decode(\SplFileInfo $file): array
{
Expand All @@ -41,6 +42,7 @@ public function decode(\SplFileInfo $file): array
}

$metadata = [];
$thumbnails = [];
if (str_contains($content, '{{') || str_contains($content, '{%')) {
if (str_starts_with($content, '---')) {
$end = mb_strpos($content, '---', 3);
Expand All @@ -59,7 +61,9 @@ public function decode(\SplFileInfo $file): array

$content = $this->twig->createTemplate($content)->render([
'item' => $metadata,
'_path' => $file->getPathname(),
]);
$thumbnails = $this->thumbnailQueue->flush();
}

$result = $this->converter->convert($content);
Expand All @@ -68,6 +72,7 @@ public function decode(\SplFileInfo $file): array
$metadata = $result->getFrontMatter();
}
$metadata['body'] = $result->getContent();
$metadata['@thumbnails'] = $thumbnails;

return $metadata;
}
Expand Down
45 changes: 45 additions & 0 deletions src/Decoder/ThumbnailQueueFileDecoder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?php

declare(strict_types=1);

/*
* This file is part of the Sigwin Yassg project.
*
* (c) sigwin.hr
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/

namespace Sigwin\YASSG\Decoder;

use Sigwin\YASSG\FileDecoder;
use Sigwin\YASSG\ThumbnailQueue;

/**
* @psalm-import-type TThumbnailOptions from \Sigwin\YASSG\ThumbnailQueue
*/
final readonly class ThumbnailQueueFileDecoder implements FileDecoder
{
public function __construct(private FileDecoder $decoder, private ThumbnailQueue $thumbnailQueue) {}

public function supports(\SplFileInfo $file): bool
{
return $this->decoder->supports($file);
}

public function decode(\SplFileInfo $file): array
{
/** @var array{"@thumbnails"?: list<TThumbnailOptions>} $decoded */
$decoded = $this->decoder->decode($file);

if (isset($decoded['@thumbnails'])) {
foreach ($decoded['@thumbnails'] as $thumbnail) {
$this->thumbnailQueue->add($thumbnail);
}
}
unset($decoded['@thumbnails']);

return $decoded;
}
}
3 changes: 3 additions & 0 deletions src/FileDecoder.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,8 @@ interface FileDecoder
{
public function supports(\SplFileInfo $file): bool;

/**
* @return array<string, mixed>
*/
public function decode(\SplFileInfo $file): array;
}
16 changes: 15 additions & 1 deletion src/Generator.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,13 @@
*/
final readonly class Generator
{
public function __construct(private string $buildDir, private Permutator $permutator, private UrlGeneratorInterface $urlGenerator, private KernelInterface $kernel, private Filesystem $filesystem) {}
public function __construct(private string $buildDir, private Permutator $permutator, private UrlGeneratorInterface $urlGenerator, private KernelInterface $kernel, private Filesystem $filesystem, private ThumbnailQueue $thumbnailQueue) {}

/**
* @param callable(Request, Response, string): void $callable
*
* @throws \Exception
*/
public function generate(callable $callable): void
{
$requestContext = $this->urlGenerator->getContext();
Expand Down Expand Up @@ -71,6 +76,10 @@ public function generate(callable $callable): void

$response = $this->dumpRequest($callable, $request);
$urlSet->addUrl(new UrlConcrete($url, new \DateTimeImmutable($response->headers->get('Last-Modified', 'now'))));

$this->thumbnailQueue->flush(function (array $item) use ($callable): void {
$callable($this->createRequest($item['destination']), new Response('OK'), $item['destination']);
});
}
if ($urlSet !== null) {
$this->dumpSitemap($urlSet, $deflate);
Expand Down Expand Up @@ -105,6 +114,11 @@ private function generateUrl(string $path): string
return sprintf('%1$s://%2$s%3$s%4$s', $context->getScheme(), $context->getHost(), $context->getBaseUrl(), $path);
}

/**
* @param callable(Request, Response, string): void $callable
*
* @throws \Exception
*/
private function dumpRequest(callable $callable, Request $request, int $expectedStatusCode = 200): Response
{
try {
Expand Down
62 changes: 62 additions & 0 deletions src/ThumbnailQueue.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<?php

declare(strict_types=1);

/*
* This file is part of the Sigwin Yassg project.
*
* (c) sigwin.hr
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/

namespace Sigwin\YASSG;

use Symfony\Component\Filesystem\Filesystem;

/**
* @psalm-type TThumbnailOptions = array{source: string, destination: string}
*/
final class ThumbnailQueue
{
/**
* @var array<string, TThumbnailOptions>
*/
private array $queue = [];

public function __construct(private string $buildDir, private Filesystem $filesystem) {}

/**
* @param TThumbnailOptions $specification
*/
public function add(array $specification): void
{
$this->queue[$specification['destination']] = $specification;
}

/**
* @param callable(TThumbnailOptions): void $callable
*
* @return list<TThumbnailOptions>
*/
public function flush(?callable $callable = null): array
{
foreach ($this->queue as $specification) {
$destination = $this->buildDir.'/'.ltrim($specification['destination'], '/');
if (file_exists($destination)) {
continue;
}

// TODO: ImgProxy
$this->filesystem->copy($specification['source'], $destination);
if ($callable !== null) {
$callable($specification);
}
}
$queue = array_values($this->queue);
$this->queue = [];

return $queue;
}
}
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: Images!
slug: images
publishedAt: "2022-07-20 12:35:00"
image: assets/images/sigwin.svg
image: ./image.webp
---

| Column 1 | Column 2 | Column 3 |
Expand All @@ -13,7 +13,7 @@ image: assets/images/sigwin.svg

This is a database lookup example: {{yassg_get('articles', '/hello-world.md').title}}

This is an asset lookup: {{asset(item.image)}}
This is an asset lookup: {{ yassg_thumbnail(item.image) }}

![Logo]({{ asset(item.image) }})
![Logo]({{ yassg_thumbnail(item.image) }})

Binary file not shown.
4 changes: 2 additions & 2 deletions tests/functional/site/fixtures/en/article/images/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ <h1>Images!</h1>
</tbody>
</table>
<p>This is a database lookup example: Hello World!</p>
<p>This is an asset lookup: /sub/dir/another/assets/images/sigwin.6f9a3d5b.svg</p>
<p><img src="/sub/dir/another/assets/images/sigwin.6f9a3d5b.svg" alt="Logo" /></p>
<p>This is an asset lookup: /sub/dir/another/content/articles/images/image.webp</p>
<p><img src="/sub/dir/another/content/articles/images/image.webp" alt="Logo" /></p>

</div>
</div>
Expand Down
Loading