Merge pull request #32326 from nextcloud/fix/icons-cacher

pull/32335/head
John Molakvoæ 2 years ago committed by GitHub
commit 5a0b28d603
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -42,6 +42,9 @@ jobs:
npm ci
npm run build --if-present
- name: Build icons css
run: npm run sass:icons
- name: Check webpack build changes
run: |
bash -c "[[ ! \"`git status --porcelain `\" ]] || exit 1"

@ -2,14 +2,14 @@
This file is licensed under the Affero General Public License version 3 or later.
See the COPYING-README file. */
#encryptAllError
, #encryptAllSuccess
, #recoveryEnabledError
, #recoveryEnabledSuccess {
#encryptAllError,
#encryptAllSuccess,
#recoveryEnabledError,
#recoveryEnabledSuccess {
display: none;
}
/* icons for sidebar */
.nav-icon-basic-encryption-module {
@include icon-color('app', 'encryption', $color-black);
background-image: var(--icon-encryption-dark);
}

@ -133,7 +133,7 @@
@include icon-color('recent', 'files', $color-black);
}
.nav-icon-favorites {
@include icon-color('star-dark', 'actions', $color-black, 2, true);
@include icon-color('starred', 'actions', $color-black, 2, true);
}
.nav-icon-sharingin,
.nav-icon-sharingout,
@ -157,7 +157,7 @@
@include icon-color('unshare', 'files', $color-black);
}
.nav-icon-favorites-starred {
@include icon-color('star-dark', 'actions', $color-yellow, 2, true);
@include icon-color('starred', 'actions', $color-yellow, 2, true);
}
#app-navigation .nav-files a.nav-icon-files {

@ -150,5 +150,5 @@
}
.nav-icon-external-storage {
@include icon-color('app-dark', 'files_external', $color-black);
background-image: var(--icon-external-dark);
}

@ -100,13 +100,12 @@ export default {
this.themes.forEach(theme => {
if (theme.id === id && enabled) {
theme.enabled = true
document.body.setAttribute(`data-theme-${theme.id}`, true)
return
}
theme.enabled = false
document.body.removeAttribute(`data-theme-${theme.id}`)
})
this.updateBodyAttributes()
this.selectItem(enabled, id)
},
changeFont({ enabled, id }) {
@ -114,16 +113,24 @@ export default {
this.fonts.forEach(font => {
if (font.id === id && enabled) {
font.enabled = true
document.body.setAttribute(`data-theme-${font.id}`, true)
return
}
font.enabled = false
document.body.removeAttribute(`data-theme-${font.id}`)
})
this.updateBodyAttributes()
this.selectItem(enabled, id)
},
updateBodyAttributes() {
const enabledThemesIDs = this.themes.filter(theme => theme.enabled === true).map(theme => theme.id)
this.themes.forEach(theme => {
document.body.toggleAttribute(`data-theme-${theme.id}`, theme.enabled)
})
document.body.setAttribute('data-themes', enabledThemesIDs.join(','))
},
/**
* Commit a change and force reload css
* Fetching the file again will trigger the server update

@ -1,151 +0,0 @@
<?php
declare(strict_types=1);
/**
* @copyright Copyright (c) 2018, John Molakvoæ (skjnldsv@protonmail.com)
*
* @author Christoph Wurst <christoph@winzerhof-wurst.at>
* @author Daniel Kesselberg <mail@danielkesselberg.de>
* @author Joas Schilling <coding@schilljs.com>
* @author John Molakvoæ <skjnldsv@protonmail.com>
* @author Julius Härtl <jus@bitgrid.net>
* @author Roeland Jago Douma <roeland@famdouma.nl>
* @author Thomas Citharel <nextcloud@tcit.fr>
*
* @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 <http://www.gnu.org/licenses/>.
*
*/
namespace OC\Core\Controller;
use OC\Files\Filesystem;
use OC\Template\IconsCacher;
use OCP\App\AppPathNotFoundException;
use OCP\App\IAppManager;
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\IRequest;
class SvgController extends Controller {
/** @var string */
protected $serverRoot;
/** @var ITimeFactory */
protected $timeFactory;
/** @var IAppManager */
protected $appManager;
/** @var IconsCacher */
private $iconsCacher;
public function __construct(string $appName,
IRequest $request,
ITimeFactory $timeFactory,
IAppManager $appManager,
IconsCacher $iconsCacher) {
parent::__construct($appName, $request);
$this->serverRoot = \OC::$SERVERROOT;
$this->timeFactory = $timeFactory;
$this->appManager = $appManager;
$this->iconsCacher = $iconsCacher;
}
/**
* @PublicPage
* @NoCSRFRequired
* @NoSameSiteCookieRequired
*
* Generate svg from filename with the requested color
*
* @param string $folder
* @param string $fileName
* @param string $color
* @return DataDisplayResponse|NotFoundResponse
*/
public function getSvgFromCore(string $folder, string $fileName, string $color = 'ffffff') {
$path = $this->serverRoot . "/core/img/$folder/$fileName.svg";
return $this->getSvg($path, $color, $fileName);
}
/**
* @PublicPage
* @NoCSRFRequired
* @NoSameSiteCookieRequired
*
* Generate svg from filename with the requested color
*
* @param string $app
* @param string $fileName
* @param string $color
* @return DataDisplayResponse|NotFoundResponse
*/
public function getSvgFromApp(string $app, string $fileName, string $color = 'ffffff') {
try {
$appPath = $this->appManager->getAppPath($app);
} catch (AppPathNotFoundException $e) {
return new NotFoundResponse();
}
$path = $appPath . "/img/$fileName.svg";
return $this->getSvg($path, $color, $fileName);
}
/**
* Generate svg from filename with the requested color
*
* @param string $path
* @param string $color
* @param string $fileName
* @return DataDisplayResponse|NotFoundResponse
*/
private function getSvg(string $path, string $color, string $fileName) {
if (!Filesystem::isValidPath($path)) {
return new NotFoundResponse();
}
if (!file_exists($path)) {
return new NotFoundResponse();
}
$svg = file_get_contents($path);
if ($svg === null) {
return new NotFoundResponse();
}
$svg = $this->iconsCacher->colorizeSvg($svg, $color);
$response = new DataDisplayResponse($svg, Http::STATUS_OK, ['Content-Type' => 'image/svg+xml']);
// Set cache control
$ttl = 31536000;
$response->cacheFor($ttl);
$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;
}
}

@ -721,20 +721,16 @@ $min-content-width: $breakpoint-mobile - $navigation-width - $list-min-width;
#app-settings-header .settings-button {
display: block;
display: flex;
align-items: center;
height: 44px;
width: 100%;
padding: 0;
margin: 0;
background-color: var(--color-main-background);
@include icon-color('settings-dark', 'actions', $color-black, 1, true);
background-position: 14px center;
background-repeat: no-repeat;
box-shadow: none;
border: 0;
border-radius: 0;
text-align: left;
padding-left: 44px;
font-weight: normal;
font-size: 100%;
opacity: 0.8;
@ -750,6 +746,19 @@ $min-content-width: $breakpoint-mobile - $navigation-width - $list-min-width;
&:focus {
background-color: var(--color-background-hover);
}
&::before {
background-image: var(--icon-settings-dark);
background-position: 14px center;
background-repeat: no-repeat;
content: '';
width: 44px;
height: 44px;
top: 0;
left: 0;
display: block;
filter: var(--background-invert-if-dark);
}
}
/* GENERAL SECTION ------------------------------------------------------------ */

@ -36,22 +36,31 @@
}
/**
* Calculates the URL to the svg under the SVG API.
*
* @param string $icon the icon filename
* @param string $dir the icon folder within /core/img if $core or app name
* @param string $color the desired color in hexadecimal
* @param int [$version] the version of the file
* @param bool [$core] search icon in core
* @return string The URL to the svg.
* @see core/src/icons.js
*/
@function icon-color-path($icon, $dir, $color, $version: 1, $core: false) {
$color: remove-hash-from-color($color);
@if $core {
@return '#{$webroot}/svg/core/#{$dir}/#{$icon}?color=#{$color}&v=#{$version}';
} @else {
@return '#{$webroot}/svg/#{$dir}/#{$icon}?color=#{$color}&v=#{$version}';
@function match-color-string($color) {
@if $color == #000 {
@return "dark";
}
@if $color == #fff {
@return 'white';
}
@if $color == #FC0 {
@return 'yellow';
}
@if $color == #e9322d {
@return 'red';
}
@if $color == #eca700 {
@return 'orange';
}
@if $color == #46ba61 {
@return 'green';
}
@if $color == #969696 {
@return 'grey';
}
@return $color;
}
/**
@ -66,30 +75,12 @@
* @returns A background image with the url to the set to the requested icon.
*/
@mixin icon-color($icon, $dir, $color, $version: 1, $core: false) {
$color: remove-hash-from-color($color);
$color: match-color-string($color);
/* $dir is the app name, so we add this to the icon var to avoid conflicts between apps */
$varName: "--icon-#{$dir}-#{$icon}-#{$color}";
@if $core {
$varName: "--icon-#{$icon}-#{$color}";
}
#{$varName}: url(icon-color-path($icon, $dir, $color, $version, $core));
$varName: "--icon-#{$icon}-#{$color}";
background-image: var(#{$varName});
}
/**
* Create black and white icons
* This will add a default black version of and an additional white version when .icon-white is applied
*/
@mixin icon-black-white($icon, $dir, $version, $core: false) {
.icon-#{$icon} {
@include icon-color($icon, $dir, $color-black, $version, $core);
}
.icon-#{$icon}-white,
.icon-#{$icon}.icon-white {
@include icon-color($icon, $dir, $color-white, $version, $core);
}
}
@mixin position($value) {
@if $value == 'sticky' {
position: -webkit-sticky; // Safari support

@ -123,393 +123,42 @@ audio, canvas, embed, iframe, img, input, object, video {
}
}
/* ICONS -------------------------------------------------------------------
* These icon classes are generated automatically with the following pattern
* for icon-black-white('close', ...)
* .icon-close (black icon)
* .icon-close-white (white icon)
* .icon-close.icon-white (white icon)
*
* Some class definitions are kept as before, since they don't follow the pattern
* or have some additional styling like drop shadows
*/
@include icon-black-white('add', 'actions', 1, true);
@include icon-black-white('address', 'actions', 1, true);
@include icon-black-white('audio', 'actions', 2, true);
.icon-audio-white {
filter: drop-shadow(1px 1px 4px var(--color-box-shadow));
}
@include icon-black-white('audio-off', 'actions', 1, true);
.icon-audio-off-white {
filter: drop-shadow(1px 1px 4px var(--color-box-shadow));
}
.icon-caret-white,
.icon-caret {
@include icon-color('caret', 'actions', $color-white, 1, true);
}
.icon-caret-dark {
@include icon-color('caret', 'actions', $color-black, 1, true);
}
@include icon-black-white('checkmark', 'actions', 1, true);
.icon-checkmark-color {
@include icon-color('checkmark', 'actions', $color-success, 1, true);
}
@include icon-black-white('clippy', 'actions', 2, true);
@include icon-black-white('close', 'actions', 1, true);
@include icon-black-white('comment', 'actions', 1, true);
@include icon-black-white('confirm', 'actions', 2, true);
@include icon-black-white('download', 'actions', 1, true);
.icon-confirm-fade {
@include icon-color('confirm-fade', 'actions', $color-black, 2, true);
}
.icon-delete {
@include icon-color('delete', 'actions', $color-black, 1, true);
&.no-permission,
&.no-hover {
&:hover,
&:focus {
@include icon-color('delete', 'actions', $color-black, 1, true);
}
}
&:hover,
&:focus {
@include icon-color('delete', 'actions', $color-error, 1, true);
filter: initial;
}
&.icon-white {
@include icon-color('delete', 'actions', $color-white, 1, true);
}
}
.icon-delete-white {
@include icon-color('delete', 'actions', $color-white, 1, true);
&.no-permission {
&:hover,
&:focus {
@include icon-color('delete', 'actions', $color-white, 1, true);
}
}
&:hover,
&:focus {
@include icon-color('delete', 'actions', $color-error, 1, true);
}
}
@include icon-black-white('details', 'actions', 1, true);
@include icon-black-white('edit', 'actions', 1, true);
@include icon-black-white('error', 'actions', 1, true);
.icon-error-color {
@include icon-color('error', 'actions', $color-error, 1, true);
}
@include icon-black-white('external', 'actions', 1, true);
@include icon-black-white('fullscreen', 'actions', 1, true);
.icon-fullscreen-white {
filter: drop-shadow(1px 1px 4px var(--color-box-shadow));
}
@include icon-black-white('history', 'actions', 2, true);
@include icon-black-white('info', 'actions', 1, true);
@include icon-black-white('logout', 'actions', 1, true);
@include icon-black-white('mail', 'actions', 1, true);
@include icon-black-white('menu', 'actions', 1, true);
@include icon-black-white('menu-sidebar', 'actions', 1, true);
@include icon-black-white('more', 'actions', 1, true);
@include icon-black-white('password', 'actions', 1, true);
@include icon-black-white('pause', 'actions', 1, true);
@include icon-black-white('play', 'actions', 1, true);
@include icon-black-white('play-add', 'actions', 1, true);
@include icon-black-white('play-next', 'actions', 1, true);
@include icon-black-white('play-previous', 'actions', 1, true);
@include icon-black-white('projects', 'actions', 1, true);
@include icon-black-white('public', 'actions', 1, true);
@include icon-black-white('quota', 'actions', 1, true);
@include icon-black-white('rename', 'actions', 1, true);
@include icon-black-white('screen', 'actions', 1, true);
@include icon-black-white('template-add', 'actions', 1, true);
.icon-screen-white {
filter: drop-shadow(1px 1px 4px var(--color-box-shadow));
}
@include icon-black-white('screen-off', 'actions', 1, true);
.icon-screen-off-white {
filter: drop-shadow(1px 1px 4px var(--color-box-shadow));
}
@include icon-black-white('search', 'actions', 1, true);
/* default icon have a .5 opacity */
.icon-settings {
@include icon-color('settings', 'actions', $color-black, 1, true);
}
.icon-settings-dark {
@include icon-color('settings-dark', 'actions', $color-black, 1, true);
}
.icon-settings-white {
@include icon-color('settings-dark', 'actions', $color-white, 1, true);
}
/* always use icon-shared, AdBlock blocks icon-share */
.icon-shared,
.icon-share {
@include icon-color('share', 'actions', $color-black, 1, true);
&.icon-white {
@include icon-color('share', 'actions', $color-white, 1, true);
}
}
.icon-shared-white,
.icon-share-white {
@include icon-color('share', 'actions', $color-white, 1, true);
}
@include icon-black-white('sound', 'actions', 1, true);
@include icon-black-white('sound-off', 'actions', 1, true);
.icon-favorite {
@include icon-color('star-dark', 'actions', $color-black, 1, true);
}
@include icon-black-white('star', 'actions', 1, true);
.icon-star-dark {
@include icon-color('star', 'actions', $color-black, 1, true);
}
.icon-starred {
&:hover,
&:focus {
@include icon-color('star', 'actions', $color-black, 1, true);
}
@include icon-color('star-dark', 'actions', $color-yellow, 1, true);
}
.icon-star {
&:hover,
&:focus {
@include icon-color('star-dark', 'actions', $color-yellow, 1, true);
}
}
@include icon-black-white('tag', 'actions', 2, true);
@include icon-black-white('timezone', 'actions', 1, true);
@include icon-black-white('toggle', 'actions', 1, true);
@include icon-black-white('toggle-background', 'actions', 1, true);
@include icon-black-white('toggle-pictures', 'actions', 1, true);
@include icon-black-white('toggle-filelist', 'actions', 1, true);
@include icon-black-white('triangle-e', 'actions', 1, true);
@include icon-black-white('triangle-n', 'actions', 1, true);
@include icon-black-white('triangle-s', 'actions', 1, true);
@include icon-black-white('upload', 'actions', 1, true);
@include icon-black-white('user', 'actions', 1, true);
@include icon-black-white('group', 'actions', 1, true);
@include icon-black-white('filter', 'actions', 1, true);
@include icon-black-white('video', 'actions', 2, true);
.icon-video-white {
filter: drop-shadow(1px 1px 4px var(--color-box-shadow));
}
@include icon-black-white('video-off', 'actions', 1, true);
.icon-video-off-white {
filter: drop-shadow(1px 1px 4px var(--color-box-shadow));
}
@include icon-black-white('video-switch', 'actions', 1, true);
/* SHADOW WHITE ICONS: white version only ----------------------------------- */
.icon-view-close,
.icon-view-close-white {
@include icon-color('view-close', 'actions', $color-white, 1, true);
}
.icon-view-download,
.icon-view-download-white {
@include icon-color('view-download', 'actions', $color-white, 1, true);
}
.icon-view-pause,
.icon-view-pause-white {
@include icon-color('view-pause', 'actions', $color-white, 1, true);
}
.icon-view-play,
.icon-view-play-white {
@include icon-color('view-play', 'actions', $color-white, 1, true);
}
.icon-view-next {
@include icon-color('arrow-right', 'actions', $color-black, 1, true);
&.icon-white {
@include icon-color('arrow-right', 'actions', $color-white, 1, true);
}
}
.icon-view-previous {
@include icon-color('arrow-left', 'actions', $color-black, 1, true);
&.icon-white {
@include icon-color('arrow-left', 'actions', $color-white, 1, true);
}
}
@include icon-black-white('disabled-user', 'actions', 1, true);
@include icon-black-white('disabled-users', 'actions', 1, true);
@include icon-black-white('user-admin', 'actions', 1, true);
@include icon-black-white('alert-outline', 'actions', 1, true);
/* PLACES ------------------------------------------------------------------- */
.icon-calendar {
@include icon-color('calendar', 'places', $color-white, 1, true);
}
.icon-calendar-dark {
@include icon-color('calendar', 'places', $color-black, 1, true);
}
.icon-contacts {
@include icon-color('contacts', 'places', $color-white, 1, true);
}
.icon-contacts-dark {
@include icon-color('contacts', 'places', $color-black, 1, true);
}
.icon-files {
@include icon-color('files', 'places', $color-white, 1, true);
}
.icon-files-dark {
@include icon-color('files', 'places', $color-black, 1, true);
}
.icon-file,
.icon-filetype-text {
@include icon-color('text', 'filetypes', #969696, 1, true);
}
.icon-filetype-file {
@include icon-color('file', 'filetypes', #969696, 1, true);
}
@include icon-black-white('folder', 'filetypes', 1, true);
.icon-filetype-folder {
@include icon-color('folder', 'filetypes', $color-primary, 1, true);
}
.icon-filetype-folder-drag-accept {
@include icon-color('folder-drag-accept', 'filetypes', $color-primary, 1, true);
}
@include icon-black-white('home', 'places', 1, true);
@include icon-black-white('link', 'places', 1, true);
@include icon-black-white('music', 'places', 1, true);
@include icon-black-white('picture', 'places', 1, true);
/* CLIENTS ------------------------------------------------------------------- */
@include icon-black-white('desktop', 'clients', 1, true);
@include icon-black-white('phone', 'clients', 1, true);
@include icon-black-white('tablet', 'clients', 1, true);
/* APP CATEGORIES ------------------------------------------------------------------- */
.icon-category-installed {
@include icon-color('user', 'actions', $color-black, 1, true);
}
.icon-category-enabled {
@include icon-color('checkmark', 'actions', $color-black, 1, true);
}
.icon-category-disabled {
@include icon-color('close', 'actions', $color-black, 1, true);
}
.icon-category-app-bundles {
@include icon-color('bundles', 'categories', $color-black, 1, true);
}
.icon-category-updates {
@include icon-color('download', 'actions', $color-black, 1, true);
}
.icon-category-files {
@include icon-color('files', 'categories', $color-black, 1, true);
}
.icon-category-social {
@include icon-color('social', 'categories', $color-black, 1, true);
}
.icon-category-office {
@include icon-color('office', 'categories', $color-black, 1, true);
}
.icon-category-auth {
@include icon-color('auth', 'categories', $color-black, 1, true);
}
.icon-category-monitoring {
@include icon-color('monitoring', 'categories', $color-black, 1, true);
}
.icon-category-multimedia {
@include icon-color('multimedia', 'categories', $color-black, 1, true);
}
.icon-category-organization {
@include icon-color('organization', 'categories', $color-black, 1, true);
}
.icon-category-customization {
@include icon-color('customization', 'categories', $color-black, 1, true);
}
.icon-category-integration {
@include icon-color('integration', 'categories', $color-black, 1, true);
}
.icon-category-tools {
@include icon-color('settings-dark', 'actions', $color-black, 1, true);
}
.icon-category-games {
@include icon-color('games', 'categories', $color-black, 1, true);
}
.icon-category-security {
@include icon-color('password', 'actions', $color-black, 1, true);
}
.icon-category-search {
@include icon-color('search', 'actions', $color-black, 1, true);
}
.icon-category-workflow {
@include icon-color('workflow', 'categories', $color-black, 1, true);
}
.icon-category-dashboard {
@include icon-color('dashboard', 'categories', $color-black, 1, true);
}
.icon-talk {
@include icon-color('app-dark', 'spreed', $color-black, 1);
}
/* ICONS -------------------------------------------------------------------
* These icon classes are generated automatically with the following pattern
* .icon-close (black icon)
* .icon-close-white (white icon)
* .icon-close.icon-white (white icon)
*
* Some class definitions are kept as before, since they don't follow the pattern
* or have some additional styling like drop shadows
*/
.nav-icon-systemtagsfilter {
@include icon-color('tag', 'actions', $color-black, 1, true);
}
@import url('../../dist/icons.css');

@ -975,6 +975,8 @@ span.ui-icon {
background-size: 20px 20px;
padding: 14px;
cursor: pointer;
// Force white
background-image: var(--original-icon-contacts-white);
filter: var(--primary-invert-if-bright);
&:hover,

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" version="1.1" height="16"><path d="m8 2c-2.142 0-4.125 1.145-5.196 3l1.948 1.125c0.671-1.162 1.906-1.875 3.2476-1.875 1.1906 0 2.297 0.56157 3 1.5l-1.5 1.5h4.5v-4.5l-1.406 1.406c-1.129-1.348-2.802-2.1563-4.594-2.1563z"/><path d="m2 8.75v4.5l1.408-1.41c1.116 1.334 2.817 2.145 4.592 2.16 2.16 0.01827 4.116-1.132 5.196-3.002l-1.948-1.125c-0.677 1.171-1.9005 1.886-3.248 1.875-1.18-0.01-2.3047-0.572-3-1.5l1.5-1.5z"/></svg>

After

Width:  |  Height:  |  Size: 493 B

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 16 16" height="16" width="16" version="1.1"><circle stroke-width="2" stroke="#000" cy="8" cx="8" r="7" fill="none"/><path stroke-linejoin="round" d="m8 3.5-1 5 3.5 2-2-2z" stroke="#000" stroke-linecap="round" stroke-width="1.5"/></svg>

After

Width:  |  Height:  |  Size: 289 B

@ -0,0 +1 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="m12.5 1a2.5 2.5 0 0 0-2.5 2.5 2.5 2.5 0 0 0 0.003906 0.12891l-4.9023 2.4512a2.5 2.5 0 0 0-1.6016-0.58008 2.5 2.5 0 0 0-2.5 2.5 2.5 2.5 0 0 0 2.5 2.5 2.5 2.5 0 0 0 0.30469-0.021484l3.4395-1.7246-1.25-0.625a2.5 2.5 0 0 0 0.0058594-0.12891 2.5 2.5 0 0 0-0.0039062-0.12891l4.9023-2.4512a2.5 2.5 0 0 0 1.6016 0.58008 2.5 2.5 0 0 0 0.26562-0.013672l1.5625-0.7832a2.5 2.5 0 0 0 0.67188-1.7031 2.5 2.5 0 0 0-2.5-2.5zm0.25391 9.0156-3.7246 1.8672 0.97656 0.48828a2.5 2.5 0 0 0-0.005859 0.12891 2.5 2.5 0 0 0 2.5 2.5 2.5 2.5 0 0 0 2.5-2.5 2.5 2.5 0 0 0-2.2461-2.4844z"/><rect transform="rotate(-26.63)" x="-1.0586" y="11.891" width="11.687" height="2.0029" ry="0" style="paint-order:normal"/></svg>

After

Width:  |  Height:  |  Size: 795 B

@ -0,0 +1 @@
<svg height="16" viewBox="0 0 21.33 21.33" width="16" xmlns="http://www.w3.org/2000/svg"><path d="M10.67 1.33a9.34 9.34 0 100 18.68 9.34 9.34 0 000-18.68zM6.93 15.8a2.33 2.33 0 110-4.67 2.33 2.33 0 010 4.67zm1.4-8.87a2.33 2.33 0 114.67 0 2.33 2.33 0 01-4.67 0zm6.07 8.87a2.33 2.33 0 110-4.67 2.33 2.33 0 010 4.67z"/></svg>

After

Width:  |  Height:  |  Size: 322 B

@ -79,8 +79,6 @@ $application->registerRoutes($this, [
['name' => 'Preview#getPreviewByFileId', 'url' => '/core/preview', 'verb' => 'GET'],
['name' => 'Preview#getPreview', 'url' => '/core/preview.png', 'verb' => 'GET'],
['name' => 'RecommendedApps#index', 'url' => '/core/apps/recommended', 'verb' => 'GET'],
['name' => 'Svg#getSvgFromCore', 'url' => '/svg/core/{folder}/{fileName}', 'verb' => 'GET'],
['name' => 'Svg#getSvgFromApp', 'url' => '/svg/{app}/{fileName}', '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'],

@ -0,0 +1,334 @@
/* eslint-disable quote-props */
/* eslint-disable node/no-unpublished-import */
import path from 'path'
import fs from 'fs'
import sass from 'sass'
const colors = {
dark: '000',
white: 'fff',
yellow: 'FC0',
red: 'e9322d',
orange: 'eca700',
green: '46ba61',
grey: '969696',
}
const variables = {}
const icons = {
'add': path.join(__dirname, '../img', 'actions', 'add.svg'),
'address': path.join(__dirname, '../img', 'actions', 'address.svg'),
'alert-outline': path.join(__dirname, '../img', 'actions', 'alert-outline.svg'),
'audio-off': path.join(__dirname, '../img', 'actions', 'audio-off.svg'),
'audio': path.join(__dirname, '../img', 'actions', 'audio.svg'),
'calendar': path.join(__dirname, '../img', 'places', 'calendar.svg'),
'caret': path.join(__dirname, '../img', 'actions', 'caret.svg'),
'category-app-bundles': path.join(__dirname, '../img', 'categories', 'bundles.svg'),
'category-auth': path.join(__dirname, '../img', 'categories', 'auth.svg'),
'category-customization': path.join(__dirname, '../img', 'categories', 'customization.svg'),
'category-dashboard': path.join(__dirname, '../img', 'categories', 'dashboard.svg'),
'category-files': path.join(__dirname, '../img', 'categories', 'files.svg'),
'category-games': path.join(__dirname, '../img', 'categories', 'games.svg'),
'category-integration': path.join(__dirname, '../img', 'categories', 'integration.svg'),
'category-monitoring': path.join(__dirname, '../img', 'categories', 'monitoring.svg'),
'category-multimedia': path.join(__dirname, '../img', 'categories', 'multimedia.svg'),
'category-office': path.join(__dirname, '../img', 'categories', 'office.svg'),
'category-organization': path.join(__dirname, '../img', 'categories', 'organization.svg'),
'category-social': path.join(__dirname, '../img', 'categories', 'social.svg'),
'category-workflow': path.join(__dirname, '../img', 'categories', 'workflow.svg'),
'change': path.join(__dirname, '../img', 'actions', 'change.svg'),
'checkmark': path.join(__dirname, '../img', 'actions', 'checkmark.svg'),
'circles': path.join(__dirname, '../img', 'apps', 'circles.svg'),
'clippy': path.join(__dirname, '../img', 'actions', 'clippy.svg'),
'close': path.join(__dirname, '../img', 'actions', 'close.svg'),
'comment': path.join(__dirname, '../img', 'actions', 'comment.svg'),
'confirm-fade': path.join(__dirname, '../img', 'actions', 'confirm-fade.svg'),
'confirm': path.join(__dirname, '../img', 'actions', 'confirm.svg'),
'contacts': path.join(__dirname, '../img', 'places', 'contacts.svg'),
'delete': path.join(__dirname, '../img', 'actions', 'delete.svg'),
'desktop': path.join(__dirname, '../img', 'clients', 'desktop.svg'),
'details': path.join(__dirname, '../img', 'actions', 'details.svg'),
'disabled-user': path.join(__dirname, '../img', 'actions', 'disabled-user.svg'),
'disabled-users': path.join(__dirname, '../img', 'actions', 'disabled-users.svg'),
'download': path.join(__dirname, '../img', 'actions', 'download.svg'),
'edit': path.join(__dirname, '../img', 'actions', 'edit.svg'),
'encryption': path.join(__dirname, '../../', 'apps/files_external/img', 'app.svg'),
'error': path.join(__dirname, '../img', 'actions', 'error.svg'),
'external': path.join(__dirname, '../img', 'actions', 'external.svg'),
'favorite': path.join(__dirname, '../img', 'actions', 'star-dark.svg'),
'files': path.join(__dirname, '../img', 'places', 'files.svg'),
'filter': path.join(__dirname, '../img', 'actions', 'filter.svg'),
'folder': path.join(__dirname, '../img', 'filetypes', 'folder.svg'),
'fullscreen': path.join(__dirname, '../img', 'actions', 'fullscreen.svg'),
'group': path.join(__dirname, '../img', 'actions', 'group.svg'),
'history': path.join(__dirname, '../img', 'actions', 'history.svg'),
'home': path.join(__dirname, '../img', 'places', 'home.svg'),
'info': path.join(__dirname, '../img', 'actions', 'info.svg'),
'link': path.join(__dirname, '../img', 'places', 'link.svg'),
'logout': path.join(__dirname, '../img', 'actions', 'logout.svg'),
'mail': path.join(__dirname, '../img', 'actions', 'mail.svg'),
'menu-sidebar': path.join(__dirname, '../img', 'actions', 'menu-sidebar.svg'),
'menu': path.join(__dirname, '../img', 'actions', 'menu.svg'),
'more': path.join(__dirname, '../img', 'actions', 'more.svg'),
'music': path.join(__dirname, '../img', 'places', 'music.svg'),
'password': path.join(__dirname, '../img', 'actions', 'password.svg'),
'pause': path.join(__dirname, '../img', 'actions', 'pause.svg'),
'phone': path.join(__dirname, '../img', 'clients', 'phone.svg'),
'picture': path.join(__dirname, '../img', 'places', 'picture.svg'),
'play-add': path.join(__dirname, '../img', 'actions', 'play-add.svg'),
'play-next': path.join(__dirname, '../img', 'actions', 'play-next.svg'),
'play-previous': path.join(__dirname, '../img', 'actions', 'play-previous.svg'),
'play': path.join(__dirname, '../img', 'actions', 'play.svg'),
'projects': path.join(__dirname, '../img', 'actions', 'projects.svg'),
'public': path.join(__dirname, '../img', 'actions', 'public.svg'),
'quota': path.join(__dirname, '../img', 'actions', 'quota.svg'),
'recent': path.join(__dirname, '../img', 'actions', 'recent.svg'),
'rename': path.join(__dirname, '../img', 'actions', 'rename.svg'),
'screen-off': path.join(__dirname, '../img', 'actions', 'screen-off.svg'),
'screen': path.join(__dirname, '../img', 'actions', 'screen.svg'),
'search': path.join(__dirname, '../img', 'actions', 'search.svg'),
'settings': path.join(__dirname, '../img', 'actions', 'settings-dark.svg'),
'share': path.join(__dirname, '../img', 'actions', 'share.svg'),
'shared': path.join(__dirname, '../img', 'actions', 'share.svg'),
'sound-off': path.join(__dirname, '../img', 'actions', 'sound-off.svg'),
'sound': path.join(__dirname, '../img', 'actions', 'sound.svg'),
'star': path.join(__dirname, '../img', 'actions', 'star.svg'),
'starred': path.join(__dirname, '../img', 'actions', 'star-dark.svg'),
'tablet': path.join(__dirname, '../img', 'clients', 'tablet.svg'),
'tag': path.join(__dirname, '../img', 'actions', 'tag.svg'),
'talk': path.join(__dirname, '../img', 'apps', 'spreed.svg'),
'template-add': path.join(__dirname, '../img', 'actions', 'template-add.svg'),
'timezone': path.join(__dirname, '../img', 'actions', 'timezone.svg'),
'toggle-background': path.join(__dirname, '../img', 'actions', 'toggle-background.svg'),
'toggle-filelist': path.join(__dirname, '../img', 'actions', 'toggle-filelist.svg'),
'toggle-pictures': path.join(__dirname, '../img', 'actions', 'toggle-pictures.svg'),
'toggle': path.join(__dirname, '../img', 'actions', 'toggle.svg'),
'triangle-e': path.join(__dirname, '../img', 'actions', 'triangle-e.svg'),
'triangle-n': path.join(__dirname, '../img', 'actions', 'triangle-n.svg'),
'triangle-s': path.join(__dirname, '../img', 'actions', 'triangle-s.svg'),
'unshare': path.join(__dirname, '../img', 'actions', 'unshare.svg'),
'upload': path.join(__dirname, '../img', 'actions', 'upload.svg'),
'user-admin': path.join(__dirname, '../img', 'actions', 'user-admin.svg'),
'user': path.join(__dirname, '../img', 'actions', 'user.svg'),
'video-off': path.join(__dirname, '../img', 'actions', 'video-off.svg'),
'video-switch': path.join(__dirname, '../img', 'actions', 'video-switch.svg'),
'video': path.join(__dirname, '../img', 'actions', 'video.svg'),
'view-close': path.join(__dirname, '../img', 'actions', 'view-close.svg'),
'view-download': path.join(__dirname, '../img', 'actions', 'view-download.svg'),
'view-next': path.join(__dirname, '../img', 'actions', 'arrow-right.svg'),
'view-pause': path.join(__dirname, '../img', 'actions', 'view-pause.svg'),
'view-play': path.join(__dirname, '../img', 'actions', 'view-play.svg'),
'view-previous': path.join(__dirname, '../img', 'actions', 'arrow-left.svg'),
}
const iconsColor = {
'settings': {
path: path.join(__dirname, '../img', 'actions', 'settings.svg'),
color: 'black',
},
'error-color': {
path: path.join(__dirname, '../img', 'actions', 'error.svg'),
color: 'red',
},
'checkmark-color': {
path: path.join(__dirname, '../img', 'actions', 'checkmark.svg'),
color: 'green',
},
'starred': {
path: path.join(__dirname, '../img', 'actions', 'star-dark.svg'),
color: 'yellow',
},
'delete-color': {
path: path.join(__dirname, '../img', 'actions', 'delete.svg'),
color: 'red',
},
'file': {
path: path.join(__dirname, '../img', 'filetypes', 'text.svg'),
color: 'grey',
},
'filetype-file': {
path: path.join(__dirname, '../img', 'filetypes', 'file.svg'),
color: 'grey',
},
'filetype-folder': {
path: path.join(__dirname, '../img', 'filetypes', 'folder.svg'),
// TODO: replace primary ?
color: 'primary',
},
'filetype-folder-drag-accept': {
path: path.join(__dirname, '../img', 'filetypes', 'folder-drag-accept.svg'),
// TODO: replace primary ?
color: 'primary',
},
}
// use this to define aliases to existing icons
// key is the css selector, value is the variable
const iconsAliases = {
'icon-caret': 'icon-caret-white',
// starring action
'icon-star:hover': 'icon-starred',
'icon-star:focus': 'icon-starred',
// Un-starring action
'icon-starred:hover': 'icon-star',
'icon-starred:focus': 'icon-star',
// Delete normal
'icon-delete.no-permission:hover': 'icon-delete-dark',
'icon-delete.no-permission:focus': 'icon-delete-dark',
'icon-delete.no-hover:hover': 'icon-delete-dark',
'icon-delete.no-hover:focus': 'icon-delete-dark',
'icon-delete:hover': 'icon-delete-color-red',
'icon-delete:focus': 'icon-delete-color-red',
// Delete white
'icon-delete-white.no-permission:hover': 'icon-delete-white',
'icon-delete-white.no-permission:focus': 'icon-delete-white',
'icon-delete-white.no-hover:hover': 'icon-delete-white',
'icon-delete-white.no-hover:focus': 'icon-delete-white',
'icon-delete-white:hover': 'icon-delete-color-red',
'icon-delete-white:focus': 'icon-delete-color-red',
// Default to white
'icon-view-close': 'icon-view-close-white',
'icon-view-download': 'icon-view-download-white',
'icon-view-pause': 'icon-view-pause-white',
'icon-view-play': 'icon-view-play-white',
// Default app place to white
'icon-calendar': 'icon-calendar-white',
'icon-contacts': 'icon-contacts-white',
'icon-files': 'icon-files-white',
// Re-using existing icons
'icon-category-installed': 'icon-user-dark',
'icon-category-enabled': 'icon-checkmark-dark',
'icon-category-disabled': 'icon-close-dark',
'icon-category-updates': 'icon-download-dark',
'icon-category-security': 'icon-password-dark',
'icon-category-search': 'icon-search-dark',
'icon-category-tools': 'icon-settings-dark',
'icon-filetype-text': 'icon-file-grey',
}
const colorSvg = function(svg = '', color = '000') {
if (!color.match(/^[0-9a-f]{3,6}$/i)) {
// Prevent not-sane colors from being written into the SVG
console.warn(color, 'does not match the required format')
color = '000'
}
// add fill (fill is not present on black elements)
const fillRe = /<((circle|rect|path)((?!fill)[a-z0-9 =".\-#():;,])+)\/>/gmi
svg = svg.replace(fillRe, '<$1 fill="#' + color + '"/>')
// replace any fill or stroke colors
svg = svg.replace(/stroke="#([a-z0-9]{3,6})"/gmi, 'stroke="#' + color + '"')
svg = svg.replace(/fill="#([a-z0-9]{3,6})"/gmi, 'fill="#' + color + '"')
return svg
}
const generateVariablesAliases = function(invert = false) {
let css = ''
Object.keys(variables).forEach(variable => {
if (variable.indexOf('original-') !== -1) {
let finalVariable = variable.replace('original-', '')
if (invert) {
finalVariable = finalVariable.replace('white', 'tempwhite')
.replace('dark', 'white')
.replace('tempwhite', 'dark')
}
css += `${finalVariable}: var(${variable});`
}
})
return css
}
const formatIcon = function(icon, invert = false) {
const color1 = invert ? 'white' : 'dark'
const color2 = invert ? 'dark' : 'white'
return `
.icon-${icon},
.icon-${icon}-dark {
background-image: var(--icon-${icon}-${color1});
}
.icon-${icon}-white,
.icon-${icon}.icon-white {
background-image: var(--icon-${icon}-${color2});
}`
}
const formatIconColor = function(icon) {
const { color } = iconsColor[icon]
return `
.icon-${icon} {
background-image: var(--icon-${icon}-${color});
}`
}
const formatAlias = function(alias, invert = false) {
let icon = iconsAliases[alias]
if (invert) {
icon = icon.replace('white', 'tempwhite')
.replace('dark', 'white')
.replace('tempwhite', 'dark')
}
return `
.${alias} {
background-image: var(--${icon})
}`
}
let css = ''
Object.keys(icons).forEach(icon => {
const path = icons[icon]
const svg = fs.readFileSync(path, 'utf8')
const darkSvg = colorSvg(svg, '000000')
const whiteSvg = colorSvg(svg, 'ffffff')
variables[`--original-icon-${icon}-dark`] = Buffer.from(darkSvg, 'utf-8').toString('base64')
variables[`--original-icon-${icon}-white`] = Buffer.from(whiteSvg, 'utf-8').toString('base64')
})
Object.keys(iconsColor).forEach(icon => {
const { path, color } = iconsColor[icon]
const svg = fs.readFileSync(path, 'utf8')
const coloredSvg = colorSvg(svg, colors[color])
variables[`--icon-${icon}-${color}`] = Buffer.from(coloredSvg, 'utf-8').toString('base64')
})
// ICONS VARIABLES LIST
css += ':root {'
Object.keys(variables).forEach(variable => {
const data = variables[variable]
css += `${variable}: url(data:image/svg+xml;base64,${data});`
})
css += '}'
// DEFAULT THEME
css += 'body {'
css += generateVariablesAliases()
Object.keys(icons).forEach(icon => {
css += formatIcon(icon)
})
Object.keys(iconsColor).forEach(icon => {
css += formatIconColor(icon)
})
Object.keys(iconsAliases).forEach(alias => {
css += formatAlias(alias)
})
css += '}'
// DARK THEME MEDIA QUERY
css += '@media (prefers-color-scheme: dark) { body {'
css += generateVariablesAliases(true)
css += '}}'
// DARK THEME
css += 'body[data-themes*=light] {'
css += generateVariablesAliases()
css += '}'
// DARK THEME
css += 'body[data-themes*=dark] {'
css += generateVariablesAliases(true)
css += '}'
// WRITE CSS
fs.writeFileSync(path.join(__dirname, '../../dist', 'icons.css'), sass.compileString(css).css)

@ -53,7 +53,7 @@
top: 0;
right: 0;
padding: 25px;
background: var(--icon-close-000) no-repeat center;
background: var(--icon-close-dark) no-repeat center;
opacity: .5;
&:hover,

@ -42,7 +42,7 @@ $getUserAvatar = static function (int $size) use ($_): string {
</head>
<body id="<?php p($_['bodyid']);?>" <?php foreach ($_['enabledThemes'] as $themeId) {
p("data-theme-$themeId ");
}?>>
}?> data-themes=<?php p(join(',', $_['enabledThemes'])) ?>>
<?php include 'layout.noscript.warning.php'; ?>
<?php foreach ($_['initialStates'] as $app => $initialState) { ?>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

4
dist/core-main.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

2001
dist/icons.css vendored

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -962,7 +962,6 @@ return array(
'OC\\Core\\Controller\\RecommendedAppsController' => $baseDir . '/core/Controller/RecommendedAppsController.php',
'OC\\Core\\Controller\\SearchController' => $baseDir . '/core/Controller/SearchController.php',
'OC\\Core\\Controller\\SetupController' => $baseDir . '/core/Controller/SetupController.php',
'OC\\Core\\Controller\\SvgController' => $baseDir . '/core/Controller/SvgController.php',
'OC\\Core\\Controller\\TwoFactorChallengeController' => $baseDir . '/core/Controller/TwoFactorChallengeController.php',
'OC\\Core\\Controller\\UnifiedSearchController' => $baseDir . '/core/Controller/UnifiedSearchController.php',
'OC\\Core\\Controller\\UserController' => $baseDir . '/core/Controller/UserController.php',
@ -1523,7 +1522,6 @@ return array(
'OC\\TemplateLayout' => $baseDir . '/lib/private/TemplateLayout.php',
'OC\\Template\\Base' => $baseDir . '/lib/private/Template/Base.php',
'OC\\Template\\CSSResourceLocator' => $baseDir . '/lib/private/Template/CSSResourceLocator.php',
'OC\\Template\\IconsCacher' => $baseDir . '/lib/private/Template/IconsCacher.php',
'OC\\Template\\JSCombiner' => $baseDir . '/lib/private/Template/JSCombiner.php',
'OC\\Template\\JSConfigHelper' => $baseDir . '/lib/private/Template/JSConfigHelper.php',
'OC\\Template\\JSResourceLocator' => $baseDir . '/lib/private/Template/JSResourceLocator.php',

@ -991,7 +991,6 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OC\\Core\\Controller\\RecommendedAppsController' => __DIR__ . '/../../..' . '/core/Controller/RecommendedAppsController.php',
'OC\\Core\\Controller\\SearchController' => __DIR__ . '/../../..' . '/core/Controller/SearchController.php',
'OC\\Core\\Controller\\SetupController' => __DIR__ . '/../../..' . '/core/Controller/SetupController.php',
'OC\\Core\\Controller\\SvgController' => __DIR__ . '/../../..' . '/core/Controller/SvgController.php',
'OC\\Core\\Controller\\TwoFactorChallengeController' => __DIR__ . '/../../..' . '/core/Controller/TwoFactorChallengeController.php',
'OC\\Core\\Controller\\UnifiedSearchController' => __DIR__ . '/../../..' . '/core/Controller/UnifiedSearchController.php',
'OC\\Core\\Controller\\UserController' => __DIR__ . '/../../..' . '/core/Controller/UserController.php',
@ -1552,7 +1551,6 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OC\\TemplateLayout' => __DIR__ . '/../../..' . '/lib/private/TemplateLayout.php',
'OC\\Template\\Base' => __DIR__ . '/../../..' . '/lib/private/Template/Base.php',
'OC\\Template\\CSSResourceLocator' => __DIR__ . '/../../..' . '/lib/private/Template/CSSResourceLocator.php',
'OC\\Template\\IconsCacher' => __DIR__ . '/../../..' . '/lib/private/Template/IconsCacher.php',
'OC\\Template\\JSCombiner' => __DIR__ . '/../../..' . '/lib/private/Template/JSCombiner.php',
'OC\\Template\\JSConfigHelper' => __DIR__ . '/../../..' . '/lib/private/Template/JSConfigHelper.php',
'OC\\Template\\JSResourceLocator' => __DIR__ . '/../../..' . '/lib/private/Template/JSResourceLocator.php',

@ -1,263 +0,0 @@
<?php
declare(strict_types=1);
/**
* @copyright Copyright (c) 2018, John Molakvoæ (skjnldsv@protonmail.com)
*
* @author Christoph Wurst <christoph@winzerhof-wurst.at>
* @author Joas Schilling <coding@schilljs.com>
* @author John Molakvoæ <skjnldsv@protonmail.com>
* @author Julius Härtl <jus@bitgrid.net>
* @author Robin Appelman <robin@icewind.nl>
* @author Roeland Jago Douma <roeland@famdouma.nl>
*
* @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 <http://www.gnu.org/licenses/>.
*
*/
namespace OC\Template;
use OC\Files\AppData\Factory;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\Files\IAppData;
use OCP\Files\NotFoundException;
use OCP\Files\SimpleFS\ISimpleFile;
use OCP\Files\SimpleFS\ISimpleFolder;
use OCP\IURLGenerator;
use Psr\Log\LoggerInterface;
class IconsCacher {
protected LoggerInterface $logger;
/** @var IAppData */
protected $appData;
/** @var ISimpleFolder */
private $folder;
/** @var IURLGenerator */
protected $urlGenerator;
/** @var ITimeFactory */
protected $timeFactory;
/** @var string */
private $iconVarRE = '/--(icon-[a-zA-Z0-9-]+):\s?url\(["\']?([a-zA-Z0-9-_\~\/\.\?\&\=\:\;\+\,]+)[^;]+;/m';
/** @var string */
private $fileName = 'icons-vars.css';
private $iconList = 'icons-list.template';
private $cachedCss;
private $cachedList;
/**
* @throws \OCP\Files\NotPermittedException
*/
public function __construct(LoggerInterface $logger,
Factory $appDataFactory,
IURLGenerator $urlGenerator,
ITimeFactory $timeFactory) {
$this->logger = $logger;
$this->appData = $appDataFactory->get('css');
$this->urlGenerator = $urlGenerator;
$this->timeFactory = $timeFactory;
try {
$this->folder = $this->appData->getFolder('icons');
} catch (NotFoundException $e) {
$this->folder = $this->appData->newFolder('icons');
}
}
private function getIconsFromCss(string $css): array {
preg_match_all($this->iconVarRE, $css, $matches, PREG_SET_ORDER);
$icons = [];
foreach ($matches as $icon) {
$icons[$icon[1]] = $icon[2];
}
return $icons;
}
/**
* @param string $css
* @return string
* @throws NotFoundException
* @throws \OCP\Files\NotPermittedException
*/
public function setIconsCss(string $css): string {
$cachedFile = $this->getCachedList();
if (!$cachedFile) {
$currentData = '';
$cachedFile = $this->folder->newFile($this->iconList);
} else {
$currentData = $cachedFile->getContent();
}
$cachedVarsCssFile = $this->getCachedCSS();
if (!$cachedVarsCssFile) {
$cachedVarsCssFile = $this->folder->newFile($this->fileName);
}
$icons = $this->getIconsFromCss($currentData . $css);
$data = '';
$list = '';
foreach ($icons as $icon => $url) {
$list .= "--$icon: url('$url');";
[$location,$color] = $this->parseUrl($url);
$svg = false;
if ($location !== '' && \file_exists($location)) {
$svg = \file_get_contents($location);
}
if ($svg === false) {
$this->logger->debug('Failed to get icon file ' . $location);
$data .= "--$icon: url('$url');";
continue;
}
$encode = base64_encode($this->colorizeSvg($svg, $color));
$data .= '--' . $icon . ': url(data:image/svg+xml;base64,' . $encode . ');';
}
if (\strlen($data) > 0 && \strlen($list) > 0) {
$data = ":root {\n$data\n}";
$cachedVarsCssFile->putContent($data);
$list = ":root {\n$list\n}";
$cachedFile->putContent($list);
$this->cachedList = null;
$this->cachedCss = null;
}
return preg_replace($this->iconVarRE, '', $css);
}
/**
* @param $url
* @return array
*/
private function parseUrl($url): array {
$location = '';
$color = '';
$base = $this->getRoutePrefix() . '/svg/';
$cleanUrl = \substr($url, \strlen($base));
if (\strpos($url, $base . 'core') === 0) {
$cleanUrl = \substr($cleanUrl, \strlen('core'));
if (\preg_match('/\/([a-zA-Z0-9-_\~\/\.\=\:\;\+\,]+)\?color=([0-9a-fA-F]{3,6})/', $cleanUrl, $matches)) {
[,$cleanUrl,$color] = $matches;
$location = \OC::$SERVERROOT . '/core/img/' . $cleanUrl . '.svg';
}
} elseif (\strpos($url, $base) === 0) {
if (\preg_match('/([A-z0-9\_\-]+)\/([a-zA-Z0-9-_\~\/\.\=\:\;\+\,]+)\?color=([0-9a-fA-F]{3,6})/', $cleanUrl, $matches)) {
[,$app,$cleanUrl, $color] = $matches;
$appPath = \OC_App::getAppPath($app);
if ($appPath !== false) {
$location = $appPath . '/img/' . $cleanUrl . '.svg';
}
if ($app === 'settings') {
$location = \OC::$SERVERROOT . '/settings/img/' . $cleanUrl . '.svg';
}
}
}
return [
$location,
$color
];
}
/**
* @param $svg
* @param $color
* @return string
*/
public function colorizeSvg($svg, $color): string {
if (!preg_match('/^[0-9a-f]{3,6}$/i', $color)) {
// Prevent not-sane colors from being written into the SVG
$color = '000';
}
// 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);
return $svg;
}
private function getRoutePrefix() {
$frontControllerActive = (\OC::$server->getConfig()->getSystemValue('htaccess.IgnoreFrontController', false) === true || getenv('front_controller_active') === 'true');
$prefix = \OC::$WEBROOT . '/index.php';
if ($frontControllerActive) {
$prefix = \OC::$WEBROOT;
}
return $prefix;
}
/**
* Get icons css file
* @return ISimpleFile|boolean
*/
public function getCachedCSS() {
try {
if (!$this->cachedCss) {
$this->cachedCss = $this->folder->getFile($this->fileName);
}
return $this->cachedCss;
} catch (NotFoundException $e) {
return false;
}
}
/**
* Get icon-vars list template
* @return ISimpleFile|boolean
*/
public function getCachedList() {
try {
if (!$this->cachedList) {
$this->cachedList = $this->folder->getFile($this->iconList);
}
return $this->cachedList;
} catch (NotFoundException $e) {
return false;
}
}
/**
* Add the icons cache css into the header
*/
public function injectCss() {
$mtime = $this->timeFactory->getTime();
$file = $this->getCachedList();
if ($file) {
$mtime = $file->getMTime();
}
// Only inject once
foreach (\OC_Util::$headers as $header) {
if (
array_key_exists('attributes', $header) &&
array_key_exists('href', $header['attributes']) &&
strpos($header['attributes']['href'], $this->fileName) !== false) {
return;
}
}
$linkToCSS = $this->urlGenerator->linkToRoute('core.Css.getCss', ['appName' => 'icons', 'fileName' => $this->fileName, 'v' => $mtime]);
\OC_Util::addHeader('link', ['rel' => 'stylesheet', 'href' => $linkToCSS], null, true);
}
}

@ -74,9 +74,6 @@ class SCSSCacher {
/** @var ICacheFactory */
private $cacheFactory;
/** @var IconsCacher */
private $iconsCacher;
/** @var ICache */
private $isCachedCache;
@ -98,7 +95,6 @@ class SCSSCacher {
\OC_Defaults $defaults,
$serverRoot,
ICacheFactory $cacheFactory,
IconsCacher $iconsCacher,
ITimeFactory $timeFactory,
AppConfig $appConfig) {
$this->logger = $logger;
@ -115,7 +111,6 @@ class SCSSCacher {
$lockingCache = new NullCache();
}
$this->lockingCache = $lockingCache;
$this->iconsCacher = $iconsCacher;
$this->timeFactory = $timeFactory;
$this->appConfig = $appConfig;
}
@ -139,10 +134,6 @@ class SCSSCacher {
$webDir = $this->getWebDir($path, $app, $this->serverRoot, \OC::$WEBROOT);
$this->logger->debug('SCSSCacher::process ordinary check follows', ['app' => 'scss_cacher']);
if (!$this->variablesChanged() && $this->isCached($fileNameCSS, $app)) {
// Inject icons vars css if any
return $this->injectCssVariablesIfAny();
}
try {
$folder = $this->appData->getFolder($app);
@ -163,7 +154,7 @@ class SCSSCacher {
if (!$this->variablesChanged() && $this->isCached($fileNameCSS, $app)) {
// Inject icons vars css if any
$this->logger->debug("SCSSCacher::process cached file for app '$app' and file '$fileNameCSS' is now available after $retry s. Moving on...", ['app' => 'scss_cacher']);
return $this->injectCssVariablesIfAny();
return true;
}
sleep(1);
$retry++;
@ -184,11 +175,6 @@ class SCSSCacher {
$this->lockingCache->remove($lockKey);
$this->logger->debug('SCSSCacher::process Lock removed for ' . $lockKey, ['app' => 'scss_cacher']);
// Inject icons vars css if any
if ($this->iconsCacher->getCachedCSS() && $this->iconsCacher->getCachedCSS()->getSize() > 0) {
$this->iconsCacher->injectCss();
}
return $cached;
}
@ -335,9 +321,6 @@ class SCSSCacher {
return false;
}
// Parse Icons and create related css variables
$compiledScss = $this->iconsCacher->setIconsCss($compiledScss);
// Gzip file
try {
$gzipFile = $folder->getFile($fileNameCSS . '.gzip'); # Safari doesn't like .gz
@ -512,17 +495,4 @@ class SCSSCacher {
return $webRoot . substr($path, strlen($serverRoot));
}
/**
* Add the icons css cache in the header if needed
*
* @return boolean true
*/
private function injectCssVariablesIfAny() {
// Inject icons vars css if any
if ($this->iconsCacher->getCachedCSS() && $this->iconsCacher->getCachedCSS()->getSize() > 0) {
$this->iconsCacher->injectCss();
}
return true;
}
}

@ -105,7 +105,6 @@ class OC_Template extends \OC\Template\Base {
// apps that started before the template initialization can load their own scripts/styles
// so to make sure this scripts/styles here are loaded first we put all core scripts first
// check lib/public/Util.php
// OC_Util::addStyle('css-variables', null, true);
OC_Util::addStyle('server', null, true);
// include common nextcloud webpack bundle

509
package-lock.json generated

@ -80,6 +80,7 @@
"webdav": "^4.8.0"
},
"devDependencies": {
"@babel/node": "^7.17.10",
"@nextcloud/babel-config": "^1.0.0",
"@nextcloud/browserslist-config": "^2.2.0",
"@nextcloud/eslint-config": "^7.0.2",
@ -576,6 +577,29 @@
"node": ">=6.9.0"
}
},
"node_modules/@babel/node": {
"version": "7.17.10",
"resolved": "https://registry.npmjs.org/@babel/node/-/node-7.17.10.tgz",
"integrity": "sha512-sFFMyvw23U8QOcTnLJnw2/Myr01e4+iLVy7rHAHrNSnXAfnwS3j2NqihpmZm7TotyNKKf/y8cJ96T5asY46eyw==",
"dev": true,
"dependencies": {
"@babel/register": "^7.17.7",
"commander": "^4.0.1",
"core-js": "^3.22.1",
"node-environment-flags": "^1.0.5",
"regenerator-runtime": "^0.13.4",
"v8flags": "^3.1.1"
},
"bin": {
"babel-node": "bin/babel-node.js"
},
"engines": {
"node": ">=6.9.0"
},
"peerDependencies": {
"@babel/core": "^7.0.0-0"
}
},
"node_modules/@babel/parser": {
"version": "7.16.8",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.16.8.tgz",
@ -1755,6 +1779,121 @@
"@babel/core": "^7.0.0-0"
}
},
"node_modules/@babel/register": {
"version": "7.17.7",
"resolved": "https://registry.npmjs.org/@babel/register/-/register-7.17.7.tgz",
"integrity": "sha512-fg56SwvXRifootQEDQAu1mKdjh5uthPzdO0N6t358FktfL4XjAVXuH58ULoiW8mesxiOgNIrxiImqEwv0+hRRA==",
"dev": true,
"dependencies": {
"clone-deep": "^4.0.1",
"find-cache-dir": "^2.0.0",
"make-dir": "^2.1.0",
"pirates": "^4.0.5",
"source-map-support": "^0.5.16"
},
"engines": {
"node": ">=6.9.0"
},
"peerDependencies": {
"@babel/core": "^7.0.0-0"
}
},
"node_modules/@babel/register/node_modules/find-cache-dir": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz",
"integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==",
"dev": true,
"dependencies": {
"commondir": "^1.0.1",
"make-dir": "^2.0.0",
"pkg-dir": "^3.0.0"
},
"engines": {
"node": ">=6"
}
},
"node_modules/@babel/register/node_modules/find-up": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
"integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
"dev": true,
"dependencies": {
"locate-path": "^3.0.0"
},
"engines": {
"node": ">=6"
}
},
"node_modules/@babel/register/node_modules/locate-path": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
"integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
"dev": true,
"dependencies": {
"p-locate": "^3.0.0",
"path-exists": "^3.0.0"
},
"engines": {
"node": ">=6"
}
},
"node_modules/@babel/register/node_modules/p-limit": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
"integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
"dev": true,
"dependencies": {
"p-try": "^2.0.0"
},
"engines": {
"node": ">=6"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/@babel/register/node_modules/p-locate": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
"integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
"dev": true,
"dependencies": {
"p-limit": "^2.0.0"
},
"engines": {
"node": ">=6"
}
},
"node_modules/@babel/register/node_modules/p-try": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
"integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
"dev": true,
"engines": {
"node": ">=6"
}
},
"node_modules/@babel/register/node_modules/path-exists": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
"integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=",
"dev": true,
"engines": {
"node": ">=4"
}
},
"node_modules/@babel/register/node_modules/pkg-dir": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz",
"integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==",
"dev": true,
"dependencies": {
"find-up": "^3.0.0"
},
"engines": {
"node": ">=6"
}
},
"node_modules/@babel/runtime": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.16.7.tgz",
@ -6029,6 +6168,15 @@
"node": ">= 0.8"
}
},
"node_modules/commander": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz",
"integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==",
"dev": true,
"engines": {
"node": ">= 6"
}
},
"node_modules/comment-parser": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.3.0.tgz",
@ -6177,9 +6325,9 @@
}
},
"node_modules/core-js": {
"version": "3.22.0",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.22.0.tgz",
"integrity": "sha512-8h9jBweRjMiY+ORO7bdWSeWfHhLPO7whobj7Z2Bl0IDo00C228EdGgH7FE4jGumbEjzcFfkfW8bXgdkEDhnwHQ==",
"version": "3.22.5",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.22.5.tgz",
"integrity": "sha512-VP/xYuvJ0MJWRAobcmQ8F2H6Bsn+s7zqAAjFaHGBMc5AQm7zaelhD1LGduFn2EehEcQcU+br6t+fwbpQ5d1ZWA==",
"hasInstallScript": true,
"funding": {
"type": "opencollective",
@ -7048,7 +7196,6 @@
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.19.1.tgz",
"integrity": "sha512-2vJ6tjA/UfqLm2MPs7jxVybLoB8i1t1Jd9R3kISld20sIxPcTbLuggQOUxeWeAvIUkduv/CfMjuh4WmiXr2v9w==",
"dev": true,
"peer": true,
"dependencies": {
"call-bind": "^1.0.2",
"es-to-primitive": "^1.2.1",
@ -7088,7 +7235,6 @@
"resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz",
"integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==",
"dev": true,
"peer": true,
"dependencies": {
"is-callable": "^1.1.4",
"is-date-object": "^1.0.1",
@ -9003,7 +9149,6 @@
"resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz",
"integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==",
"dev": true,
"peer": true,
"dependencies": {
"call-bind": "^1.0.2",
"get-intrinsic": "^1.1.1"
@ -9374,7 +9519,6 @@
"resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz",
"integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==",
"dev": true,
"peer": true,
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
@ -9405,7 +9549,6 @@
"resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz",
"integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==",
"dev": true,
"peer": true,
"dependencies": {
"has-symbols": "^1.0.2"
},
@ -9499,6 +9642,18 @@
"he": "bin/he"
}
},
"node_modules/homedir-polyfill": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz",
"integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==",
"dev": true,
"dependencies": {
"parse-passwd": "^1.0.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/hosted-git-info": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz",
@ -9848,7 +10003,6 @@
"resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz",
"integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==",
"dev": true,
"peer": true,
"dependencies": {
"get-intrinsic": "^1.1.0",
"has": "^1.0.3",
@ -9904,7 +10058,6 @@
"resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz",
"integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==",
"dev": true,
"peer": true,
"dependencies": {
"has-bigints": "^1.0.1"
},
@ -9929,7 +10082,6 @@
"resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz",
"integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==",
"dev": true,
"peer": true,
"dependencies": {
"call-bind": "^1.0.2",
"has-tostringtag": "^1.0.0"
@ -9951,7 +10103,6 @@
"resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz",
"integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==",
"dev": true,
"peer": true,
"engines": {
"node": ">= 0.4"
},
@ -10000,7 +10151,6 @@
"resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz",
"integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==",
"dev": true,
"peer": true,
"dependencies": {
"has-tostringtag": "^1.0.0"
},
@ -10099,7 +10249,6 @@
"resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz",
"integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==",
"dev": true,
"peer": true,
"engines": {
"node": ">= 0.4"
},
@ -10121,7 +10270,6 @@
"resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.6.tgz",
"integrity": "sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g==",
"dev": true,
"peer": true,
"dependencies": {
"has-tostringtag": "^1.0.0"
},
@ -10162,7 +10310,6 @@
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz",
"integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==",
"dev": true,
"peer": true,
"dependencies": {
"call-bind": "^1.0.2",
"has-tostringtag": "^1.0.0"
@ -10189,7 +10336,6 @@
"resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.1.tgz",
"integrity": "sha512-IU0NmyknYZN0rChcKhRO1X8LYz5Isj/Fsqh8NJOSf+N/hCOTwy29F32Ik7a+QszE63IdvmwdTPDd6cZ5pg4cwA==",
"dev": true,
"peer": true,
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
@ -10211,7 +10357,6 @@
"resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz",
"integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==",
"dev": true,
"peer": true,
"dependencies": {
"has-tostringtag": "^1.0.0"
},
@ -10227,7 +10372,6 @@
"resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz",
"integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==",
"dev": true,
"peer": true,
"dependencies": {
"has-symbols": "^1.0.2"
},
@ -10249,7 +10393,6 @@
"resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz",
"integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==",
"dev": true,
"peer": true,
"dependencies": {
"call-bind": "^1.0.2"
},
@ -13313,6 +13456,28 @@
"lz-string": "bin/bin.js"
}
},
"node_modules/make-dir": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz",
"integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==",
"dev": true,
"dependencies": {
"pify": "^4.0.1",
"semver": "^5.6.0"
},
"engines": {
"node": ">=6"
}
},
"node_modules/make-dir/node_modules/semver": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
"dev": true,
"bin": {
"semver": "bin/semver"
}
},
"node_modules/make-fetch-happen": {
"version": "9.1.0",
"resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz",
@ -14135,6 +14300,25 @@
"@sinonjs/commons": "^1.7.0"
}
},
"node_modules/node-environment-flags": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.6.tgz",
"integrity": "sha512-5Evy2epuL+6TM0lCQGpFIj6KwiEsGh1SrHUhTbNX+sLbBtjidPZFAnVK9y5yU1+h//RitLbRHTIMyxQPtxMdHw==",
"dev": true,
"dependencies": {
"object.getownpropertydescriptors": "^2.0.3",
"semver": "^5.7.0"
}
},
"node_modules/node-environment-flags/node_modules/semver": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
"dev": true,
"bin": {
"semver": "bin/semver"
}
},
"node_modules/node-fetch": {
"version": "2.6.7",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
@ -14599,7 +14783,6 @@
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz",
"integrity": "sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g==",
"dev": true,
"peer": true,
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
@ -14643,6 +14826,23 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/object.getownpropertydescriptors": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.3.tgz",
"integrity": "sha512-VdDoCwvJI4QdC6ndjpqFmoL3/+HxffFBbcJzKi5hwLLqqx3mdbedRpfZDdK0SrOSauj8X4GzBvnDZl4vTN7dOw==",
"dev": true,
"dependencies": {
"call-bind": "^1.0.2",
"define-properties": "^1.1.3",
"es-abstract": "^1.19.1"
},
"engines": {
"node": ">= 0.8"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/object.pick": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz",
@ -14877,6 +15077,15 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/parse-passwd": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz",
"integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=",
"dev": true,
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/parse5": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz",
@ -15001,10 +15210,19 @@
"url": "https://github.com/sponsors/jonschlinkert"
}
},
"node_modules/pify": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz",
"integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==",
"dev": true,
"engines": {
"node": ">=6"
}
},
"node_modules/pirates": {
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.4.tgz",
"integrity": "sha512-ZIrVPH+A52Dw84R0L3/VS9Op04PuQ2SEoJL6bkshmiTic/HldyW9Tf7oH5mhJZBK7NmDx27vSMrYEXPXclpDKw==",
"version": "4.0.5",
"resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz",
"integrity": "sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==",
"dev": true,
"engines": {
"node": ">= 6"
@ -16776,7 +16994,6 @@
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
"integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
"dev": true,
"peer": true,
"dependencies": {
"call-bind": "^1.0.0",
"get-intrinsic": "^1.0.2",
@ -17580,7 +17797,6 @@
"resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz",
"integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==",
"dev": true,
"peer": true,
"dependencies": {
"call-bind": "^1.0.2",
"define-properties": "^1.1.3"
@ -17594,7 +17810,6 @@
"resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz",
"integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==",
"dev": true,
"peer": true,
"dependencies": {
"call-bind": "^1.0.2",
"define-properties": "^1.1.3"
@ -18541,7 +18756,6 @@
"resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz",
"integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==",
"dev": true,
"peer": true,
"dependencies": {
"function-bind": "^1.1.1",
"has-bigints": "^1.0.1",
@ -18861,6 +19075,18 @@
"node": ">= 8"
}
},
"node_modules/v8flags": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.2.0.tgz",
"integrity": "sha512-mH8etigqMfiGWdeXpaaqGfs6BndypxusHHcv2qSHyZkGEznCd/qAXCWWRzeowtL54147cktFOC4P5y+kl8d8Jg==",
"dev": true,
"dependencies": {
"homedir-polyfill": "^1.0.1"
},
"engines": {
"node": ">= 0.10"
}
},
"node_modules/validate-npm-package-license": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
@ -19553,7 +19779,6 @@
"resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz",
"integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==",
"dev": true,
"peer": true,
"dependencies": {
"is-bigint": "^1.0.1",
"is-boolean-object": "^1.1.0",
@ -20134,6 +20359,20 @@
"js-tokens": "^4.0.0"
}
},
"@babel/node": {
"version": "7.17.10",
"resolved": "https://registry.npmjs.org/@babel/node/-/node-7.17.10.tgz",
"integrity": "sha512-sFFMyvw23U8QOcTnLJnw2/Myr01e4+iLVy7rHAHrNSnXAfnwS3j2NqihpmZm7TotyNKKf/y8cJ96T5asY46eyw==",
"dev": true,
"requires": {
"@babel/register": "^7.17.7",
"commander": "^4.0.1",
"core-js": "^3.22.1",
"node-environment-flags": "^1.0.5",
"regenerator-runtime": "^0.13.4",
"v8flags": "^3.1.1"
}
},
"@babel/parser": {
"version": "7.16.8",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.16.8.tgz",
@ -20946,6 +21185,90 @@
"esutils": "^2.0.2"
}
},
"@babel/register": {
"version": "7.17.7",
"resolved": "https://registry.npmjs.org/@babel/register/-/register-7.17.7.tgz",
"integrity": "sha512-fg56SwvXRifootQEDQAu1mKdjh5uthPzdO0N6t358FktfL4XjAVXuH58ULoiW8mesxiOgNIrxiImqEwv0+hRRA==",
"dev": true,
"requires": {
"clone-deep": "^4.0.1",
"find-cache-dir": "^2.0.0",
"make-dir": "^2.1.0",
"pirates": "^4.0.5",
"source-map-support": "^0.5.16"
},
"dependencies": {
"find-cache-dir": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz",
"integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==",
"dev": true,
"requires": {
"commondir": "^1.0.1",
"make-dir": "^2.0.0",
"pkg-dir": "^3.0.0"
}
},
"find-up": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
"integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
"dev": true,
"requires": {
"locate-path": "^3.0.0"
}
},
"locate-path": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
"integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
"dev": true,
"requires": {
"p-locate": "^3.0.0",
"path-exists": "^3.0.0"
}
},
"p-limit": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
"integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
"dev": true,
"requires": {
"p-try": "^2.0.0"
}
},
"p-locate": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
"integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
"dev": true,
"requires": {
"p-limit": "^2.0.0"
}
},
"p-try": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
"integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
"dev": true
},
"path-exists": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
"integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=",
"dev": true
},
"pkg-dir": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz",
"integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==",
"dev": true,
"requires": {
"find-up": "^3.0.0"
}
}
}
},
"@babel/runtime": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.16.7.tgz",
@ -24360,6 +24683,12 @@
"delayed-stream": "~1.0.0"
}
},
"commander": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz",
"integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==",
"dev": true
},
"comment-parser": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.3.0.tgz",
@ -24488,9 +24817,9 @@
"dev": true
},
"core-js": {
"version": "3.22.0",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.22.0.tgz",
"integrity": "sha512-8h9jBweRjMiY+ORO7bdWSeWfHhLPO7whobj7Z2Bl0IDo00C228EdGgH7FE4jGumbEjzcFfkfW8bXgdkEDhnwHQ=="
"version": "3.22.5",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.22.5.tgz",
"integrity": "sha512-VP/xYuvJ0MJWRAobcmQ8F2H6Bsn+s7zqAAjFaHGBMc5AQm7zaelhD1LGduFn2EehEcQcU+br6t+fwbpQ5d1ZWA=="
},
"core-js-compat": {
"version": "3.20.3",
@ -25180,7 +25509,6 @@
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.19.1.tgz",
"integrity": "sha512-2vJ6tjA/UfqLm2MPs7jxVybLoB8i1t1Jd9R3kISld20sIxPcTbLuggQOUxeWeAvIUkduv/CfMjuh4WmiXr2v9w==",
"dev": true,
"peer": true,
"requires": {
"call-bind": "^1.0.2",
"es-to-primitive": "^1.2.1",
@ -25214,7 +25542,6 @@
"resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz",
"integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==",
"dev": true,
"peer": true,
"requires": {
"is-callable": "^1.1.4",
"is-date-object": "^1.0.1",
@ -26642,7 +26969,6 @@
"resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz",
"integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==",
"dev": true,
"peer": true,
"requires": {
"call-bind": "^1.0.2",
"get-intrinsic": "^1.1.1"
@ -26928,8 +27254,7 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz",
"integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==",
"dev": true,
"peer": true
"dev": true
},
"has-flag": {
"version": "3.0.0",
@ -26948,7 +27273,6 @@
"resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz",
"integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==",
"dev": true,
"peer": true,
"requires": {
"has-symbols": "^1.0.2"
}
@ -27022,6 +27346,15 @@
"resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
"integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw=="
},
"homedir-polyfill": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz",
"integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==",
"dev": true,
"requires": {
"parse-passwd": "^1.0.0"
}
},
"hosted-git-info": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz",
@ -27282,7 +27615,6 @@
"resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz",
"integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==",
"dev": true,
"peer": true,
"requires": {
"get-intrinsic": "^1.1.0",
"has": "^1.0.3",
@ -27329,7 +27661,6 @@
"resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz",
"integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==",
"dev": true,
"peer": true,
"requires": {
"has-bigints": "^1.0.1"
}
@ -27348,7 +27679,6 @@
"resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz",
"integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==",
"dev": true,
"peer": true,
"requires": {
"call-bind": "^1.0.2",
"has-tostringtag": "^1.0.0"
@ -27363,8 +27693,7 @@
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz",
"integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==",
"dev": true,
"peer": true
"dev": true
},
"is-ci": {
"version": "2.0.0",
@ -27398,7 +27727,6 @@
"resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz",
"integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==",
"dev": true,
"peer": true,
"requires": {
"has-tostringtag": "^1.0.0"
}
@ -27463,8 +27791,7 @@
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz",
"integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==",
"dev": true,
"peer": true
"dev": true
},
"is-number": {
"version": "7.0.0",
@ -27477,7 +27804,6 @@
"resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.6.tgz",
"integrity": "sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g==",
"dev": true,
"peer": true,
"requires": {
"has-tostringtag": "^1.0.0"
}
@ -27506,7 +27832,6 @@
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz",
"integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==",
"dev": true,
"peer": true,
"requires": {
"call-bind": "^1.0.2",
"has-tostringtag": "^1.0.0"
@ -27523,8 +27848,7 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.1.tgz",
"integrity": "sha512-IU0NmyknYZN0rChcKhRO1X8LYz5Isj/Fsqh8NJOSf+N/hCOTwy29F32Ik7a+QszE63IdvmwdTPDd6cZ5pg4cwA==",
"dev": true,
"peer": true
"dev": true
},
"is-stream": {
"version": "2.0.1",
@ -27537,7 +27861,6 @@
"resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz",
"integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==",
"dev": true,
"peer": true,
"requires": {
"has-tostringtag": "^1.0.0"
}
@ -27547,7 +27870,6 @@
"resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz",
"integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==",
"dev": true,
"peer": true,
"requires": {
"has-symbols": "^1.0.2"
}
@ -27563,7 +27885,6 @@
"resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz",
"integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==",
"dev": true,
"peer": true,
"requires": {
"call-bind": "^1.0.2"
}
@ -29911,6 +30232,24 @@
"integrity": "sha1-wNjq82BZ9wV5bh40SBHPTEmNOiY=",
"dev": true
},
"make-dir": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz",
"integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==",
"dev": true,
"requires": {
"pify": "^4.0.1",
"semver": "^5.6.0"
},
"dependencies": {
"semver": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
"dev": true
}
}
},
"make-fetch-happen": {
"version": "9.1.0",
"resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz",
@ -30553,6 +30892,24 @@
}
}
},
"node-environment-flags": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.6.tgz",
"integrity": "sha512-5Evy2epuL+6TM0lCQGpFIj6KwiEsGh1SrHUhTbNX+sLbBtjidPZFAnVK9y5yU1+h//RitLbRHTIMyxQPtxMdHw==",
"dev": true,
"requires": {
"object.getownpropertydescriptors": "^2.0.3",
"semver": "^5.7.0"
},
"dependencies": {
"semver": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
"dev": true
}
}
},
"node-fetch": {
"version": "2.6.7",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
@ -30919,8 +31276,7 @@
"version": "1.12.0",
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz",
"integrity": "sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g==",
"dev": true,
"peer": true
"dev": true
},
"object-keys": {
"version": "1.1.1",
@ -30949,6 +31305,17 @@
"object-keys": "^1.1.1"
}
},
"object.getownpropertydescriptors": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.3.tgz",
"integrity": "sha512-VdDoCwvJI4QdC6ndjpqFmoL3/+HxffFBbcJzKi5hwLLqqx3mdbedRpfZDdK0SrOSauj8X4GzBvnDZl4vTN7dOw==",
"dev": true,
"requires": {
"call-bind": "^1.0.2",
"define-properties": "^1.1.3",
"es-abstract": "^1.19.1"
}
},
"object.pick": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz",
@ -31107,6 +31474,12 @@
"lines-and-columns": "^1.1.6"
}
},
"parse-passwd": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz",
"integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=",
"dev": true
},
"parse5": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz",
@ -31209,10 +31582,16 @@
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
"dev": true
},
"pify": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz",
"integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==",
"dev": true
},
"pirates": {
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.4.tgz",
"integrity": "sha512-ZIrVPH+A52Dw84R0L3/VS9Op04PuQ2SEoJL6bkshmiTic/HldyW9Tf7oH5mhJZBK7NmDx27vSMrYEXPXclpDKw==",
"version": "4.0.5",
"resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz",
"integrity": "sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==",
"dev": true
},
"pkg-dir": {
@ -32546,7 +32925,6 @@
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
"integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
"dev": true,
"peer": true,
"requires": {
"call-bind": "^1.0.0",
"get-intrinsic": "^1.0.2",
@ -33203,7 +33581,6 @@
"resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz",
"integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==",
"dev": true,
"peer": true,
"requires": {
"call-bind": "^1.0.2",
"define-properties": "^1.1.3"
@ -33214,7 +33591,6 @@
"resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz",
"integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==",
"dev": true,
"peer": true,
"requires": {
"call-bind": "^1.0.2",
"define-properties": "^1.1.3"
@ -33926,7 +34302,6 @@
"resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz",
"integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==",
"dev": true,
"peer": true,
"requires": {
"function-bind": "^1.1.1",
"has-bigints": "^1.0.1",
@ -34187,6 +34562,15 @@
}
}
},
"v8flags": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.2.0.tgz",
"integrity": "sha512-mH8etigqMfiGWdeXpaaqGfs6BndypxusHHcv2qSHyZkGEznCd/qAXCWWRzeowtL54147cktFOC4P5y+kl8d8Jg==",
"dev": true,
"requires": {
"homedir-polyfill": "^1.0.1"
}
},
"validate-npm-package-license": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
@ -34703,7 +35087,6 @@
"resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz",
"integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==",
"dev": true,
"peer": true,
"requires": {
"is-bigint": "^1.0.1",
"is-boolean-object": "^1.1.0",

@ -15,7 +15,8 @@
"lint:fix": "eslint '**/src/**/*.{vue,js}' --fix",
"test": "jest",
"test:watch": "jest --watch",
"test:jsunit": "karma start tests/karma.config.js --single-run"
"test:jsunit": "karma start tests/karma.config.js --single-run",
"sass:icons": "babel-node core/src/icons.js"
},
"repository": {
"type": "git",
@ -97,6 +98,7 @@
"webdav": "^4.8.0"
},
"devDependencies": {
"@babel/node": "^7.17.10",
"@nextcloud/babel-config": "^1.0.0",
"@nextcloud/browserslist-config": "^2.2.0",
"@nextcloud/eslint-config": "^7.0.2",

@ -1,198 +0,0 @@
<?php
declare(strict_types = 1);
/**
* @copyright Copyright (c) 2018 Michael Weimann <mail@michael-weimann.eu>
*
* @author Michael Weimann <mail@michael-weimann.eu>
*
* @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 <http://www.gnu.org/licenses/>.
*
*/
namespace Tests\Core\Controller;
use OC\AppFramework\Http;
use OC\Core\Controller\SvgController;
use OC\Template\IconsCacher;
use OCP\App\AppPathNotFoundException;
use OCP\App\IAppManager;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\IRequest;
use Test\TestCase;
/**
* This class provides test cases for the svg controller
*/
class SvgControllerTest extends TestCase {
public const TEST_IMAGES_SOURCE_PATH = __DIR__ . '/../../data/svg';
public const TEST_IMAGES_PATH = __DIR__ . '/../../../core/img/testImages';
public const TEST_IMAGE_MIXED = 'mixed-source.svg';
public const TEST_IMAGE_RECT = 'rect-black.svg';
public const TEST_IMAGES = [
self::TEST_IMAGE_MIXED,
self::TEST_IMAGE_RECT,
];
/** @var IAppManager|\PHPUnit\Framework\MockObject\MockObject */
private $appManager;
/**
* @var SvgController
*/
private $svgController;
/**
* Copy test svgs into the core img "test" directory.
*
* @beforeClass
* @return void
*/
public static function copyTestImagesIntoPlace() {
mkdir(self::TEST_IMAGES_PATH);
foreach (self::TEST_IMAGES as $testImage) {
copy(
self::TEST_IMAGES_SOURCE_PATH .'/' . $testImage,
self::TEST_IMAGES_PATH . '/' . $testImage
);
}
}
/**
* Removes the test svgs from the core img "test" directory.
*
* @afterClass
* @return void
*/
public static function removeTestImages() {
foreach (self::TEST_IMAGES as $testImage) {
unlink(self::TEST_IMAGES_PATH . '/' . $testImage);
}
rmdir(self::TEST_IMAGES_PATH);
}
/**
* Setups a SVG controller instance for tests.
*
* @before
* @return void
*/
public function setupSvgController() {
/** @var IRequest */
$request = $this->getMockBuilder(IRequest::class)->getMock();
/** @var ITimeFactory $timeFactory */
$timeFactory = $this->getMockBuilder(ITimeFactory::class)->getMock();
/** @var IAppManager */
$this->appManager = $this->getMockBuilder(IAppManager::class)->getMock();
/** @var IconsCacher $iconsCacher */
$iconsCacher = $this->getMockBuilder(IconsCacher::class)->disableOriginalConstructor()->setMethods(['__construct'])->getMock();
$this->svgController = new SvgController('core', $request, $timeFactory, $this->appManager, $iconsCacher);
}
/**
* Checks that requesting an unknown image results in a 404.
*
* @return void
*/
public function testGetSvgFromCoreNotFound() {
$response = $this->svgController->getSvgFromCore('huhuu', '2342', '#ff0000');
self::assertEquals(Http::STATUS_NOT_FOUND, $response->getStatus());
}
/**
* Provides svg coloring test data.
*
* @return array
*/
public function provideGetSvgFromCoreTestData(): array {
return [
'mixed' => ['mixed-source', 'f00', file_get_contents(self::TEST_IMAGES_SOURCE_PATH . '/mixed-red.svg')],
'black rect' => ['rect-black', 'f00', file_get_contents(self::TEST_IMAGES_SOURCE_PATH . '/rect-red.svg')],
];
}
/**
* Tests that retrieving a colored SVG works.
*
* @dataProvider provideGetSvgFromCoreTestData
* @param string $name The requested svg name
* @param string $color The requested color
* @param string $expected The expected svg
* @return void
*/
public function testGetSvgFromCore(string $name, string $color, string $expected) {
$response = $this->svgController->getSvgFromCore('testImages', $name, $color);
self::assertEquals(Http::STATUS_OK, $response->getStatus());
$headers = $response->getHeaders();
self::assertArrayHasKey('Content-Type', $headers);
self::assertEquals($headers['Content-Type'], 'image/svg+xml');
self::assertEquals($expected, $response->getData());
}
/**
* Checks that requesting an unknown image results in a 404.
*/
public function testGetSvgFromAppNotFound(): void {
$this->appManager->expects($this->once())
->method('getAppPath')
->with('invalid_app')
->willThrowException(new AppPathNotFoundException('Could not find path for invalid_app'));
$response = $this->svgController->getSvgFromApp('invalid_app', 'some-icon', '#ff0000');
self::assertEquals(Http::STATUS_NOT_FOUND, $response->getStatus());
}
/**
* Provides svg coloring test data.
*
* @return array
*/
public function provideGetSvgFromAppTestData(): array {
return [
'settings admin' => ['settings', 'admin', 'f00', file_get_contents(self::TEST_IMAGES_SOURCE_PATH . '/settings-admin-red.svg')],
'files app' => ['files', 'app', 'f00', file_get_contents(self::TEST_IMAGES_SOURCE_PATH . '/files-app-red.svg')],
];
}
/**
* Tests that retrieving a colored SVG works.
*
* @dataProvider provideGetSvgFromAppTestData
* @param string $appName
* @param string $name The requested svg name
* @param string $color The requested color
* @param string $expected
*/
public function testGetSvgFromApp(string $appName, string $name, string $color, string $expected): void {
$this->appManager->expects($this->once())
->method('getAppPath')
->with($appName)
->willReturn(realpath(__DIR__ . '/../../../apps/') . '/' . $appName);
$response = $this->svgController->getSvgFromApp($appName, $name, $color);
self::assertEquals(Http::STATUS_OK, $response->getStatus());
$headers = $response->getHeaders();
self::assertArrayHasKey('Content-Type', $headers);
self::assertEquals($headers['Content-Type'], 'image/svg+xml');
self::assertEquals($expected, $response->getData());
}
}

@ -27,7 +27,6 @@ use OC\AppConfig;
use OC\Files\AppData\AppData;
use OC\Files\AppData\Factory;
use OC\Template\CSSResourceLocator;
use OC\Template\IconsCacher;
use OC\Template\SCSSCacher;
use OCA\Theming\ThemingDefaults;
use OCP\AppFramework\Utility\ITimeFactory;
@ -50,8 +49,6 @@ class CSSResourceLocatorTest extends \Test\TestCase {
protected $cacheFactory;
/** @var LoggerInterface|\PHPUnit\Framework\MockObject\MockObject */
protected $logger;
/** @var IconsCacher|\PHPUnit\Framework\MockObject\MockObject */
protected $iconsCacher;
/** @var ITimeFactory|\PHPUnit\Framework\MockObject\MockObject */
private $timeFactory;
/** @var AppConfig|\PHPUnit\Framework\MockObject\MockObject */
@ -66,7 +63,6 @@ class CSSResourceLocatorTest extends \Test\TestCase {
$this->config = $this->createMock(IConfig::class);
$this->cacheFactory = $this->createMock(ICacheFactory::class);
$this->themingDefaults = $this->createMock(ThemingDefaults::class);
$this->iconsCacher = $this->createMock(IconsCacher::class);
$this->timeFactory = $this->createMock(ITimeFactory::class);
$this->appConfig = $this->createMock(AppConfig::class);
}
@ -83,7 +79,6 @@ class CSSResourceLocatorTest extends \Test\TestCase {
$this->themingDefaults,
\OC::$SERVERROOT,
$this->cacheFactory,
$this->iconsCacher,
$this->timeFactory,
$this->appConfig
);

@ -1,149 +0,0 @@
<?php
declare(strict_types = 1);
/**
* @copyright Copyright (c) 2018, John Molakvoæ (skjnldsv@protonmail.com)
*
* @author John Molakvoæ (skjnldsv) <skjnldsv@protonmail.com>
*
* @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 <http://www.gnu.org/licenses/>.
*
*/
namespace Test\Template;
use OC\Files\AppData\AppData;
use OC\Files\AppData\Factory;
use OC\Template\IconsCacher;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\Files\IAppData;
use OCP\Files\SimpleFS\ISimpleFile;
use OCP\Files\SimpleFS\ISimpleFolder;
use OCP\IURLGenerator;
use Psr\Log\LoggerInterface;
class IconsCacherTest extends \Test\TestCase {
/** @var LoggerInterface|\PHPUnit\Framework\MockObject\MockObject */
protected $logger;
/** @var IAppData|\PHPUnit\Framework\MockObject\MockObject */
protected $appData;
/** @var IURLGenerator|\PHPUnit\Framework\MockObject\MockObject */
protected $urlGenerator;
/** @var ITimeFactory|\PHPUnit\Framework\MockObject\MockObject */
private $timeFactory;
protected function setUp(): void {
$this->logger = $this->createMock(LoggerInterface::class);
$this->appData = $this->createMock(AppData::class);
$this->timeFactory = $this->createMock(ITimeFactory::class);
/** @var Factory|\PHPUnit\Framework\MockObject\MockObject $factory */
$factory = $this->createMock(Factory::class);
$factory->method('get')->with('css')->willReturn($this->appData);
$this->folder = $this->createMock(ISimpleFolder::class);
$this->appData->method('getFolder')->willReturn($this->folder);
$this->urlGenerator = $this->createMock(IURLGenerator::class);
$this->iconsCacher = new IconsCacher(
$this->logger,
$factory,
$this->urlGenerator,
$this->timeFactory
);
}
public function testGetIconsFromEmptyCss() {
$css = "
icon.test {
color: #aaa;
}
";
$icons = self::invokePrivate($this->iconsCacher, 'getIconsFromCss', [$css]);
$this->assertTrue(empty($icons));
}
public function testGetIconsFromValidCss() {
$css = "
icon.test {
--icon-test: url('/svg/core/actions/add/000?v=1');
background-image: var(--icon-test);
}
";
$actual = self::invokePrivate($this->iconsCacher, 'getIconsFromCss', [$css]);
$expected = [
'icon-test' => '/svg/core/actions/add/000?v=1'
];
$this->assertEquals($expected, $actual);
}
public function testSetIconsFromEmptyCss() {
$expected = "
icon.test {
color: #aaa;
}
";
$actual = $this->iconsCacher->setIconsCss($expected);
$this->assertEquals($expected, $actual);
}
public function testSetIconsFromValidCss() {
$css = "
icon.test {
--icon-test: url('/index.php/svg/core/actions/add?color=000&v=1');
background-image: var(--icon-test);
}
";
$expected = "
icon.test {
\n background-image: var(--icon-test);
}
";
$iconsFile = $this->createMock(ISimpleFile::class);
$this->folder->expects($this->exactly(2))
->method('getFile')
->willReturn($iconsFile);
$actual = $this->iconsCacher->setIconsCss($css);
$this->assertEquals($expected, $actual);
}
public function testSetIconsFromValidCssMultipleTimes() {
$css = "
icon.test {
--icon-test: url('/index.php/svg/core/actions/add?color=000&v=1');
background-image: var(--icon-test);
}
";
$expected = "
icon.test {
\n background-image: var(--icon-test);
}
";
$iconsFile = $this->createMock(ISimpleFile::class);
$this->folder->expects($this->exactly(4))
->method('getFile')
->willReturn($iconsFile);
$actual = $this->iconsCacher->setIconsCss($css);
$actual = $this->iconsCacher->setIconsCss($actual);
$actual = $this->iconsCacher->setIconsCss($actual);
$this->assertEquals($expected, $actual);
}
}

@ -26,7 +26,6 @@ namespace Test\Template;
use OC\AppConfig;
use OC\Files\AppData\AppData;
use OC\Files\AppData\Factory;
use OC\Template\IconsCacher;
use OC\Template\SCSSCacher;
use OCA\Theming\ThemingDefaults;
use OCP\AppFramework\Utility\ITimeFactory;
@ -59,8 +58,6 @@ class SCSSCacherTest extends \Test\TestCase {
protected $isCachedCache;
/** @var ICacheFactory|\PHPUnit\Framework\MockObject\MockObject */
protected $cacheFactory;
/** @var IconsCacher|\PHPUnit\Framework\MockObject\MockObject */
protected $iconsCacher;
/** @var ITimeFactory|\PHPUnit\Framework\MockObject\MockObject */
protected $timeFactory;
/** @var AppConfig|\PHPUnit\Framework\MockObject\MockObject */
@ -70,7 +67,6 @@ class SCSSCacherTest extends \Test\TestCase {
parent::setUp();
$this->logger = $this->createMock(LoggerInterface::class);
$this->appData = $this->createMock(AppData::class);
$this->iconsCacher = $this->createMock(IconsCacher::class);
$this->timeFactory = $this->createMock(ITimeFactory::class);
/** @var Factory|\PHPUnit\Framework\MockObject\MockObject $factory */
@ -104,9 +100,6 @@ class SCSSCacherTest extends \Test\TestCase {
$this->themingDefaults->expects($this->any())->method('getScssVariables')->willReturn([]);
$iconsFile = $this->createMock(ISimpleFile::class);
$this->iconsCacher->expects($this->any())
->method('getCachedCSS')
->willReturn($iconsFile);
$this->appConfig = $this->createMock(AppConfig::class);
@ -118,7 +111,6 @@ class SCSSCacherTest extends \Test\TestCase {
$this->themingDefaults,
\OC::$SERVERROOT,
$this->cacheFactory,
$this->iconsCacher,
$this->timeFactory,
$this->appConfig
);
@ -159,10 +151,6 @@ class SCSSCacherTest extends \Test\TestCase {
->method('getBaseUrl')
->willReturn('http://localhost/nextcloud');
$this->iconsCacher->expects($this->any())
->method('setIconsCss')
->willReturn('scss {}');
$actual = $this->scssCacher->process(\OC::$SERVERROOT, '/core/css/styles.scss', 'core');
$this->assertTrue($actual);
}
@ -195,10 +183,6 @@ class SCSSCacherTest extends \Test\TestCase {
->with($filePrefix.'styles.css.deps')
->willReturn($fileDeps);
$this->iconsCacher->expects($this->any())
->method('setIconsCss')
->willReturn('scss {}');
$actual = $this->scssCacher->process(\OC::$SERVERROOT, '/core/css/styles.scss', 'core');
$this->assertTrue($actual);
}
@ -226,10 +210,6 @@ class SCSSCacherTest extends \Test\TestCase {
$this->fail();
});
$this->iconsCacher->expects($this->any())
->method('setIconsCss')
->willReturn('scss {}');
$actual = $this->scssCacher->process(\OC::$SERVERROOT, '/core/css/styles.scss', 'core');
$this->assertTrue($actual);
}
@ -264,10 +244,6 @@ class SCSSCacherTest extends \Test\TestCase {
$this->fail();
});
$this->iconsCacher->expects($this->any())
->method('setIconsCss')
->willReturn('scss {}');
$actual = $this->scssCacher->process(\OC::$SERVERROOT, '/core/css/styles.scss', 'core');
$this->assertTrue($actual);
}
@ -330,10 +306,6 @@ class SCSSCacherTest extends \Test\TestCase {
throw new \Exception();
});
$this->iconsCacher->expects($this->any())
->method('setIconsCss')
->willReturn('scss {}');
$file->expects($this->once())->method('putContent');
$depsFile->expects($this->once())->method('putContent');
$gzipFile->expects($this->once())->method('putContent');
@ -368,10 +340,6 @@ class SCSSCacherTest extends \Test\TestCase {
$depsFile->expects($this->once())->method('putContent');
$gzipFile->expects($this->once())->method('putContent');
$this->iconsCacher->expects($this->any())
->method('setIconsCss')
->willReturn('scss {}');
$actual = self::invokePrivate($this->scssCacher, 'cache', [$path, $fileNameCSS, $fileNameSCSS, $folder, $webDir]);
$this->assertTrue($actual);
}
@ -398,10 +366,6 @@ class SCSSCacherTest extends \Test\TestCase {
throw new \Exception();
});
$this->iconsCacher->expects($this->at(0))
->method('setIconsCss')
->willReturn('body{background-color:#0082c9}');
$file->expects($this->at(0))->method('putContent')->with($this->callback(
function ($content) {
return 'body{background-color:#0082c9}' === $content;

Loading…
Cancel
Save