From 84e90e26c0a257c11ebdd05e01046e1a90e6c9bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20Molakvo=C3=A6=20=28skjnldsv=29?= Date: Mon, 25 Jun 2018 11:17:00 +0200 Subject: [PATCH] Svg color api MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: John Molakvoæ (skjnldsv) --- core/Controller/JsController.php | 4 +- core/Controller/SvgController.php | 97 +++++++++++++++++++++++++++++ core/css/icons.scss | 36 ++++++----- core/routes.php | 1 + lib/private/Template/SCSSCacher.php | 1 + 5 files changed, 121 insertions(+), 18 deletions(-) create mode 100644 core/Controller/SvgController.php diff --git a/core/Controller/JsController.php b/core/Controller/JsController.php index 3fc48e9a38..f91fe8f75d 100644 --- a/core/Controller/JsController.php +++ b/core/Controller/JsController.php @@ -57,8 +57,8 @@ class JsController extends Controller { * @PublicPage * @NoCSRFRequired * - * @param string $fileName css filename with extension - * @param string $appName css folder name + * @param string $fileName js filename with extension + * @param string $appName js folder name * @return FileDisplayResponse|NotFoundResponse */ public function getJs(string $fileName, string $appName): Response { diff --git a/core/Controller/SvgController.php b/core/Controller/SvgController.php new file mode 100644 index 0000000000..b2202f88a2 --- /dev/null +++ b/core/Controller/SvgController.php @@ -0,0 +1,97 @@ + + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +namespace OC\Core\Controller; + +use OCP\AppFramework\Controller; +use OCP\AppFramework\Http; +use OCP\AppFramework\Http\DataDisplayResponse; +use OCP\AppFramework\Http\NotFoundResponse; +use OCP\AppFramework\Utility\ITimeFactory; +use OCP\Files\NotFoundException; +use OCP\IRequest; + +class SvgController extends Controller { + + /** @var string */ + protected $serverRoot; + + /** @var ITimeFactory */ + protected $timeFactory; + + public function __construct(string $appName, + IRequest $request, + ITimeFactory $timeFactory) { + parent::__construct($appName, $request); + + $this->serverRoot = \OC::$SERVERROOT; + $this->timeFactory = $timeFactory; + } + + /** + * @NoAdminRequired + * @NoCSRFRequired + * + * Generate svg from filename with the requested color + * + * @param string $fileName + * @param string $color + * @return DataDisplayResponse|NotFoundException + */ + public function getSvg(string $fileName, $color = 'ffffff') { + $path = $this->serverRoot . "/core/img/actions/$fileName.svg"; + if (!file_exists($path)) { + return new NotFoundResponse(); + } + + $svg = file_get_contents($path); + + if (is_null($svg)) { + return new NotFoundResponse(); + } + + // add fill (fill is not present on black elements) + $fillRe = '/<((circle|rect|path)((?!fill)[a-z0-9 =".\-#])+)\/>/mi'; + + $svg = preg_replace($fillRe, '<$1 fill="#' . $color . '"/>', $svg); + + // replace any fill or stroke colors + $svg = preg_replace('/stroke="#([a-z0-9]{3,6})"/mi', 'stroke="#' . $color . '"', $svg); + $svg = preg_replace('/fill="#([a-z0-9]{3,6})"/mi', 'fill="#' . $color . '"', $svg); + + $response = new DataDisplayResponse($svg, Http::STATUS_OK, ['Content-Type' => 'image/svg+xml']); + + // Set cache control + $ttl = 31536000; + $response->addHeader('Cache-Control', 'max-age=' . $ttl . ', immutable'); + $response->addHeader('Content-Disposition', 'inline; filename="' . $fileName . '.svg"'); + $expires = new \DateTime(); + $expires->setTimestamp($this->timeFactory->getTime()); + $expires->add(new \DateInterval('PT' . $ttl . 'S')); + $response->addHeader('Expires', $expires->format(\DateTime::RFC1123)); + $response->addHeader('Pragma', 'cache'); + + return $response; + } +} \ No newline at end of file diff --git a/core/css/icons.scss b/core/css/icons.scss index 91a90abe27..c78d8eba7c 100644 --- a/core/css/icons.scss +++ b/core/css/icons.scss @@ -109,6 +109,9 @@ img, object, video, button, textarea, input, select, div[contenteditable='true'] .icon-address { background-image: url('../img/actions/address.svg?v=1'); } +.icon-address-white { + background-image: url('#{$webroot}/svg/address/fff?v=1'); +} .icon-audio { background-image: url('../img/actions/audio.svg?v=1'); @@ -140,14 +143,15 @@ img, object, video, button, textarea, input, select, div[contenteditable='true'] .icon-checkmark { background-image: url('../img/actions/checkmark.svg?v=1'); + } .icon-checkmark-white { - background-image: url('../img/actions/checkmark-white.svg?v=1'); + background-image: url('#{$webroot}/svg/icon-checkmark/fff?v=1'); } .icon-checkmark-color { - background-image: url('../img/actions/checkmark-color.svg?v=1'); + background-image: url('#{$webroot}/svg/icon-checkmark/#{$color-success}?v=1'); } .icon-clippy { @@ -159,7 +163,7 @@ img, object, video, button, textarea, input, select, div[contenteditable='true'] } .icon-close-white { - background-image: url('../img/actions/close-white.svg?v=1'); + background-image: url('#{$webroot}/svg/close/fff?v=1'); } .icon-comment { @@ -175,7 +179,7 @@ img, object, video, button, textarea, input, select, div[contenteditable='true'] } .icon-confirm-white { - background-image: url('../img/actions/confirm-white.svg?v=2'); + background-image: url('#{$webroot}/svg/icon-confirm/fff?v=1'); } .icon-delete { @@ -188,22 +192,22 @@ img, object, video, button, textarea, input, select, div[contenteditable='true'] } &:hover, &:focus { - background-image: url('../img/actions/delete-hover.svg?v=1'); + background-image: url('#{$webroot}/svg/icon-delete/d40000?v=1'); filter: initial; } } .icon-delete-white { - background-image: url('../img/actions/delete-white.svg?v=1'); + background-image: url('#{$webroot}/svg/icon-delete/fff?v=1'); &.no-permission { &:hover, &:focus { - background-image: url('../img/actions/delete-white.svg?v=1'); + background-image: url('#{$webroot}/svg/icon-delete/fff?v=1'); } } &:hover, &:focus { - background-image: url('../img/actions/delete-hover.svg?v=1'); + background-image: url('#{$webroot}/svg/icon-delete/d40000?v=1'); } } @@ -216,7 +220,7 @@ img, object, video, button, textarea, input, select, div[contenteditable='true'] } .icon-download-white { - background-image: url('../img/actions/download-white.svg?v=1'); + background-image: url('#{$webroot}/svg/icon-download/fff?v=1'); } .icon-edit { @@ -228,11 +232,11 @@ img, object, video, button, textarea, input, select, div[contenteditable='true'] } .icon-error-white { - background-image: url('../img/actions/error-white.svg?v=1'); + background-image: url('#{$webroot}/svg/icon-error/fff?v=1'); } .icon-error-color { - background-image: url('../img/actions/error-color.svg?v=1'); + background-image: url('#{$webroot}/svg/icon-error/d40000?v=1'); } .icon-external { @@ -258,7 +262,7 @@ img, object, video, button, textarea, input, select, div[contenteditable='true'] } .icon-info-white { - background-image: url('../img/actions/info-white.svg?v=1'); + background-image: url('#{$webroot}/svg/icon-info/fff?v=1'); } .icon-logout { @@ -278,7 +282,7 @@ img, object, video, button, textarea, input, select, div[contenteditable='true'] } .icon-more-white { - background-image: url('../img/actions/more-white.svg?v=1'); + background-image: url('#{$webroot}/svg/more/fff?v=1'); } .icon-password { @@ -342,7 +346,7 @@ img, object, video, button, textarea, input, select, div[contenteditable='true'] } .icon-search-white { - background-image: url('../img/actions/search-white.svg?v=1'); + background-image: url('#{$webroot}/svg/search/fff?v=1'); } .icon-settings { @@ -354,7 +358,7 @@ img, object, video, button, textarea, input, select, div[contenteditable='true'] } .icon-settings-white { - background-image: url('../img/actions/settings-white.svg?v=1'); + background-image: url('#{$webroot}/svg/settings-dark/fff?v=1'); } /* always use icon-shared, AdBlock blocks icon-share */ @@ -435,7 +439,7 @@ img, object, video, button, textarea, input, select, div[contenteditable='true'] } .icon-upload-white { - background-image: url('../img/actions/upload-white.svg?v=1'); + background-image: url('#{$webroot}/svg/upload/fff?v=1'); } .icon-user { diff --git a/core/routes.php b/core/routes.php index c5df3a362f..75e6f52a49 100644 --- a/core/routes.php +++ b/core/routes.php @@ -61,6 +61,7 @@ $application->registerRoutes($this, [ ['name' => 'OCJS#getConfig', 'url' => '/core/js/oc.js', 'verb' => 'GET'], ['name' => 'Preview#getPreviewByFileId', 'url' => '/core/preview', 'verb' => 'GET'], ['name' => 'Preview#getPreview', 'url' => '/core/preview.png', 'verb' => 'GET'], + ['name' => 'Svg#getSvg', 'url' => '/svg/{fileName}/{color}', 'verb' => 'GET'], ['name' => 'Css#getCss', 'url' => '/css/{appName}/{fileName}', 'verb' => 'GET'], ['name' => 'Js#getJs', 'url' => '/js/{appName}/{fileName}', 'verb' => 'GET'], ['name' => 'contactsMenu#index', 'url' => '/contactsmenu/contacts', 'verb' => 'POST'], diff --git a/lib/private/Template/SCSSCacher.php b/lib/private/Template/SCSSCacher.php index 6e25e1fa5d..d7cea03228 100644 --- a/lib/private/Template/SCSSCacher.php +++ b/lib/private/Template/SCSSCacher.php @@ -233,6 +233,7 @@ class SCSSCacher { // Compile try { $compiledScss = $scss->compile( + '$webroot: \'' . \OC::$WEBROOT. '\';'. '@import "variables.scss";' . $this->getInjectedVariables() . '@import "'.$fileNameSCSS.'";');