diff --git a/src/Illuminate/Image/Image.php b/src/Illuminate/Image/Image.php index 4a8a644d8c17..299661dbf9b6 100644 --- a/src/Illuminate/Image/Image.php +++ b/src/Illuminate/Image/Image.php @@ -8,6 +8,7 @@ use Illuminate\Contracts\Filesystem\Factory as FilesystemFactory; use Illuminate\Contracts\Image\Driver; use Illuminate\Contracts\Image\Transformation; +use Illuminate\Contracts\Support\Htmlable; use Illuminate\Http\UploadedFile; use Illuminate\Image\Transformations\Blur; use Illuminate\Image\Transformations\Contain; @@ -21,13 +22,14 @@ use Illuminate\Image\Transformations\Rotate; use Illuminate\Image\Transformations\Scale; use Illuminate\Image\Transformations\Sharpen; +use Illuminate\Support\Arr; use Illuminate\Support\Str; use Illuminate\Support\Traits\Conditionable; use Illuminate\Support\Traits\Macroable; use Stringable; use Throwable; -class Image implements Stringable +class Image implements Htmlable, Stringable { use Conditionable, Macroable; @@ -413,6 +415,32 @@ public function toDataUri(): string return 'data:'.$this->mimeType().';base64,'.$this->toBase64(); } + /** + * @param array&string[] $attributes + */ + public function toHtml(array $attributes = []): string + { + $attributes = collect([ + 'src' => $this->toDataUri(), + 'width' => $this->width(), + 'height' => $this->height(), + ]) + ->merge(Arr::mapWithKeys($attributes, function ($value, $key) { + if (is_int($key) && is_string($value)) { + return [$value => true]; + } + + if (is_string($key) && (is_scalar($value) || $value instanceof Stringable || $value === true)) { + return [$key => $value]; + } + + return []; + })) + ->map(fn ($value, $key) => $value === true ? e($key) : sprintf('%s="%s"', e($key), e($value))); + + return 'join(' ').'>'; + } + /** * Get the file extension based on the MIME type. */ diff --git a/tests/Image/ImageTest.php b/tests/Image/ImageTest.php index 08ab3d8f0794..a6da582a07e4 100644 --- a/tests/Image/ImageTest.php +++ b/tests/Image/ImageTest.php @@ -902,6 +902,39 @@ public function test_optimize_sets_both_format_and_quality() $this->assertSame(90, $options->quality); } + public function test_to_html() + { + $image = $this->makeImage(); + $html = $image->toHtml(); + $this->assertStringStartsWith('', $html); + + $result = $image->scale(400, 400); + $html = $image->toHtml(); + $this->assertStringStartsWith('', $html); + } + + public function test_to_html_with_additional_attributes() + { + $image = $this->makeImage(); + + $result = $image->scale(400, 400); + $html = $image->toHtml(['alt' => 'My avatar', 'hidden']); + $this->assertStringStartsWith('', $html); + } + + public function test_to_html_attributes_are_overwritable() + { + $image = $this->makeImage(); + + $result = $image->scale(400, 400); + $html = $image->toHtml(['height' => 42]); + $this->assertStringStartsWith('', $html); + } + public function test_optimize_allows_gif() { $result = $this->makeImage()->optimize('gif');