diff --git a/config/default.php b/config/default.php index 68d8c55c9..507b4a752 100644 --- a/config/default.php +++ b/config/default.php @@ -191,7 +191,7 @@ 'enabled' => true, // adds `loading="lazy"` attribute (`true` by default) ], 'resize' => [ - 'enabled' => false, // enables image resizing by using the `width` extra attribute (`false` by default) + 'enabled' => false, // enables image resizing by using the `width` or 'height' extra attribute (`false` by default) ], 'responsive' => [ 'enabled' => false, // creates responsive images and add them to the `srcset` attribute (`false` by default) @@ -266,6 +266,9 @@ 'webp' => [ 'enabled' => false, // creates a WebP version of images with `html` filter (`false` by default) ], + 'thumbnails' => [ + 'dir' => 'thumbnails', // where thumbnails are stored (in the assets target directory) + ], ], ], 'postprocess' => [ diff --git a/docs/4-Configuration.md b/docs/4-Configuration.md index f092ef3b9..bf35fa45e 100644 --- a/docs/4-Configuration.md +++ b/docs/4-Configuration.md @@ -709,7 +709,7 @@ assets: variables: [] # list of preset variables (empty by default) minify: enabled: true # enables asset minification (`true` by default) - target: assets # where remote and resized assets are saved + target: assets # where handled assets are stored images: optimize: enabled: false # enables images optimization with JpegOptim, Optipng, Pngquant 2, SVGO 1, Gifsicle, cwebp (`false` by default) @@ -721,6 +721,8 @@ assets: default: '100vw' # `sizes` attribute (`100vw` by default) webp: enabled: false # creates a WebP version of images with `html` filter (`false` by default) + thumbnails: + dir: thumbnails # where thumbnails are stored (in the assets target directory) ``` ::: diff --git a/src/Assets/Asset.php b/src/Assets/Asset.php index 94d12f232..12b1a7494 100644 --- a/src/Assets/Asset.php +++ b/src/Assets/Asset.php @@ -401,24 +401,22 @@ public function optimize(string $filepath): self * * @throws RuntimeException */ - public function resize(int $width): self + public function resize(?int $width = null, ?int $height = null): self { - if ($this->data['type'] != 'image') { - throw new RuntimeException(\sprintf('Not able to resize "%s": it\'s not an image', $this->data['path'])); + if ($width === null && $height === null) { + return $this; } - - if ($width >= $this->getWidth()) { + if ($width >= $this->getWidth() && $height >= $this->getHeight()) { return $this; } $assetResized = clone $this; - $assetResized->data['width'] = $width; $cache = new Cache($this->builder, 'assets'); - $cacheKey = $cache->createKeyFromAsset($assetResized, ["{$width}x"]); + $cacheKey = $cache->createKeyFromAsset($assetResized, ["{$width}x{$height}"]); if (!$cache->has($cacheKey)) { if ($assetResized->data['type'] !== 'image') { - throw new RuntimeException(\sprintf('Not able to resize "%s"', $assetResized->data['path'])); + throw new RuntimeException(\sprintf('Not able to resize "%s": it\'s not an image', $assetResized->data['path'])); } if (!extension_loaded('gd')) { throw new RuntimeException('GD extension is required to use images resize.'); @@ -426,18 +424,24 @@ public function resize(int $width): self try { $img = ImageManager::make($assetResized->data['content_source']); - $img->resize($width, null, function (\Intervention\Image\Constraint $constraint) { + $img->resize($width, $height, function (\Intervention\Image\Constraint $constraint) { $constraint->aspectRatio(); $constraint->upsize(); }); } catch (\Exception $e) { throw new RuntimeException(\sprintf('Not able to resize image "%s": %s', $assetResized->data['path'], $e->getMessage())); } - $assetResized->data['path'] = '/'.Util::joinPath((string) $this->config->get('assets.target'), 'thumbnails', (string) $width, $assetResized->data['path']); + $assetResized->data['width'] = $assetResized->getWidth(); + $assetResized->data['height'] = $assetResized->getHeight(); + $assetResized->data['path'] = '/'.Util::joinPath( + (string) $this->config->get('assets.target'), + (string) $this->config->get('assets.images.thumbnails.dir'), + "{$width}x{$height}", + $assetResized->data['path'] + ); try { $assetResized->data['content'] = (string) $img->encode($assetResized->data['ext'], $this->config->get('assets.images.quality')); - $assetResized->data['height'] = $assetResized->getHeight(); } catch (\Exception $e) { throw new RuntimeException(\sprintf('Not able to encode image "%s": %s', $assetResized->data['path'], $e->getMessage())); } diff --git a/src/Converter/Parsedown.php b/src/Converter/Parsedown.php index 4964948aa..26223bc88 100644 --- a/src/Converter/Parsedown.php +++ b/src/Converter/Parsedown.php @@ -104,20 +104,28 @@ protected function inlineImage($Excerpt) // create asset $asset = new Asset($this->builder, $image['element']['attributes']['src'], ['force_slash' => false]); $image['element']['attributes']['src'] = $asset; - $width = $asset->getWidth(); + $width = null; + $height = null; /** * Should be resized? */ $assetResized = null; - if (isset($image['element']['attributes']['width']) - && (int) $image['element']['attributes']['width'] < $width - && $this->builder->getConfig()->get('body.images.resize.enabled') + if ($this->builder->getConfig()->get('body.images.resize.enabled') + && ( + (isset($image['element']['attributes']['width']) && (int) $image['element']['attributes']['width'] < $asset->getWidth()) + || (isset($image['element']['attributes']['height']) && (int) $image['element']['attributes']['height'] < $asset->getHeight()) + ) ) { - $width = (int) $image['element']['attributes']['width']; + if (isset($image['element']['attributes']['width'])) { + $width = (int) $image['element']['attributes']['width']; + } + if (isset($image['element']['attributes']['height'])) { + $height = (int) $image['element']['attributes']['height']; + } try { - $assetResized = $asset->resize($width); + $assetResized = $asset->resize($width, $height); $image['element']['attributes']['src'] = $assetResized; } catch (\Exception $e) { $this->builder->getLogger()->debug($e->getMessage()); @@ -128,7 +136,7 @@ protected function inlineImage($Excerpt) // set width if (!isset($image['element']['attributes']['width']) && $asset['type'] == 'image') { - $image['element']['attributes']['width'] = $width; + $image['element']['attributes']['width'] = ($assetResized ?? $asset)->getWidth(); } // set height if (!isset($image['element']['attributes']['height']) && $asset['type'] == 'image') { @@ -138,7 +146,7 @@ protected function inlineImage($Excerpt) /** * Should be responsive? */ - if ($this->builder->getConfig()->get('body.images.responsive.enabled')) { + if ($this->builder->getConfig()->get('body.images.responsive.enabled') && false === false) { if ($srcset = Image::buildSrcset( $assetResized ?? $asset, $this->builder->getConfig()->get('assets.images.responsive.widths') ?? [480, 640, 768, 1024, 1366, 1600, 1920] diff --git a/src/Renderer/Twig/Extension.php b/src/Renderer/Twig/Extension.php index 0ea709317..2d2acc008 100644 --- a/src/Renderer/Twig/Extension.php +++ b/src/Renderer/Twig/Extension.php @@ -371,13 +371,13 @@ public function fingerprint($asset): Asset * * @return Asset */ - public function resize($asset, int $size): Asset + public function resize($asset, ?int $width = null, ?int $height = null): Asset { if (!$asset instanceof Asset) { $asset = new Asset($this->builder, $asset); } - return $asset->resize($size); + return $asset->resize($width, $height); } /** diff --git a/tests/fixtures/website/config.php b/tests/fixtures/website/config.php index 660d10802..4b7ca2e0a 100644 --- a/tests/fixtures/website/config.php +++ b/tests/fixtures/website/config.php @@ -171,7 +171,7 @@ 'enabled' => true, ], 'remote' => [ - 'enabled' => false, + 'enabled' => true, ], 'resize' => [ 'enabled' => true, diff --git a/tests/fixtures/website/pages/Assets/images.md b/tests/fixtures/website/pages/Assets/images.md index a4d769bf6..8063225e7 100644 --- a/tests/fixtures/website/pages/Assets/images.md +++ b/tests/fixtures/website/pages/Assets/images.md @@ -15,7 +15,7 @@ typora-root-url: ../../static ## Resize -### Image resized to 100px +### Image resized to 100px width ```markdown ![Alt text](/images/cecil-logo.png){width=100} @@ -23,7 +23,15 @@ typora-root-url: ../../static ![Alt text](/images/cecil-logo.png){width=100} -### External image resized to 250px +### Image resized to 100px height + +```markdown +![Alt text](/images/cecil-logo.png){height=150} +``` + +![Alt text](/images/cecil-logo.png){height=150} + +### External image resized to 250px width ```markdown ![Jamstatic](https://jamstatic.fr/assets/images/twitter-card.png){width=250}