diff --git a/src/DependencyInjection/Configuration.php b/src/DependencyInjection/Configuration.php
index 3fdc6ce..bfcdc28 100644
--- a/src/DependencyInjection/Configuration.php
+++ b/src/DependencyInjection/Configuration.php
@@ -434,6 +434,12 @@ private function getIconsNode(string $info): ArrayNodeDefinition
->treatTrueLike([])
->treatNullLike([])
->arrayPrototype()
+ ->beforeNormalization()
+ ->ifString()
+ ->then(static fn (string $v): array => [
+ 'src' => $v,
+ ])
+ ->end()
->children()
->scalarNode('src')
->isRequired()
@@ -502,6 +508,12 @@ private function getScreenshotsNode(string $info): ArrayNodeDefinition
->treatTrueLike([])
->treatNullLike([])
->arrayPrototype()
+ ->beforeNormalization()
+ ->ifString()
+ ->then(static fn (string $v): array => [
+ 'src' => $v,
+ ])
+ ->end()
->children()
->scalarNode('src')
->info('The path to the screenshot. Can be served by Asset Mapper.')
diff --git a/src/Normalizer/IconNormalizer.php b/src/Normalizer/IconNormalizer.php
index 77bc4af..599e2d2 100644
--- a/src/Normalizer/IconNormalizer.php
+++ b/src/Normalizer/IconNormalizer.php
@@ -5,14 +5,18 @@
namespace SpomkyLabs\PwaBundle\Normalizer;
use SpomkyLabs\PwaBundle\Dto\Icon;
+use SpomkyLabs\PwaBundle\ImageProcessor\ImageProcessor;
use Symfony\Component\AssetMapper\AssetMapperInterface;
+use Symfony\Component\AssetMapper\MappedAsset;
+use Symfony\Component\Mime\MimeTypes;
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
use function assert;
final readonly class IconNormalizer implements NormalizerInterface
{
public function __construct(
- private AssetMapperInterface $assetMapper
+ private AssetMapperInterface $assetMapper,
+ private null|ImageProcessor $imageProcessor,
) {
}
@@ -20,17 +24,20 @@ public function normalize(mixed $object, string $format = null, array $context =
{
assert($object instanceof Icon);
$url = null;
+ $asset = null;
if (! str_starts_with($object->src, '/')) {
- $url = $this->assetMapper->getAsset($object->src)?->publicPath;
+ $asset = $this->assetMapper->getAsset($object->src);
+ $url = $asset?->publicPath;
}
if ($url === null) {
$url = $object->src;
}
+ $format = $this->getFormat($object, $asset);
$result = [
'src' => $url,
'sizes' => $object->getSizeList(),
- 'type' => $object->format,
+ 'type' => $format,
'purpose' => $object->purpose,
];
@@ -56,4 +63,18 @@ public function getSupportedTypes(?string $format): array
Icon::class => true,
];
}
+
+ private function getFormat(Icon $object, ?MappedAsset $asset): ?string
+ {
+ if ($object->format !== null) {
+ return $object->format;
+ }
+
+ if ($this->imageProcessor === null || $asset === null || ! class_exists(MimeTypes::class)) {
+ return null;
+ }
+
+ $mime = MimeTypes::getDefault();
+ return $mime->guessMimeType($asset->sourcePath);
+ }
}
diff --git a/src/Twig/PwaRuntime.php b/src/Twig/PwaRuntime.php
index 6d38a51..11b7d99 100644
--- a/src/Twig/PwaRuntime.php
+++ b/src/Twig/PwaRuntime.php
@@ -22,14 +22,40 @@ public function __construct(
$this->manifestPublicUrl = '/' . trim($manifestPublicUrl, '/');
}
- public function load(): string
+ public function load(bool $themeColor = true, bool $icons = true): string
{
$url = $this->assetMapper->getPublicPath($this->manifestPublicUrl) ?? $this->manifestPublicUrl;
$output = sprintf('', $url);
- if ($this->manifest->themeColor !== null) {
+ if ($this->manifest->icons !== [] && $icons === true) {
+ foreach ($this->manifest->icons as $icon) {
+ $iconUrl = $this->getIconPublicUrl($icon->src);
+ $output .= sprintf(
+ '%s',
+ PHP_EOL,
+ str_contains($icon->purpose ?? '', 'maskable') ? 'mask-icon' : 'icon',
+ $icon->getSizeList(),
+ $iconUrl
+ );
+ }
+ }
+ if ($this->manifest->themeColor !== null && $themeColor === true) {
$output .= sprintf('%s', PHP_EOL, $this->manifest->themeColor);
}
return $output;
}
+
+ private function getIconPublicUrl(string $source): ?string
+ {
+ $url = null;
+ if (! str_starts_with($source, '/')) {
+ $asset = $this->assetMapper->getAsset($source);
+ $url = $asset?->publicPath;
+ }
+ if ($url === null) {
+ $url = $source;
+ }
+
+ return $url;
+ }
}
diff --git a/tests/config.php b/tests/config.php
index ae83477..befd97e 100644
--- a/tests/config.php
+++ b/tests/config.php
@@ -114,16 +114,7 @@
'scope' => '/app/',
'start_url' => 'https://example.com',
'theme_color' => 'red',
- 'screenshots' => [
- [
- 'src' => 'pwa/screenshots/360x800.svg',
- 'platform' => 'android',
- 'format' => 'png',
- 'label' => '360x800',
- 'width' => 360,
- 'height' => 800,
- ],
- ],
+ 'screenshots' => ['pwa/screenshots/360x800.svg'],
'share_target' => [
'action' => 'shared_content_receiver',
'action_params' => [
@@ -154,21 +145,11 @@
'name' => 'New reminder',
'url' => '/create/reminder',
'icons' => [
+ 'pwa/1920x1920.svg',
[
'src' => 'pwa/1920x1920.svg',
- 'sizes' => [48, 72, 96, 128, 256],
- 'format' => 'webp',
- ],
- [
- 'src' => 'pwa/1920x1920.svg',
- 'sizes' => [48, 72, 96, 128, 256],
- 'format' => 'png',
'purpose' => 'maskable',
],
- [
- 'src' => 'pwa/1920x1920.svg',
- 'sizes' => [0],
- ],
],
],
],