1
0
mirror of https://github.com/BookStackApp/BookStack.git synced 2025-08-07 23:03:00 +03:00

Added SVG support to the image gallery.

This commit is contained in:
Dan Brown
2022-05-22 11:52:42 +01:00
parent 49498cfaf9
commit c9aa1c979f
5 changed files with 36 additions and 9 deletions

View File

@@ -219,6 +219,6 @@ abstract class Controller extends BaseController
*/ */
protected function getImageValidationRules(): array protected function getImageValidationRules(): array
{ {
return ['image_extension', 'mimes:jpeg,png,gif,webp', 'max:' . (config('app.upload_limit') * 1000)]; return ['image_extension', 'mimes:jpeg,png,gif,webp,svg', 'max:' . (config('app.upload_limit') * 1000)];
} }
} }

View File

@@ -30,7 +30,7 @@ class ImageService
protected $image; protected $image;
protected $fileSystem; protected $fileSystem;
protected static $supportedExtensions = ['jpg', 'jpeg', 'png', 'gif', 'webp']; protected static $supportedExtensions = ['jpg', 'jpeg', 'png', 'gif', 'webp', 'svg'];
/** /**
* ImageService constructor. * ImageService constructor.
@@ -230,6 +230,14 @@ class ImageService
return strtolower(pathinfo($image->path, PATHINFO_EXTENSION)) === 'gif'; return strtolower(pathinfo($image->path, PATHINFO_EXTENSION)) === 'gif';
} }
/**
* Check if the given image is an SVG image file.
*/
protected function isSvg(Image $image): bool
{
return strtolower(pathinfo($image->path, PATHINFO_EXTENSION)) === 'svg';
}
/** /**
* Check if the given image and image data is apng. * Check if the given image and image data is apng.
*/ */
@@ -255,8 +263,8 @@ class ImageService
*/ */
public function getThumbnail(Image $image, ?int $width, ?int $height, bool $keepRatio = false): string public function getThumbnail(Image $image, ?int $width, ?int $height, bool $keepRatio = false): string
{ {
// Do not resize GIF images where we're not cropping // Do not resize GIF images where we're not cropping or SVG images.
if ($keepRatio && $this->isGif($image)) { if (($keepRatio && $this->isGif($image)) || $this->isSvg($image)) {
return $this->getPublicUrl($image->path); return $this->getPublicUrl($image->path);
} }

View File

@@ -74,6 +74,23 @@ class ImageTest extends TestCase
$this->assertStringNotContainsString('thumbs-', $imgDetails['response']->thumbs->display); $this->assertStringNotContainsString('thumbs-', $imgDetails['response']->thumbs->display);
} }
public function test_svg_upload()
{
/** @var Page $page */
$page = Page::query()->first();
$admin = $this->getAdmin();
$this->actingAs($admin);
$imgDetails = $this->uploadGalleryImage($page, 'diagram.svg', 'image/svg+xml');
$this->assertFileExists(public_path($imgDetails['path']));
$this->assertTrue(
$imgDetails['response']->url === $imgDetails['response']->thumbs->gallery
&& $imgDetails['response']->url === $imgDetails['response']->thumbs->display,
);
$this->deleteImage($imgDetails['path']);
}
public function test_image_edit() public function test_image_edit()
{ {
$editor = $this->getEditor(); $editor = $this->getEditor();

View File

@@ -3,6 +3,7 @@
namespace Tests\Uploads; namespace Tests\Uploads;
use BookStack\Entities\Models\Page; use BookStack\Entities\Models\Page;
use BookStack\Uploads\Image;
use Illuminate\Http\UploadedFile; use Illuminate\Http\UploadedFile;
use stdClass; use stdClass;
@@ -84,21 +85,19 @@ trait UsesImages
* Returns the image name. * Returns the image name.
* Can provide a page to relate the image to. * Can provide a page to relate the image to.
* *
* @param Page|null $page
*
* @return array{name: string, path: string, page: Page, response: stdClass} * @return array{name: string, path: string, page: Page, response: stdClass}
*/ */
protected function uploadGalleryImage(Page $page = null, ?string $testDataFileName = null) protected function uploadGalleryImage(Page $page = null, string $testDataFileName = 'first-image.png', string $contentType = 'image/png')
{ {
if ($page === null) { if ($page === null) {
$page = Page::query()->first(); $page = Page::query()->first();
} }
$imageName = $testDataFileName ?? 'first-image.png'; $imageName = $testDataFileName;
$relPath = $this->getTestImagePath('gallery', $imageName); $relPath = $this->getTestImagePath('gallery', $imageName);
$this->deleteImage($relPath); $this->deleteImage($relPath);
$upload = $this->uploadImage($imageName, $page->id, 'image/png', $testDataFileName); $upload = $this->uploadImage($imageName, $page->id, $contentType, $testDataFileName);
$upload->assertStatus(200); $upload->assertStatus(200);
return [ return [

View File

@@ -0,0 +1,3 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" style="background-color: rgb(255, 255, 255);" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="121px" height="141px" viewBox="-0.5 -0.5 121 141"><defs/><g><ellipse cx="25" cy="87.5" rx="7.5" ry="7.5" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><path d="M 25 95 L 25 120 M 25 100 L 10 100 M 25 100 L 40 100 M 25 120 L 10 140 M 25 120 L 40 140" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 0 0 L 120 0 L 120 50 L 80 50 L 60 80 L 60 50 L 0 50 Z" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 25px; margin-left: 1px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">Hello!</div></div></div></foreignObject><text x="60" y="29" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">Hello!</text></switch></g></g><switch><g requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"/><a transform="translate(0,-5)" xlink:href="https://www.diagrams.net/doc/faq/svg-export-text-problems" target="_blank"><text text-anchor="middle" font-size="10px" x="50%" y="100%">Text is not SVG - cannot display</text></a></switch></svg>

After

Width:  |  Height:  |  Size: 1.9 KiB