summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLukas Reschke <lukas@statuscode.ch>2017-03-20 19:49:53 +0100
committerGitHub <noreply@github.com>2017-03-20 19:49:53 +0100
commit21cf1b22e9efa17aa4b9fcd4575c891c309c30df (patch)
treeee0dff452a18a887baaed583d081cf03c2608d57
parent03a92eaf74ea3898f67a12e3c19216683abb44d8 (diff)
parenta0f7d4b6888466600698a31a50a551f915c69045 (diff)
downloadnextcloud-server-21cf1b22e9efa17aa4b9fcd4575c891c309c30df.tar.gz
nextcloud-server-21cf1b22e9efa17aa4b9fcd4575c891c309c30df.zip
Merge pull request #3530 from nextcloud/scss-variables
Implement scss variables
-rwxr-xr-xautotest-js.sh7
-rw-r--r--core/css/apps.scss79
-rw-r--r--core/css/header.scss31
-rw-r--r--core/css/icons.scss8
-rw-r--r--core/css/inputs.scss126
-rw-r--r--core/css/multiselect.scss22
-rw-r--r--core/css/share.scss10
-rw-r--r--core/css/styles.scss161
-rw-r--r--core/css/tooltip.scss12
-rw-r--r--core/css/variables.scss22
-rw-r--r--lib/private/Template/SCSSCacher.php31
-rw-r--r--lib/private/TemplateLayout.php2
-rw-r--r--tests/data/scss/styles-error.scss1
-rw-r--r--tests/data/scss/styles-success.scss1
-rw-r--r--tests/lib/Template/SCSSCacherTest.php278
15 files changed, 528 insertions, 263 deletions
diff --git a/autotest-js.sh b/autotest-js.sh
index bd7310c4e43..5f03132ee42 100755
--- a/autotest-js.sh
+++ b/autotest-js.sh
@@ -24,7 +24,12 @@ mkdir -p "$PREFIX" && $NPM install --link --prefix "$PREFIX" || exit 3
# create scss test
mkdir -p tests/css
-./build/bin/node-sass --output tests/css core/css
+for SCSSFILE in core/css/*.scss
+do
+ FILE=$(basename $SCSSFILE)
+ FILENAME="${FILE%.*}"
+ printf "@import 'variables.scss'; @import '${FILE}';" | ./build/bin/node-sass --include-path core/css/ > tests/css/${FILE}.css
+done
KARMA="$PREFIX/node_modules/karma/bin/karma"
diff --git a/core/css/apps.scss b/core/css/apps.scss
index 91805fe16b2..e9ed9f470cd 100644
--- a/core/css/apps.scss
+++ b/core/css/apps.scss
@@ -55,13 +55,13 @@ em {
height: 100%;
float: left;
box-sizing: border-box;
- background-color: #fff;
+ background-color: $color-main-background;
padding-bottom: 44px;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
- border-right: 1px solid #eee;
+ border-right: 1px solid nc-darken($color-main-background, 8%);
display: flex;
flex-direction: column;
> ul {
@@ -78,7 +78,7 @@ em {
&,
> a {
opacity: 1;
- box-shadow: inset 2px 0 #0082c9;
+ box-shadow: inset 2px 0 $color-primary;
}
}
}
@@ -115,7 +115,7 @@ em {
box-sizing: border-box;
white-space: nowrap;
text-overflow: ellipsis;
- color: #000;
+ color: $color-main-text;
opacity: .57;
}
li > a:first-child img {
@@ -166,9 +166,9 @@ em {
-ms-transform: rotate(0);
transform: rotate(0);
}
- background-image: linear-gradient(top, rgb(238, 238, 238) 0%, rgb(245, 245, 245) 100%);
- background-image: -webkit-linear-gradient(top, rgb(238, 238, 238) 0%, rgb(245, 245, 245) 100%);
- background-image: -ms-linear-gradient(top, rgb(238, 238, 238) 0%, rgb(245, 245, 245) 100%);
+ background-image: linear-gradient(top, nc-darken($color-main-background, 8%) 0%, nc-darken($color-main-background, 3%) 100%);
+ background-image: -webkit-linear-gradient(top, nc-darken($color-main-background, 8%) 0%, nc-darken($color-main-background, 3%) 100%);
+ background-image: -ms-linear-gradient(top, nc-darken($color-main-background, 8%) 0%, nc-darken($color-main-background, 3%) 100%);
}
}
> {
@@ -190,7 +190,7 @@ em {
> ul .collapsible.open {
&:hover,
&:focus {
- box-shadow: inset 0 0 3px #ddd;
+ box-shadow: inset 0 0 3px $color-box-shadow;
}
ul {
display: block;
@@ -248,10 +248,10 @@ em {
padding-bottom: 40px;
}
.error {
- color: #dd1144;
+ color: $color-error;
}
.app-navigation-separator {
- border-bottom: 1px solid #ddd;
+ border-bottom: 1px solid nc-lighten($color-main-text, 86%);
}
/**
@@ -324,7 +324,7 @@ em {
margin-right: 0;
height: 38px;
float: left;
- border: 1px solid rgba(190, 190, 190, 0.9);
+ border: 1px solid rgba(nc-lighten($color-main-text, 73%), 0.9);
}
button,
input[type='submit'] {
@@ -377,8 +377,8 @@ em {
width: 27%;
min-width: 300px;
display: block;
- background: #fff;
- border-left: 1px solid #eee;
+ background: $color-main-background;
+ border-left: 1px solid nc-darken($color-main-background, 8%);
-webkit-transition: margin-right 300ms;
transition: margin-right 300ms;
overflow-x: hidden;
@@ -408,11 +408,11 @@ em {
#app-settings-content {
display: none;
padding: 10px;
- background-color: #fff;
+ background-color: $color-main-background;
/* restrict height of settings and make scrollable */
max-height: 300px;
overflow-y: auto;
- border-right: 1px solid #eee;
+ border-right: 1px solid nc-darken($color-main-background, 8%);
width: 250px;
box-sizing: border-box;
@@ -423,12 +423,12 @@ em {
.info-text {
padding: 5px 0 7px 22px;
- color: #999;
+ color: rgba($color-main-text, .4);
}
}
#app-settings-header {
- border-right: 1px solid #eee;
+ border-right: 1px solid nc-darken($color-main-background, 8%);
width: 250px;
box-sizing: border-box;
}
@@ -439,7 +439,7 @@ em {
width: 100%;
padding: 0;
margin: 0;
- background-color: #fff;
+ background-color: $color-main-background;
background-image: url('../img/actions/settings.svg?v=1');
background-position: 14px center;
background-repeat: no-repeat;
@@ -451,11 +451,11 @@ em {
font-weight: normal;
&:hover,
&:focus {
- background-color: #fff;
+ background-color: $color-main-background;
}
&.opened {
&:hover, &:focus {
- background-color: #fff;
+ background-color: $color-main-background;
}
}
}
@@ -464,7 +464,7 @@ em {
.section {
display: block;
padding: 30px;
- color: #555;
+ color: nc-lighten($color-main-text, 33%);
margin-bottom: 24px;
&.hidden {
display: none !important;
@@ -499,10 +499,10 @@ em {
/* DROPDOWN ----------------------------------------------------------------- */
.dropdown {
- background: #eee;
+ background: nc-darken($color-main-background, 8%);
border-bottom-left-radius: 5px;
border-bottom-right-radius: 5px;
- box-shadow: 0 1px 1px #777;
+ box-shadow: 0 1px 1px $color-box-shadow;
display: block;
margin-right: 0;
position: absolute;
@@ -520,25 +520,25 @@ em {
float: left;
padding: 5px;
cursor: pointer;
- color: #888;
+ color: nc-lighten($color-main-text, 33%);
margin-bottom: 1px;
a {
- color: #888;
+ color: nc-lighten($color-main-text, 33%);
margin-bottom: 1px;
}
&.selected {
font-weight: 600;
- border-bottom: 1px solid #333;
+ border-bottom: 1px solid nc-lighten($color-main-text, 20%);
}
&:hover {
- border-bottom: 1px solid #333;
+ border-bottom: 1px solid nc-lighten($color-main-text, 20%);
}
&.selected, &:hover {
margin-bottom: 0px;
- color: #000;
+ color: $color-main-text;
a {
margin-bottom: 0px;
- color: #000;
+ color: $color-main-text;
}
}
}
@@ -557,7 +557,7 @@ em {
.popovermenu, .popovermenu:after,
#app-navigation .app-navigation-entry-menu,
#app-navigation .app-navigation-entry-menu:after {
- border: 1px solid #eee;
+ border: 1px solid nc-darken($color-main-background, 8%);
}
}
@@ -565,18 +565,18 @@ em {
.app-navigation-entry-menu,
.popovermenu {
position: absolute;
- background-color: #fff;
- color: #333;
+ background-color: $color-main-background;
+ color: nc-lighten($color-main-text, 20%);
border-radius: 3px;
z-index: 110;
margin: 5px;
margin-top: -5px;
right: 0;
- -webkit-filter: drop-shadow(0 0 5px rgba(150, 150, 150, 0.75));
- -moz-filter: drop-shadow(0 0 5px rgba(150, 150, 150, 0.75));
- -ms-filter: drop-shadow(0 0 5px rgba(150, 150, 150, 0.75));
- -o-filter: drop-shadow(0 0 5px rgba(150, 150, 150, 0.75));
- filter: drop-shadow(0 0 5px rgba(150, 150, 150, 0.75));
+ -webkit-filter: drop-shadow(0 0 5px $color-box-shadow);
+ -moz-filter: drop-shadow(0 0 5px $color-box-shadow);
+ -ms-filter: drop-shadow(0 0 5px $color-box-shadow);
+ -o-filter: drop-shadow(0 0 5px $color-box-shadow);
+ filter: drop-shadow(0 0 5px $color-box-shadow);
display: none;
&:after {
@@ -591,8 +591,7 @@ em {
width: 0;
position: absolute;
pointer-events: none;
- border-color: rgba(238, 238, 238, 0);
- border-bottom-color: #fff;
+ border-bottom-color: $color-main-background;
border-width: 10px;
}
/* Center the popover */
@@ -644,7 +643,7 @@ em {
margin: 0;
font-weight: inherit;
box-shadow: none;
- color: #333 !important; /* Overwrite app-navigation li */
+ color: nc-lighten($color-main-text, 20%) !important; /* Overwrite app-navigation li */
/* prevent .action class to break the design */
&.action {
padding: inherit !important;
diff --git a/core/css/header.scss b/core/css/header.scss
index fd2da104c38..0687a6fed13 100644
--- a/core/css/header.scss
+++ b/core/css/header.scss
@@ -25,8 +25,7 @@
&.menu:after,
.menu:after {
border: 10px solid transparent;
- border-color: transparent;
- border-bottom-color: #fff;
+ border-bottom-color: $color-main-background;
bottom: 100%;
content: ' ';
height: 0;
@@ -47,7 +46,7 @@
&:focus {
left: 76px;
top: -9px;
- color: #fff;
+ color: $color-primary-text;
width: auto;
height: auto;
}
@@ -64,7 +63,7 @@
right: 0;
z-index: 2000;
height: 45px;
- background-color: #0082c9;
+ background-color: $color-primary;
box-sizing: border-box;
justify-content: space-between;
}
@@ -90,7 +89,7 @@
#header {
.logo {
- background-image: url('../img/logo-icon.svg?v=1');
+ background-image: url('#{$image-logo}');
background-repeat: no-repeat;
background-size: 175px;
background-position: center;
@@ -101,7 +100,7 @@
.logo-icon {
/* display logo so appname can be shown next to it */
display: inline-block;
- background-image: url('../img/logo-icon.svg?v=1');
+ background-image: url($image-logo);
background-repeat: no-repeat;
background-position: center center;
width: 62px;
@@ -176,7 +175,7 @@
.header-appname {
display: inline-block;
position: relative;
- color: #fff;
+ color: $color-primary-text;
font-size: 16px;
font-weight: 300;
margin: 0;
@@ -203,8 +202,8 @@ nav {
max-height: 85%;
margin-top: 0;
padding-bottom: 10px;
- background-color: rgba(255, 255, 255, .97);
- box-shadow: 0 1px 10px rgba(150, 150, 150, .75);
+ background-color: $color-main-background;
+ box-shadow: 0 1px 10px $color-box-shadow;
border-radius: 3px;
border-top-left-radius: 0;
border-top-right-radius: 0;
@@ -275,7 +274,7 @@ nav {
padding-left: 0;
width: 80px;
text-align: center;
- color: #000;
+ color: $color-main-text;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
@@ -358,7 +357,7 @@ nav {
#settings {
display: inline-block;
- color: #ddd;
+ color: rgba($color-primary-text, 0.7);
cursor: pointer;
.icon-loading-small-dark {
display: inline-block;
@@ -386,7 +385,7 @@ nav {
&:hover,
&:focus,
&:active {
- color: #fff;
+ color: $color-primary-text;
img {
-ms-filter: 'progid:DXImageTransform.Microsoft.Alpha(Opacity=100)';
opacity: 1;
@@ -418,8 +417,8 @@ nav {
top: 45px;
z-index: 2000;
display: none;
- background: rgb(255, 255, 255);
- box-shadow: 0 1px 10px rgba(150, 150, 150, .75);
+ background: $color-main-background;
+ box-shadow: 0 1px 10px $color-box-shadow;
border-radius: 3px;
border-top-left-radius: 0;
border-top-right-radius: 0;
@@ -431,10 +430,10 @@ nav {
a {
display: block;
height: 40px;
- color: #000;
+ color: $color-main-text;
+ opacity: .5;
padding: 10px 12px 0;
-ms-filter: 'progid:DXImageTransform.Microsoft.Alpha(Opacity=50)';
- opacity: .5;
box-sizing: border-box;
img {
margin-bottom: -3px;
diff --git a/core/css/icons.scss b/core/css/icons.scss
index f4ae0ce8d5f..42224a9cfc4 100644
--- a/core/css/icons.scss
+++ b/core/css/icons.scss
@@ -42,15 +42,15 @@
-webkit-transform-origin: center;
-ms-transform-origin: center;
transform-origin: center;
- border: 2px solid rgba(150, 150, 150, 0.5);
- border-top-color: rgb(100, 100, 100);
+ border: 2px solid rgba($color-loading, 0.5);
+ border-top-color: $color-loading;
}
}
.icon-loading-dark:after,
.icon-loading-small-dark:after {
- border: 2px solid rgba(187, 187, 187, 0.5);
- border-top-color: #bbb;
+ border: 2px solid rgba($color-loading-dark, 0.5);
+ border-top-color: $color-loading-dark;
}
.icon-loading-small:after,
diff --git a/core/css/inputs.scss b/core/css/inputs.scss
index faddcc50214..37405172d3a 100644
--- a/core/css/inputs.scss
+++ b/core/css/inputs.scss
@@ -39,9 +39,9 @@ textarea,
margin: 3px 3px 3px 0;
padding: 7px 6px;
font-size: 13px;
- background-color: #fff;
- color: #333;
- border: 1px solid #ddd;
+ background-color: $color-main-background;
+ color: nc-lighten($color-main-text, 33%);
+ border: 1px solid nc-lighten($color-main-text, 86%);
outline: none;
border-radius: 3px;
&:not(:disabled):not(.primary) {
@@ -50,38 +50,38 @@ textarea,
&:focus,
&.active {
/* active class used for multiselect */
- border-color: #0082c9;
+ border-color: $color-primary;
outline: none;
}
&:active {
outline: none;
- background-color: #fff;
+ background-color: $color-main-background;
}
}
&:disabled {
- background-color: #eee;
- color: #999;
+ background-color: nc-darken($color-main-background, 8%);
+ color: rgba($color-main-text, 0.4);
cursor: default;
opacity: 0.5;
}
/* Primary action button, use sparingly */
&.primary {
- border: 1px solid #0082c9;
- background-color: #00a2e9;
- color: #fff;
+ border: 1px solid $color-primary;
+ background-color: rgba($color-primary, .7);
+ color: $color-primary-text;
cursor: pointer;
&:not(:disabled) {
&:hover,
&:focus {
- background-color: #0092d9;
+ background-color: rgba($color-primary, .85);
}
&:active {
- background-color: #00a2e9;
+ background-color: rgba($color-primary, .7);
}
}
&:disabled {
- background-color: #00a2e9;
- color: #bbb;
+ background-color: rgba($color-primary, .7);
+ color: nc-lighten($color-main-text, 73%);
}
}
}
@@ -128,7 +128,7 @@ input[type='reset'] {
min-height: 34px;
cursor: pointer;
box-sizing: border-box;
- background-color: #fafafa;
+ background-color: nc-darken($color-main-background, 3%);
}
/* Buttons */
@@ -155,7 +155,7 @@ button, .button {
}
textarea {
- color: #555;
+ color: nc-lighten($color-main-text, 33%);
cursor: text;
font-family: inherit;
height: auto;
@@ -163,8 +163,8 @@ textarea {
&:active,
&:hover,
&:focus {
- border-color: #ddd !important;
- background-color: #fff !important;
+ border-color: nc-lighten($color-main-text, 86%) !important;
+ background-color: $color-main-background !important;
}
}
}
@@ -186,7 +186,7 @@ button img,
cursor: pointer;
}
#quota {
- color: #555;
+ color: nc-lighten($color-main-text, 33%);
}
select,
.button.multiselect {
@@ -221,27 +221,26 @@ input {
border-radius: 50%;
margin: 3px;
margin-top: 1px;
- border: 1px solid #888;
+ border: 1px solid nc-lighten($color-main-text, 53%);
}
&:not(:disabled):not(:checked) + label:hover:before,
&:focus + label:before {
- border-color: #0082c9;
+ border-color: $color-primary;
}
&:checked + label:before,
&.checkbox:indeterminate + label:before {
/* ^ :indeterminate have a strange behavior on radio,
so we respecified the checkbox class again to be safe */
- box-shadow: inset 0px 0px 0px 2px #fff;
- background-color: #0082c9;
- border-color: #0082c9
+ box-shadow: inset 0px 0px 0px 2px $color-main-background;
+ background-color: $color-primary;
+ border-color: $color-primary
}
&:disabled + label:before {
- background-color: #ccc !important; /* override other status */
+ border: 1px solid nc-lighten($color-main-text, 53%);
+ background-color: nc-lighten($color-main-text, 73%) !important; /* override other status */
}
&:checked:disabled + label:before {
- box-shadow: inset 0px 0px 0px 2px #fff;
- border-color: #aaa;
- background-color: #bbb;
+ background-color: nc-lighten($color-main-text, 73%);
}
}
&.checkbox {
@@ -258,49 +257,46 @@ input {
&:indeterminate + label:before {
background-image: url('../img/actions/checkbox-mixed.svg');
}
- &:indeterminate:disabled + label:before {
- border-color: #888;
- }
}
&.radio--white,
&.checkbox--white {
+ label:before {
- border-color: #ddd;
+ border-color: nc-lighten($color-main-text, 86%);
}
&:not(:disabled):not(:checked) + label:hover:before,
&:focus + label:before {
- border-color: #fff;
+ border-color: $color-main-background;
}
&:checked + label:before {
- box-shadow: inset 0px 0px 0px 2px #000;
- background-color: #eee;
- border-color: #eee
+ box-shadow: inset 0px 0px 0px 2px $color-main-text;
+ background-color: nc-darken($color-main-background, 8%);
+ border-color: nc-darken($color-main-background, 8%)
}
&:disabled + label:before {
- background-color: #666 !important; /* override other status */
- border-color: #999 !important; /* override other status */
+ background-color: nc-lighten($color-main-text, 33%) !important; /* override other status */
+ border-color: rgba($color-main-text, 0.4) !important; /* override other status */
}
&:checked:disabled + label:before {
- box-shadow: inset 0px 0px 0px 2px #000;
- border-color: #666;
- background-color: #222;
+ box-shadow: inset 0px 0px 0px 2px $color-main-text;
+ border-color: nc-lighten($color-main-text, 33%);
+ background-color: nc-lighten($color-main-text, 33%);
}
}
&.checkbox--white {
&:checked + label:before,
&:indeterminate + label:before {
background-color: transparent !important; /* Override default checked */
- border-color: #fff !important; /* Override default checked */
+ border-color: $color-main-background !important; /* Override default checked */
background-image: url('../img/actions/checkbox-mark-white.svg');
}
&:indeterminate + label:before {
background-image: url('../img/actions/checkbox-mixed-white.svg');
}
&:checked:disabled + label:after {
- border-color: #aaa;
+ border-color: nc-lighten($color-main-text, 73%);
}
&:indeterminate:disabled + label:after {
- background-color: #aaa;
+ background-color: nc-lighten($color-main-text, 73%);
}
}
}
@@ -310,7 +306,7 @@ input {
.select2-drop {
margin-top: -2px;
&.select2-drop-active {
- border-color: #ddd;
+ border-color: nc-lighten($color-main-text, 86%);
}
.avatar {
display: inline-block;
@@ -343,17 +339,17 @@ input {
position: relative;
display: list-item;
padding: 12px;
- background-color: #fff;
+ background-color: $color-main-background;
cursor: pointer;
- color: #222;
+ color: nc-lighten($color-main-text, 33%);
}
.select2-result {
&.select2-selected {
- background-color: #f8f8f8;
+ background-color: nc-darken($color-main-background, 3%);
}
&.select2-highlighted {
- background-color: #f8f8f8;
- color: #000;
+ background-color: nc-darken($color-main-background, 3%);
+ color: $color-main-text;
}
}
}
@@ -371,11 +367,11 @@ input {
box-shadow: none;
white-space: nowrap;
text-overflow: ellipsis;
- background: #fff;
- color: #555;
+ background: $color-main-background;
+ color: nc-lighten($color-main-text, 33%);
box-sizing: content-box;
border-radius: 3px;
- border: 1px solid #ddd;
+ border: 1px solid nc-lighten($color-main-text, 86%);
margin: 0;
padding: 2px 0;
min-height: auto;
@@ -387,9 +383,9 @@ input {
&:active,
& {
background-image: none;
- background-color: #fff;
- color: #333;
- border: 1px solid #ddd;
+ background-color: $color-main-background;
+ color: nc-lighten($color-main-text, 33%);
+ border: 1px solid nc-lighten($color-main-text, 86%);
}
.select2-search-choice-close {
display: none;
@@ -413,11 +409,11 @@ input {
box-shadow: none;
white-space: nowrap;
text-overflow: ellipsis;
- background: #fff;
- color: #555;
+ background: $color-main-background;
+ color: nc-lighten($color-main-text, 33%);
box-sizing: content-box;
border-radius: 3px;
- border: 1px solid #ddd;
+ border: 1px solid nc-lighten($color-main-text, 86%);
margin: 0;
padding: 2px 0;
padding-left: 6px;
@@ -426,15 +422,15 @@ input {
line-height: 20px;
padding-left: 5px;
background-image: none;
- background-color: #f8f8f8;
- border-color: #f8f8f8;
+ background-color: nc-darken($color-main-background, 3%);
+ border-color: nc-darken($color-main-background, 3%);
.select2-search-choice-close {
display: none;
}
&.select2-search-choice-focus,
&:hover {
- background-color: #f0f0f0;
- border-color: #f0f0f0;
+ background-color: nc-darken($color-main-background, 8%);
+ border-color: nc-darken($color-main-background, 8%);
}
}
.select2-arrow {
@@ -470,7 +466,7 @@ input {
}
.ui-widget-content {
- background: #fff;
+ background: $color-main-background;
border-top: none;
}
@@ -482,7 +478,7 @@ input {
.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus {
border: none;
- background: #f8f8f8;
+ background: nc-darken($color-main-background, 3%);
}
/* Animation */
diff --git a/core/css/multiselect.scss b/core/css/multiselect.scss
index 4b5d9cb6cf3..cf13563e772 100644
--- a/core/css/multiselect.scss
+++ b/core/css/multiselect.scss
@@ -17,27 +17,27 @@
*/
ul.multiselectoptions {
- background-color: #fff;
- border: 1px solid #ddd;
+ background-color: $color-main-background;
+ border: 1px solid $color-primary;
border-top: none;
- box-shadow: 0 1px 1px #ddd;
+ box-shadow: 0 1px 10px $color-box-shadow;
padding-top: 8px;
position: absolute;
max-height: 20em;
overflow-y: auto;
z-index: 49;
&.down {
- border-bottom-left-radius: 8px;
- border-bottom-right-radius: 8px;
+ border-bottom-left-radius: 3px;
+ border-bottom-right-radius: 3px;
width: 100%;
/* do not cut off group names */
- -webkit-box-shadow: 0px 0px 20px rgba(29, 45, 68, 0.4);
- -moz-box-shadow: 0px 0px 20px rgba(29, 45, 68, 0.4);
- box-shadow: 0px 0px 20px rgba(29, 45, 68, 0.4);
+ -webkit-box-shadow: 0 1px 10px $color-box-shadow;
+ -moz-box-shadow: 0 1px 10px $color-box-shadow;
+ box-shadow: 0 1px 10px $color-box-shadow;
}
&.up {
- border-top-left-radius: 8px;
- border-top-right-radius: 8px;
+ border-top-left-radius: 3px;
+ border-top-right-radius: 3px;
}
> li {
overflow: hidden;
@@ -96,7 +96,7 @@ select.multiselect {
/* To make a select look like a multiselect until it's initialized */
div.multiselect {
&.active {
- background-color: #fff;
+ background-color: $color-main-background;
position: relative;
z-index: 50;
}
diff --git a/core/css/share.scss b/core/css/share.scss
index 6d98dc74945..0e6eb3ccf8b 100644
--- a/core/css/share.scss
+++ b/core/css/share.scss
@@ -56,9 +56,9 @@
margin-right: 0;
}
.error {
- color: #e9322d;
- border-color: #e9322d;
- box-shadow: 0 0 6px #f8b9b7;
+ color: $color-error;
+ border-color: $color-error;
+ box-shadow: 0 0 6px rgba($color-error, 0.35);
}
.mailView .icon-mail {
opacity: 0.5;
@@ -144,7 +144,7 @@ a {
}
#link {
- border-top: 1px solid #ddd;
+ border-top: 1px solid nc-lighten($color-main-text, 86%);
padding-top: 8px;
#showPassword img {
padding-left: 5px;
@@ -182,5 +182,5 @@ a {
.notCreatable {
padding-left: 12px;
padding-top: 12px;
- color: #999;
+ color: rgba($color-main-text, .4);
}
diff --git a/core/css/styles.scss b/core/css/styles.scss
index aa97c91a55d..2bec3c8d3b1 100644
--- a/core/css/styles.scss
+++ b/core/css/styles.scss
@@ -54,7 +54,7 @@ table, td, th {
a {
border: 0;
- color: #000;
+ color: $color-main-text;
text-decoration: none;
cursor: pointer;
* {
@@ -78,18 +78,18 @@ ul {
}
body {
- background-color: #ffffff;
+ background-color: $color-main-background;
font-weight: 400;
font-size: .8em;
line-height: 1.6em;
font-family: 'Open Sans', Frutiger, Calibri, 'Myriad Pro', Myriad, sans-serif;
- color: #000;
+ color: $color-main-text;
height: auto;
}
#body-login {
text-align: center;
- background-color: #0082c9;
+ background-color: $color-primary;
background-image: url('../img/background.jpg?v=1');
background-position: 50% 50%;
background-repeat: no-repeat;
@@ -105,14 +105,14 @@ body {
width: 258px !important;
display: inline-block;
margin-bottom: 0 !important;
- background-color: rgba(0, 0, 0, 0.3) !important;
+ background-color: rgba($color-main-text, 0.3) !important;
border: none !important;
}
.two-factor-link {
display: inline-block;
padding: 12px;
- color: rgba(255, 255, 255, 0.75);
+ color: rgba($color-main-background, 0.75);
}
.float-spinner {
@@ -133,8 +133,8 @@ body {
width: 100%;
z-index: 9000;
text-align: center;
- background-color: rgba(0, 0, 0, 0.5);
- color: #fff;
+ background-color: rgba($color-main-text, 0.5);
+ color: $color-primary-text;
line-height: 125%;
font-size: 24px;
div {
@@ -145,10 +145,10 @@ body {
margin: 0px auto;
}
a {
- color: #fff;
- border-bottom: 2px dotted #fff;
+ color: $color-primary-text;
+ border-bottom: 2px dotted $color-main-background;
&:hover, &:focus {
- color: #ddd;
+ color: nc-lighten($color-main-text, 86%);
}
}
}
@@ -164,7 +164,7 @@ body {
}
::-webkit-scrollbar-thumb {
- background: #ddd;
+ background: nc-lighten($color-main-text, 86%);
border-radius: 3px;
}
@@ -178,7 +178,7 @@ body {
padding: 3px;
padding-left: 25px;
background: transparent url('../img/actions/search-white.svg?v=1') no-repeat 6px center;
- color: #fff;
+ color: $color-primary-text;
border: 0;
border-radius: 3px;
margin-top: 3px;
@@ -189,11 +189,11 @@ body {
-ms-filter: 'progid:DXImageTransform.Microsoft.Alpha(Opacity=70)';
opacity: .7;
&:focus, &:active, &:valid {
- color: #fff;
+ color: $color-primary-text;
width: 155px;
cursor: text;
- background-color: #0082c9 !important;
- border: 1px solid rgba(255, 255, 255, 0.5) !important;
+ background-color: $color-primary !important;
+ border: 1px solid rgba($color-primary-text, 0.5) !important;
}
& ~ .icon-close-white {
display: inline;
@@ -228,7 +228,7 @@ body {
width: 100%;
padding: 0;
margin: 0;
- background-color: rgba(255, 255, 255, 0.95);
+ background-color: rgba($color-main-background, 0.95);
z-index: 50;
-webkit-user-select: none;
-moz-user-select: none;
@@ -298,7 +298,7 @@ body {
}
#emptycontent, .emptycontent {
- color: #888;
+ color: nc-darken($color-main-background, 8%);
text-align: center;
margin-top: 30vh;
width: 100%;
@@ -336,16 +336,16 @@ body {
/* fix sticky footer */
p.info, form fieldset legend, #datadirContent label {
text-align: center;
- color: #fff;
+ color: $color-primary-text;
}
form {
fieldset .warning-info, input[type='checkbox'] + label {
text-align: center;
- color: #fff;
+ color: $color-primary-text;
}
.warning input[type='checkbox'] {
&:hover + label, &:focus + label, + label {
- color: #fff !important;
+ color: $color-primary-text !important;
}
}
}
@@ -354,8 +354,8 @@ body {
margin: 0 0 20px;
}
a {
- color: #fff;
- border-bottom: 1px solid #aaa;
+ color: $color-primary-text;
+ border-bottom: 1px solid nc-lighten($color-main-text, 73%);
}
}
.infogroup {
@@ -442,10 +442,6 @@ body {
top: -23px;
width: 250px;
}
- .tipsy-inner {
- font-weight: bold;
- color: #ccc;
- }
input {
&[type='text'], &[type='password'], &[type='email'] {
border: none;
@@ -456,8 +452,6 @@ body {
/* strengthify wrapper */
-/* tipsy for the strengthify wrapper looks better with following font settings */
-
/* General new input field look */
/* Nicely grouping input field sets */
@@ -483,7 +477,7 @@ body {
border-top: 0 !important;
border-bottom: 0 !important;
border-radius: 0 !important;
- box-shadow: 0 1px 0 rgba(0, 0, 0, 0.1) inset !important;
+ box-shadow: 0 1px 0 rgba($color-main-text, 0.1) inset !important;
}
#body-login .groupbottom input, .groupbottom input {
@@ -491,7 +485,7 @@ body {
border-top: 0 !important;
border-top-right-radius: 0 !important;
border-top-left-radius: 0 !important;
- box-shadow: 0 1px 0 rgba(0, 0, 0, 0.1) inset !important;
+ box-shadow: 0 1px 0 rgba($color-main-text, 0.1) inset !important;
}
#body-login .groupbottom input[type=submit] {
@@ -517,16 +511,16 @@ label.infield {
user-select: none;
}
.errors {
- background: #fed7d7;
- border: 1px solid #f00;
+ background: rgba($color-error, .35);
+ border: 1px solid $color-error;
list-style-indent: inside;
margin: 0 0 2em;
padding: 1em;
}
}
.success {
- background: #d7fed7;
- border: 1px solid #0f0;
+ background: rgba($color-success, .35);
+ border: 1px solid $color-success;
width: 35%;
margin: 30px auto;
padding: 1em;
@@ -537,7 +531,7 @@ label.infield {
box-sizing: border-box;
}
p.info a, #showAdvanced {
- color: #fff;
+ color: $color-primary-text;
}
#remember_login {
&:hover + label, &:focus + label {
@@ -626,25 +620,25 @@ label.infield {
position: static;
margin: 0 -3px 5px;
font-size: 12px;
- background: #f8f8f8;
- color: #888;
+ background: nc-darken($color-main-background, 3%);
+ color: nc-lighten($color-main-text, 53%);
cursor: pointer;
- border: 1px solid #ddd;
+ border: 1px solid nc-lighten($color-main-text, 86%);
span {
cursor: pointer;
padding: 10px 20px;
}
&.ui-state-hover, &.ui-state-active {
- color: #000;
- background-color: #e8e8e8;
+ color: $color-main-text;
+ background-color: nc-darken($color-main-background, 8%);
}
}
}
.warning, .update, .error {
display: block;
padding: 10px;
- background-color: rgba(0, 0, 0, 0.3);
- color: #fff;
+ background-color: rgba($color-main-text, 0.3);
+ color: $color-primary-text;
text-align: left;
border-radius: 3px;
cursor: default;
@@ -672,23 +666,23 @@ label.infield {
#body-user .warning, #body-settings .warning {
margin-top: 8px;
padding: 5px;
- background: #fdd;
+ background: rgba($color-error, .15);
border-radius: 3px;
}
.warning {
legend, a {
- color: #fff !important;
+ color: $color-primary-text !important;
font-weight: 600 !important;
}
}
.error {
a {
- color: #fff !important;
+ color: $color-primary-text !important;
font-weight: 600 !important;
&.button {
- color: #555 !important;
+ color: nc-lighten($color-main-text, 33%) !important;
display: inline-block;
text-align: center;
}
@@ -708,7 +702,7 @@ label.infield {
}
.warning-input {
- border-color: #ce3702 !important;
+ border-color: $color-error !important;
}
/* Fixes for log in page, TODO should be removed some time */
@@ -782,7 +776,7 @@ label.infield {
#forgot-password {
padding: 11px;
float: right;
- color: #fff;
+ color: $color-primary-text;
}
.wrapper {
min-height: 100%;
@@ -822,7 +816,7 @@ td.avatar {
margin: 0 auto;
max-width: 60%;
z-index: 8000;
- background-color: #fff;
+ background-color: $color-main-background;
border: 0;
padding: 1px 8px;
display: none;
@@ -905,7 +899,7 @@ tr {
tbody tr {
&:hover, &:focus, &:active {
- background-color: #f8f8f8;
+ background-color: nc-darken($color-main-background, 3%);
}
}
@@ -920,7 +914,7 @@ code {
padding: 0 !important;
div {
padding: 0;
- background-color: rgb(220, 220, 220);
+ background-color: nc-darken($color-main-background, 10%);
font-weight: normal;
white-space: nowrap;
border-bottom-left-radius: 3px;
@@ -935,7 +929,7 @@ code {
}
#quota div.quota-warning {
- background-color: #fc4;
+ background-color: $color-warning;
}
.pager {
@@ -953,35 +947,6 @@ code {
text-overflow: ellipsis;
}
-.separator {
- display: inline;
- border-left: 1px solid #d3d3d3;
- border-right: 1px solid #fff;
- height: 10px;
- width: 0px;
- margin: 4px;
-}
-
-a.bookmarklet {
- background-color: #ddd;
- border: 1px solid #ccc;
- padding: 5px;
- padding-top: 0px;
- padding-bottom: 2px;
- text-decoration: none;
- margin-top: 5px;
-}
-
-.exception {
- color: #000;
- textarea {
- width: 95%;
- height: 200px;
- background: #ffe;
- border: 0;
- }
-}
-
.ui-icon-circle-triangle-e {
background-image: url('../img/actions/play-next.svg?v=1');
}
@@ -991,8 +956,8 @@ a.bookmarklet {
}
.ui-datepicker-prev, .ui-datepicker-next {
- border: 1px solid #ddd;
- background: #fff;
+ border: nc-lighten($color-main-text, 86%);
+ background: $color-main-background;
}
/* ---- DIALOGS ---- */
@@ -1030,7 +995,7 @@ a.bookmarklet {
width: 100%;
}
.emptycontent {
- color: #888;
+ color: nc-lighten($color-main-text, 53%);
text-align: center;
margin-top: 80px;
width: 100%;
@@ -1048,7 +1013,7 @@ a.bookmarklet {
.filelist {
td {
padding: 14px;
- border-bottom: 1px solid #eee;
+ border-bottom: 1px solid nc-darken($color-main-background, 8%);
}
tr:last-child td {
border-bottom: none;
@@ -1096,12 +1061,6 @@ span.ui-icon {
padding-right: 5px !important;
}
-.tipsy-inner {
- max-width: 400px !important;
- overflow: hidden;
- text-overflow: ellipsis;
-}
-
/* ---- TAGS ---- */
#tagsdialog {
@@ -1111,7 +1070,7 @@ span.ui-icon {
}
.scrollarea {
overflow: auto;
- border: 1px solid #ddd;
+ border: 1px solid nc-lighten($color-main-text, 86%);
width: 100%;
height: 240px;
}
@@ -1123,7 +1082,7 @@ span.ui-icon {
}
}
.taglist li {
- background: #f8f8f8;
+ background: nc-darken($color-main-background, 3%);
padding: .3em .8em;
white-space: nowrap;
overflow: hidden;
@@ -1131,7 +1090,7 @@ span.ui-icon {
-webkit-transition: background-color 500ms;
transition: background-color 500ms;
&:hover, &:active {
- background: #eee;
+ background: nc-darken($color-main-background, 8%);
}
}
.addinput {
@@ -1143,10 +1102,10 @@ span.ui-icon {
/* ---- APP SETTINGS - LEGACY, DO NOT USE THE POPUP! ---- */
.popup {
- background-color: #fff;
+ background-color: $color-main-background;
border-radius: 3px;
- box-shadow: 0 0 10px #aaa;
- color: #333;
+ box-shadow: 0 0 10px $color-box-shadow;
+ color: nc-lighten($color-main-text, 20%);
padding: 10px;
position: fixed !important;
z-index: 100;
@@ -1215,7 +1174,7 @@ div.crumb {
position: relative;
top: 12px;
padding: 14px 24px 14px 17px;
- color: #555;
+ color: nc-lighten($color-main-text, 33%);
}
&.last a {
padding-right: 0;
@@ -1263,12 +1222,12 @@ div.crumb {
position: relative;
text-align: center;
.info {
- color: #777;
+ color: nc-lighten($color-main-text, 33%);
text-align: center;
margin: 0 auto;
padding: 20px 0;
a {
- color: #777;
+ color: nc-lighten($color-main-text, 33%);
font-weight: 600;
padding: 13px;
margin: -13px;
diff --git a/core/css/tooltip.scss b/core/css/tooltip.scss
index 263dad0b0c9..66234cad9f2 100644
--- a/core/css/tooltip.scss
+++ b/core/css/tooltip.scss
@@ -54,7 +54,7 @@
left: 0;
margin-top: -5px;
border-width: 5px 5px 5px 0;
- border-right-color: #000000;
+ border-right-color: $color-main-text;
}
}
&.left {
@@ -65,7 +65,7 @@
right: 0;
margin-top: -5px;
border-width: 5px 0 5px 5px;
- border-left-color: #000000;
+ border-left-color: $color-main-text;
}
}
@@ -75,7 +75,7 @@
&.top-right .tooltip-arrow {
bottom: 0;
border-width: 5px 5px 0;
- border-top-color: #000000;
+ border-top-color: $color-main-text;
}
&.top .tooltip-arrow {
left: 50%;
@@ -96,7 +96,7 @@
&.bottom-right .tooltip-arrow {
top: 0;
border-width: 0 5px 5px;
- border-bottom-color: #000000;
+ border-bottom-color: $color-main-text;
}
&.bottom .tooltip-arrow {
left: 50%;
@@ -115,9 +115,9 @@
.tooltip-inner {
max-width: 350px;
padding: 3px 8px;
- color: #ffffff;
+ color: $color-main-background;
text-align: center;
- background-color: #000000;
+ background-color: $color-main-text;
border-radius: 4px;
}
diff --git a/core/css/variables.scss b/core/css/variables.scss
new file mode 100644
index 00000000000..47c8e1a27f8
--- /dev/null
+++ b/core/css/variables.scss
@@ -0,0 +1,22 @@
+$color-main-text: #000000;
+$color-main-background: #ffffff;
+$color-primary: #0082c9;
+$color-primary-text: #ffffff;
+$color-error: #e9322d;
+$color-warning: #ffcc44;
+$color-success: #46ba61;
+
+@function nc-darken($color, $value) {
+ @return darken($color, $value);
+}
+
+@function nc-lighten($color, $value) {
+ @return lighten($color, $value);
+}
+
+$image-logo: '../img/logo-icon.svg?v=1';
+$image-login-background: '../img/background.jpg?v=1';
+
+$color-loading: #969696;
+$color-loading-dark: #bbbbbb;
+$color-box-shadow: rgba(nc-lighten($color-main-text, 20%), 0.75); \ No newline at end of file
diff --git a/lib/private/Template/SCSSCacher.php b/lib/private/Template/SCSSCacher.php
index b55cd0b93b0..4f5c66f2409 100644
--- a/lib/private/Template/SCSSCacher.php
+++ b/lib/private/Template/SCSSCacher.php
@@ -28,7 +28,9 @@ use Leafo\ScssPhp\Formatter\Expanded;
use OC\SystemConfig;
use OCP\Files\IAppData;
use OCP\Files\NotFoundException;
+use OCP\Files\NotPermittedException;
use OCP\Files\SimpleFS\ISimpleFolder;
+use OCP\IConfig;
use OCP\ILogger;
use OCP\IURLGenerator;
@@ -43,8 +45,8 @@ class SCSSCacher {
/** @var IURLGenerator */
protected $urlGenerator;
- /** @var SystemConfig */
- protected $systemConfig;
+ /** @var IConfig */
+ protected $config;
/** @var string */
protected $serverRoot;
@@ -59,12 +61,12 @@ class SCSSCacher {
public function __construct(ILogger $logger,
IAppData $appData,
IURLGenerator $urlGenerator,
- SystemConfig $systemConfig,
+ IConfig $config,
$serverRoot) {
$this->logger = $logger;
$this->appData = $appData;
$this->urlGenerator = $urlGenerator;
- $this->systemConfig = $systemConfig;
+ $this->config = $config;
$this->serverRoot = $serverRoot;
}
@@ -94,9 +96,8 @@ class SCSSCacher {
if($this->isCached($fileNameCSS, $fileNameSCSS, $folder, $path)) {
return true;
- } else {
- return $this->cache($path, $fileNameCSS, $fileNameSCSS, $folder, $webDir);
}
+ return $this->cache($path, $fileNameCSS, $fileNameSCSS, $folder, $webDir);
}
/**
@@ -108,7 +109,7 @@ class SCSSCacher {
* @return boolean
*/
private function isCached($fileNameCSS, $fileNameSCSS, ISimpleFolder $folder, $path) {
- try{
+ try {
$cachedFile = $folder->getFile($fileNameCSS);
if ($cachedFile->getSize() > 0) {
$depFile = $folder->getFile($fileNameCSS . '.deps');
@@ -124,7 +125,6 @@ class SCSSCacher {
} catch(NotFoundException $e) {
return false;
}
- return false;
}
/**
@@ -138,8 +138,11 @@ class SCSSCacher {
*/
private function cache($path, $fileNameCSS, $fileNameSCSS, ISimpleFolder $folder, $webDir) {
$scss = new Compiler();
- $scss->setImportPaths($path);
- if($this->systemConfig->getValue('debug')) {
+ $scss->setImportPaths([
+ $path,
+ \OC::$SERVERROOT . '/core/css/',
+ ]);
+ if($this->config->getSystemValue('debug')) {
// Debug mode
$scss->setFormatter(Expanded::class);
$scss->setLineNumberStyle(Compiler::LINE_COMMENTS);
@@ -163,7 +166,9 @@ class SCSSCacher {
// Compile
try {
- $compiledScss = $scss->compile('@import "'.$fileNameSCSS.'";');
+ $compiledScss = $scss->compile(
+ '@import "variables.scss";' .
+ '@import "'.$fileNameSCSS.'";');
} catch(ParserException $e) {
$this->logger->error($e, ['app' => 'core']);
return false;
@@ -174,7 +179,7 @@ class SCSSCacher {
$depFile->putContent(json_encode($scss->getParsedFiles()));
$this->logger->debug($webDir.'/'.$fileNameSCSS.' compiled and successfully cached', ['app' => 'core']);
return true;
- } catch(NotFoundException $e) {
+ } catch(NotPermittedException $e) {
return false;
}
}
@@ -188,7 +193,7 @@ class SCSSCacher {
private function rebaseUrls($css, $webDir) {
$re = '/url\([\'"]([\.\w?=\/-]*)[\'"]\)/x';
// OC\Route\Router:75
- if(($this->systemConfig->getValue('htaccess.IgnoreFrontController', false) === true || getenv('front_controller_active') === 'true')) {
+ if(($this->config->getSystemValue('htaccess.IgnoreFrontController', false) === true || getenv('front_controller_active') === 'true')) {
$subst = 'url(\'../../'.$webDir.'/$1\')';
} else {
$subst = 'url(\'../../../'.$webDir.'/$1\')';
diff --git a/lib/private/TemplateLayout.php b/lib/private/TemplateLayout.php
index 6d2c3b2674f..a9bfaf9a7c7 100644
--- a/lib/private/TemplateLayout.php
+++ b/lib/private/TemplateLayout.php
@@ -218,7 +218,7 @@ class TemplateLayout extends \OC_Template {
\OC::$server->getLogger(),
\OC::$server->getAppDataDir('css'),
\OC::$server->getURLGenerator(),
- \OC::$server->getSystemConfig(),
+ \OC::$server->getConfig(),
\OC::$SERVERROOT
);
} else {
diff --git a/tests/data/scss/styles-error.scss b/tests/data/scss/styles-error.scss
new file mode 100644
index 00000000000..bd6c6d4ffb5
--- /dev/null
+++ b/tests/data/scss/styles-error.scss
@@ -0,0 +1 @@
+body { error }
diff --git a/tests/data/scss/styles-success.scss b/tests/data/scss/styles-success.scss
new file mode 100644
index 00000000000..bf4efa71a6a
--- /dev/null
+++ b/tests/data/scss/styles-success.scss
@@ -0,0 +1 @@
+body { background-color: $color-primary; } \ No newline at end of file
diff --git a/tests/lib/Template/SCSSCacherTest.php b/tests/lib/Template/SCSSCacherTest.php
new file mode 100644
index 00000000000..d49f0cdc6a1
--- /dev/null
+++ b/tests/lib/Template/SCSSCacherTest.php
@@ -0,0 +1,278 @@
+<?php
+/**
+ * @copyright Copyright (c) 2017 Julius Härtl <jus@bitgrid.net>
+ *
+ * @author Julius Härtl <jus@bitgrid.net>
+ *
+ * @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\Template\SCSSCacher;
+use OCP\Files\IAppData;
+use OCP\Files\NotFoundException;
+use OCP\Files\SimpleFS\ISimpleFile;
+use OCP\Files\SimpleFS\ISimpleFolder;
+use OCP\IConfig;
+use OCP\ILogger;
+use OCP\IURLGenerator;
+
+class SCSSCacherTest extends \Test\TestCase {
+ /** @var ILogger|\PHPUnit_Framework_MockObject_MockObject */
+ protected $logger;
+ /** @var IAppData|\PHPUnit_Framework_MockObject_MockObject */
+ protected $appData;
+ /** @var IURLGenerator|\PHPUnit_Framework_MockObject_MockObject */
+ protected $urlGenerator;
+ /** @var IConfig|\PHPUnit_Framework_MockObject_MockObject */
+ protected $config;
+ /** @var \OC_Defaults|\PHPUnit_Framework_MockObject_MockObject */
+ protected $defaults;
+ /** @var SCSSCacher */
+ protected $scssCacher;
+
+ protected function setUp() {
+ parent::setUp();
+ $this->logger = $this->createMock(ILogger::class);
+ $this->appData = $this->createMock(IAppData::class);
+ $this->urlGenerator = $this->createMock(IURLGenerator::class);
+ $this->config = $this->createMock(IConfig::class);
+ $this->scssCacher = new SCSSCacher(
+ $this->logger,
+ $this->appData,
+ $this->urlGenerator,
+ $this->config,
+ \OC::$SERVERROOT
+ );
+ }
+
+ public function testProcessUncachedFileNoAppDataFolder() {
+ $folder = $this->createMock(ISimpleFolder::class);
+ $this->appData->expects($this->once())->method('getFolder')->with('core')->willThrowException(new NotFoundException());
+ $this->appData->expects($this->once())->method('newFolder')->with('core')->willReturn($folder);
+ $file = $this->createMock(ISimpleFile::class);
+ $file->expects($this->any())->method('getSize')->willReturn(1);
+ $fileDeps = $this->createMock(ISimpleFile::class);
+ $folder->expects($this->at(0))->method('getFile')->with('styles.css')->willReturn($file);
+ $folder->expects($this->at(1))->method('getFile')->with('styles.css.deps')->willThrowException(new NotFoundException());
+ $folder->expects($this->at(2))->method('getFile')->with('styles.css')->willReturn($file);
+ $folder->expects($this->at(3))->method('getFile')->with('styles.css.deps')->willThrowException(new NotFoundException());
+ $folder->expects($this->at(4))->method('newFile')->with('styles.css.deps')->willReturn($fileDeps);
+ $actual = $this->scssCacher->process(\OC::$SERVERROOT, '/core/css/styles.scss', 'core');
+ $this->assertTrue($actual);
+ }
+
+ public function testProcessUncachedFile() {
+ $folder = $this->createMock(ISimpleFolder::class);
+ $this->appData->expects($this->once())->method('getFolder')->with('core')->willReturn($folder);
+ $file = $this->createMock(ISimpleFile::class);
+ $file->expects($this->any())->method('getSize')->willReturn(1);
+ $fileDeps = $this->createMock(ISimpleFile::class);
+ $folder->expects($this->at(0))->method('getFile')->with('styles.css')->willReturn($file);
+ $folder->expects($this->at(1))->method('getFile')->with('styles.css.deps')->willThrowException(new NotFoundException());
+ $folder->expects($this->at(2))->method('getFile')->with('styles.css')->willReturn($file);
+ $folder->expects($this->at(3))->method('getFile')->with('styles.css.deps')->willThrowException(new NotFoundException());
+ $folder->expects($this->at(4))->method('newFile')->with('styles.css.deps')->willReturn($fileDeps);
+ $actual = $this->scssCacher->process(\OC::$SERVERROOT, '/core/css/styles.scss', 'core');
+ $this->assertTrue($actual);
+ }
+
+ public function testProcessCacheFile() {
+ $folder = $this->createMock(ISimpleFolder::class);
+ $this->appData->expects($this->once())->method('getFolder')->with('core')->willReturn($folder);
+ $file = $this->createMock(ISimpleFile::class);
+ $file->expects($this->any())->method('getSize')->willReturn(1);
+ $fileDeps = $this->createMock(ISimpleFile::class);
+ $fileDeps->expects($this->any())->method('getSize')->willReturn(1);
+ $fileDeps->expects($this->once())->method('getContent')->willReturn('{}');
+ $folder->expects($this->at(0))->method('getFile')->with('styles.css')->willReturn($file);
+ $folder->expects($this->at(1))->method('getFile')->with('styles.css.deps')->willReturn($fileDeps);
+ $actual = $this->scssCacher->process(\OC::$SERVERROOT, '/core/css/styles.scss', 'core');
+ $this->assertTrue($actual);
+ }
+
+ public function testProcessCachedFile() {
+ $folder = $this->createMock(ISimpleFolder::class);
+ $this->appData->expects($this->once())->method('getFolder')->with('core')->willReturn($folder);
+ $file = $this->createMock(ISimpleFile::class);
+ $file->expects($this->once())->method('getSize')->willReturn(1);
+ $fileDeps = $this->createMock(ISimpleFile::class);
+ $fileDeps->expects($this->any())->method('getSize')->willReturn(1);
+ $fileDeps->expects($this->once())->method('getContent')->willReturn('{}');
+ $folder->expects($this->at(0))->method('getFile')->with('styles.css')->willReturn($file);
+ $folder->expects($this->at(1))->method('getFile')->with('styles.css.deps')->willReturn($fileDeps);
+ $actual = $this->scssCacher->process(\OC::$SERVERROOT, '/core/css/styles.scss', 'core');
+ $this->assertTrue($actual);
+ }
+
+ public function testIsCachedNoFile() {
+ $fileNameCSS = "styles.css";
+ $fileNameSCSS = "styles.scss";
+ $folder = $this->createMock(ISimpleFolder::class);
+ $path = \OC::$SERVERROOT . '/core/css/';
+
+ $folder->expects($this->at(0))->method('getFile')->with($fileNameCSS)->willThrowException(new NotFoundException());
+ $actual = self::invokePrivate($this->scssCacher, 'isCached', [$fileNameCSS, $fileNameSCSS, $folder, $path]);
+ $this->assertFalse($actual);
+ }
+
+ public function testIsCachedNoDepsFile() {
+ $fileNameCSS = "styles.css";
+ $fileNameSCSS = "styles.scss";
+ $folder = $this->createMock(ISimpleFolder::class);
+ $file = $this->createMock(ISimpleFile::class);
+ $path = \OC::$SERVERROOT . '/core/css/';
+
+ $file->expects($this->once())->method('getSize')->willReturn(1);
+ $folder->expects($this->at(0))->method('getFile')->with($fileNameCSS)->willReturn($file);
+ $folder->expects($this->at(1))->method('getFile')->with($fileNameCSS . '.deps')->willThrowException(new NotFoundException());
+
+ $actual = self::invokePrivate($this->scssCacher, 'isCached', [$fileNameCSS, $fileNameSCSS, $folder, $path]);
+ $this->assertFalse($actual);
+ }
+ public function testCacheNoFile() {
+ $fileNameCSS = "styles.css";
+ $fileNameSCSS = "styles.scss";
+ $folder = $this->createMock(ISimpleFolder::class);
+ $file = $this->createMock(ISimpleFile::class);
+ $depsFile = $this->createMock(ISimpleFile::class);
+
+ $webDir = "core/css";
+ $path = \OC::$SERVERROOT . '/core/css/';
+
+ $folder->expects($this->at(0))->method('getFile')->with($fileNameCSS)->willThrowException(new NotFoundException());
+ $folder->expects($this->at(1))->method('newFile')->with($fileNameCSS)->willReturn($file);
+ $folder->expects($this->at(2))->method('getFile')->with($fileNameCSS . '.deps')->willThrowException(new NotFoundException());
+ $folder->expects($this->at(3))->method('newFile')->with($fileNameCSS . '.deps')->willReturn($depsFile);
+
+ $file->expects($this->once())->method('putContent');
+ $depsFile->expects($this->once())->method('putContent');
+
+ $actual = self::invokePrivate($this->scssCacher, 'cache', [$path, $fileNameCSS, $fileNameSCSS, $folder, $webDir]);
+ $this->assertTrue($actual);
+ }
+
+ public function testCache() {
+ $fileNameCSS = "styles.css";
+ $fileNameSCSS = "styles.scss";
+ $folder = $this->createMock(ISimpleFolder::class);
+ $file = $this->createMock(ISimpleFile::class);
+ $depsFile = $this->createMock(ISimpleFile::class);
+
+ $webDir = "core/css";
+ $path = \OC::$SERVERROOT;
+
+ $folder->expects($this->at(0))->method('getFile')->with($fileNameCSS)->willReturn($file);
+ $folder->expects($this->at(1))->method('getFile')->with($fileNameCSS . '.deps')->willReturn($depsFile);
+
+ $file->expects($this->once())->method('putContent');
+ $depsFile->expects($this->once())->method('putContent');
+
+ $actual = self::invokePrivate($this->scssCacher, 'cache', [$path, $fileNameCSS, $fileNameSCSS, $folder, $webDir]);
+ $this->assertTrue($actual);
+ }
+
+ public function testCacheSuccess() {
+ $fileNameCSS = "styles-success.css";
+ $fileNameSCSS = "../../tests/data/scss/styles-success.scss";
+ $folder = $this->createMock(ISimpleFolder::class);
+ $file = $this->createMock(ISimpleFile::class);
+ $depsFile = $this->createMock(ISimpleFile::class);
+
+ $webDir = "tests/data/scss";
+ $path = \OC::$SERVERROOT . $webDir;
+
+ $folder->expects($this->at(0))->method('getFile')->with($fileNameCSS)->willReturn($file);
+ $folder->expects($this->at(1))->method('getFile')->with($fileNameCSS . '.deps')->willReturn($depsFile);
+
+ $file->expects($this->at(0))->method('putContent')->with($this->callback(
+ function ($content){
+ return 'body{background-color:#0082c9}' === $content;
+ }));
+ $depsFile->expects($this->at(0))->method('putContent')->with($this->callback(
+ function ($content) {
+ $deps = json_decode($content, true);
+ return array_key_exists(\OC::$SERVERROOT . '/core/css/variables.scss', $deps)
+ && array_key_exists(\OC::$SERVERROOT . '/tests/data/scss/styles-success.scss', $deps);
+ }));
+
+ $actual = self::invokePrivate($this->scssCacher, 'cache', [$path, $fileNameCSS, $fileNameSCSS, $folder, $webDir]);
+ $this->assertTrue($actual);
+ }
+
+ public function testCacheFailure() {
+ $fileNameCSS = "styles-error.css";
+ $fileNameSCSS = "../../tests/data/scss/styles-error.scss";
+ $folder = $this->createMock(ISimpleFolder::class);
+ $file = $this->createMock(ISimpleFile::class);
+ $depsFile = $this->createMock(ISimpleFile::class);
+
+ $webDir = "/tests/data/scss";
+ $path = \OC::$SERVERROOT . $webDir;
+
+ $folder->expects($this->at(0))->method('getFile')->with($fileNameCSS)->willReturn($file);
+ $folder->expects($this->at(1))->method('getFile')->with($fileNameCSS . '.deps')->willReturn($depsFile);
+
+ $actual = self::invokePrivate($this->scssCacher, 'cache', [$path, $fileNameCSS, $fileNameSCSS, $folder, $webDir]);
+ $this->assertFalse($actual);
+ }
+
+ public function testRebaseUrls() {
+ $webDir = 'apps/files/css';
+ $css = '#id { background-image: url(\'../img/image.jpg\'); }';
+ $actual = self::invokePrivate($this->scssCacher, 'rebaseUrls', [$css, $webDir]);
+ $expected = '#id { background-image: url(\'../../../apps/files/css/../img/image.jpg\'); }';
+ $this->assertEquals($expected, $actual);
+ }
+
+ public function testRebaseUrlsIgnoreFrontendController() {
+ $this->config->expects($this->once())->method('getSystemValue')->with('htaccess.IgnoreFrontController', false)->willReturn(true);
+ $webDir = 'apps/files/css';
+ $css = '#id { background-image: url(\'../img/image.jpg\'); }';
+ $actual = self::invokePrivate($this->scssCacher, 'rebaseUrls', [$css, $webDir]);
+ $expected = '#id { background-image: url(\'../../apps/files/css/../img/image.jpg\'); }';
+ $this->assertEquals($expected, $actual);
+ }
+
+ public function dataGetCachedSCSS() {
+ return [
+ ['core', 'core/css/styles.scss', '/css/core/styles.css'],
+ ['files', 'apps/files/css/styles.scss', '/css/files/styles.css']
+ ];
+ }
+
+ /**
+ * @param $appName
+ * @param $fileName
+ * @param $result
+ * @dataProvider dataGetCachedSCSS
+ */
+ public function testGetCachedSCSS($appName, $fileName, $result) {
+ $this->urlGenerator->expects($this->once())
+ ->method('linkToRoute')
+ ->with('core.Css.getCss', [
+ 'fileName' => 'styles.css',
+ 'appName' => $appName
+ ])
+ ->willReturn(\OC::$WEBROOT . $result);
+ $actual = $this->scssCacher->getCachedSCSS($appName, $fileName);
+ $this->assertEquals(substr($result, 1), $actual);
+ }
+
+
+} \ No newline at end of file