Commit 393361e7 by Andy Armstrong Committed by GitHub

Merge pull request #15982 from edx/andya/sass-linting

Lint Sass files using the rules in stylelint-config-edx
parents bdd4f232 8de47f24
...@@ -8,6 +8,7 @@ $bookmarked-icon: "\f02e"; // .fa-bookmark ...@@ -8,6 +8,7 @@ $bookmarked-icon: "\f02e"; // .fa-bookmark
> div { > div {
@include box-sizing(border-box); @include box-sizing(border-box);
display: inline-block; display: inline-block;
} }
} }
...@@ -22,11 +23,13 @@ $bookmarked-icon: "\f02e"; // .fa-bookmark ...@@ -22,11 +23,13 @@ $bookmarked-icon: "\f02e"; // .fa-bookmark
// set styles // set styles
@extend %btn-pl-default-base; @extend %btn-pl-default-base;
@include font-size(13); @include font-size(13);
width: 100%; width: 100%;
padding: ($baseline/4) ($baseline/2); padding: ($baseline/4) ($baseline/2);
&:before { &::before {
content: $bookmarked-icon; content: $bookmarked-icon;
font-family: FontAwesome; font-family: FontAwesome;
} }
...@@ -35,9 +38,9 @@ $bookmarked-icon: "\f02e"; // .fa-bookmark ...@@ -35,9 +38,9 @@ $bookmarked-icon: "\f02e"; // .fa-bookmark
// Rules for bookmark icon shown on each sequence nav item // Rules for bookmark icon shown on each sequence nav item
.course-content { .course-content {
.bookmark-icon.bookmarked { .bookmark-icon.bookmarked {
@include right($baseline / 4); @include right($baseline / 4);
top: -3px; top: -3px;
position: absolute; position: absolute;
} }
...@@ -48,17 +51,15 @@ $bookmarked-icon: "\f02e"; // .fa-bookmark ...@@ -48,17 +51,15 @@ $bookmarked-icon: "\f02e"; // .fa-bookmark
} }
.bookmark-button { .bookmark-button {
&::before {
&:before {
content: $bookmark-icon; content: $bookmark-icon;
font-family: FontAwesome; font-family: FontAwesome;
} }
&.bookmarked { &.bookmarked {
&:before { &::before {
content: $bookmarked-icon; content: $bookmarked-icon;
} }
} }
} }
} }
...@@ -3,85 +3,87 @@ $bookmarked-icon: "\f02e"; // .fa-bookmark ...@@ -3,85 +3,87 @@ $bookmarked-icon: "\f02e"; // .fa-bookmark
// Rules for Bookmarks Results Header // Rules for Bookmarks Results Header
.bookmarks-results-header { .bookmarks-results-header {
letter-spacing: 0; letter-spacing: 0;
text-transform: none; text-transform: none;
margin-bottom: ($baseline/2); margin-bottom: ($baseline/2);
} }
// Rules for Bookmarks Results // Rules for Bookmarks Results
.bookmarks-results-list { .bookmarks-results-list {
padding-top: ($baseline/2); padding-top: ($baseline/2);
.bookmarks-results-list-item { .bookmarks-results-list-item {
@include padding(0, $baseline, ($baseline/4), $baseline); @include padding(0, $baseline, ($baseline/4), $baseline);
display: block;
border: 1px solid $lms-border-color;
margin-bottom: $baseline;
&:hover { display: block;
border-color: palette(primary, base); border: 1px solid $lms-border-color;
margin-bottom: $baseline;
.list-item-breadcrumbtrail {
color: palette(primary, base);
}
}
}
.results-list-item-view {
@include float(right);
margin-top: $baseline;
}
.list-item-date { &:hover {
margin-top: ($baseline/4); border-color: palette(primary, base);
color: $lms-gray;
font-size: font-size(small);
}
.bookmarks-results-list-item:before { .list-item-breadcrumbtrail {
content: $bookmarked-icon;
position: relative;
top: -7px;
font-family: FontAwesome;
color: palette(primary, base); color: palette(primary, base);
}
} }
}
.list-item-content { .results-list-item-view {
overflow: hidden; @include float(right);
}
.list-item-left-section { margin-top: $baseline;
display: inline-block; }
vertical-align: middle;
width: 90%; .list-item-date {
} margin-top: ($baseline/4);
color: $lms-gray;
.list-item-right-section { font-size: font-size(small);
display: inline-block; }
vertical-align: middle;
.bookmarks-results-list-item::before {
.fa-arrow-right { content: $bookmarked-icon;
position: relative;
@include rtl { top: -7px;
@include transform(rotate(180deg)); font-family: FontAwesome;
} color: palette(primary, base);
} }
.list-item-content {
overflow: hidden;
}
.list-item-left-section {
display: inline-block;
vertical-align: middle;
width: 90%;
}
.list-item-right-section {
display: inline-block;
vertical-align: middle;
.fa-arrow-right {
@include rtl {
@include transform(rotate(180deg));
}
} }
}
} }
// Rules for empty bookmarks list // Rules for empty bookmarks list
.bookmarks-empty { .bookmarks-empty {
margin-top: $baseline; margin-top: $baseline;
border: 1px solid $lms-border-color; border: 1px solid $lms-border-color;
padding: $baseline; padding: $baseline;
background-color: $white; background-color: $white;
} }
.bookmarks-empty-header { .bookmarks-empty-header {
@extend %t-title5; @extend %t-title5;
margin-bottom: ($baseline/2);
margin-bottom: ($baseline/2);
} }
.bookmarks-empty-detail { .bookmarks-empty-detail {
@extend %t-copy-sub1; @extend %t-copy-sub1;
} }
...@@ -26,8 +26,10 @@ ...@@ -26,8 +26,10 @@
margin: $baseline 0; margin: $baseline 0;
} }
&:after, &:before { &::after,
&::before {
@include left(0); @include left(0);
bottom: 35%; bottom: 35%;
border: solid transparent; border: solid transparent;
height: 0; height: 0;
...@@ -40,15 +42,17 @@ ...@@ -40,15 +42,17 @@
} }
} }
&:after { &::after {
@include border-right-color($white); @include border-right-color($white);
@include margin-left($baseline*-1+1); @include margin-left($baseline*-1+1);
border-width: $baseline/2; border-width: $baseline/2;
} }
&:before { &::before {
@include margin-left($baseline*-1); @include margin-left($baseline*-1);
@include border-right-color($lms-border-color); @include border-right-color($lms-border-color);
border-width: $baseline/2; border-width: $baseline/2;
} }
...@@ -65,14 +69,19 @@ ...@@ -65,14 +69,19 @@
} }
// Welcome message / Latest Update message // Welcome message / Latest Update message
.welcome-message, .update-message{ .welcome-message,
.update-message {
border: solid 1px $lms-border-color; border: solid 1px $lms-border-color;
@include border-left(solid 4px $black); @include border-left(solid 4px $black);
margin-bottom: $baseline; margin-bottom: $baseline;
padding: $baseline; padding: $baseline;
overflow: hidden; overflow: hidden;
h1, h2, h3 { h1,
h2,
h3 {
font-size: font-size(large); font-size: font-size(large);
font-weight: $font-bold; font-weight: $font-bold;
color: $black; color: $black;
...@@ -80,14 +89,16 @@ ...@@ -80,14 +89,16 @@
img { img {
@include float(left); @include float(left);
margin: $baseline/2; margin: $baseline/2;
max-width: 100%; max-width: 100%;
} }
.dismiss-message { .dismiss-message {
@include float(right); @include float(right);
.btn-link { .btn-link {
color: palette(grayscale, base); color: palette(grayscale, base);
} }
} }
} }
...@@ -123,6 +134,7 @@ ...@@ -123,6 +134,7 @@
.section-name { .section-name {
@include margin(0, 0, ($baseline / 2), ($baseline / 2)); @include margin(0, 0, ($baseline / 2), ($baseline / 2));
padding: 0; padding: 0;
h3 { h3 {
...@@ -140,7 +152,6 @@ ...@@ -140,7 +152,6 @@
padding-bottom: $baseline; padding-bottom: $baseline;
border-bottom: 1px solid $light-grey-solid; border-bottom: 1px solid $light-grey-solid;
margin: 0 0 ($baseline / 2) 0; margin: 0 0 ($baseline / 2) 0;
.subsection { .subsection {
list-style-type: none; list-style-type: none;
...@@ -157,7 +168,8 @@ ...@@ -157,7 +168,8 @@
margin: 0; margin: 0;
} }
&:hover, &:focus { &:hover,
&:focus {
background-color: palette(primary, x-back); background-color: palette(primary, x-back);
border-radius: $btn-border-radius; border-radius: $btn-border-radius;
text-decoration: none; text-decoration: none;
...@@ -205,6 +217,7 @@ ...@@ -205,6 +217,7 @@
.date-summary { .date-summary {
@include clearfix; @include clearfix;
@include border-left(3px solid $gray-l3); @include border-left(3px solid $gray-l3);
padding: $baseline/2; padding: $baseline/2;
.heading { .heading {
...@@ -223,6 +236,7 @@ ...@@ -223,6 +236,7 @@
.date-summary-link { .date-summary-link {
font-weight: $font-semibold; font-weight: $font-semibold;
a { a {
color: $link-color; color: $link-color;
font-weight: $font-regular; font-weight: $font-regular;
...@@ -284,7 +298,7 @@ ...@@ -284,7 +298,7 @@
// Course Reviews Page // Course Reviews Page
.course-reviews { .course-reviews {
.page-header.has-secondary > .page-header-main { .page-header.has-secondary > .page-header-main {
display: block; display: block;
position: relative; position: relative;
......
...@@ -17,12 +17,14 @@ ...@@ -17,12 +17,14 @@
.search-count { .search-count {
@include text-align(right); @include text-align(right);
display: block; display: block;
color: $lms-gray; color: $lms-gray;
} }
.search-results-item { .search-results-item {
@include padding-right(140px); @include padding-right(140px);
position: relative; position: relative;
border-top: 1px solid $border-color; border-top: 1px solid $border-color;
padding: $baseline ($baseline/2); padding: $baseline ($baseline/2);
...@@ -51,6 +53,7 @@ ...@@ -51,6 +53,7 @@
.result-link { .result-link {
@include right($baseline/2); @include right($baseline/2);
position: absolute; position: absolute;
top: $baseline; top: $baseline;
line-height: 1.6em; line-height: 1.6em;
...@@ -58,6 +61,7 @@ ...@@ -58,6 +61,7 @@
.result-type { .result-type {
@include right($baseline/2); @include right($baseline/2);
position: absolute; position: absolute;
color: $lms-gray; color: $lms-gray;
font-size: 14px; font-size: 14px;
......
...@@ -2,7 +2,6 @@ ...@@ -2,7 +2,6 @@
display: inline-block; display: inline-block;
position: relative; position: relative;
width: 100%; width: 100%;
margin-top: $baseline;
max-width: $lms-max-width; max-width: $lms-max-width;
margin: $baseline auto 0; margin: $baseline auto 0;
-webkit-transition: all 0.4s ease-out; -webkit-transition: all 0.4s ease-out;
...@@ -14,6 +13,7 @@ ...@@ -14,6 +13,7 @@
.action-toggle-verification-sock { .action-toggle-verification-sock {
@include left(50%); @include left(50%);
@include margin-left(-1 * $baseline * 15/2); @include margin-left(-1 * $baseline * 15/2);
position: absolute; position: absolute;
top: (-1 * $baseline); top: (-1 * $baseline);
width: ($baseline * 15); width: ($baseline * 15);
...@@ -71,6 +71,7 @@ ...@@ -71,6 +71,7 @@
.mini-cert { .mini-cert {
@include right($baseline); @include right($baseline);
position: absolute; position: absolute;
top: $baseline; top: $baseline;
width: ($baseline * 13); width: ($baseline * 13);
...@@ -96,7 +97,7 @@ ...@@ -96,7 +97,7 @@
width: ($baseline * 5/2); width: ($baseline * 5/2);
} }
.story-quote > .author{ .story-quote > .author {
display: block; display: block;
margin-top: ($baseline / 4); margin-top: ($baseline / 4);
font-weight: 600; font-weight: 600;
...@@ -135,6 +136,7 @@ ...@@ -135,6 +136,7 @@
&.attached { &.attached {
@include right($baseline); @include right($baseline);
position: fixed; position: fixed;
bottom: $baseline; bottom: $baseline;
top: auto; top: auto;
......
...@@ -17,7 +17,7 @@ $upgrade-message-background-color: $blue-d1; ...@@ -17,7 +17,7 @@ $upgrade-message-background-color: $blue-d1;
-webkit-transition: all 0.2s ease-in-out; -webkit-transition: all 0.2s ease-in-out;
transition: all 0.2s ease-in-out; transition: all 0.2s ease-in-out;
&:after { &::after {
content: ""; content: "";
display: table; display: table;
clear: both; clear: both;
...@@ -28,12 +28,14 @@ $upgrade-message-background-color: $blue-d1; ...@@ -28,12 +28,14 @@ $upgrade-message-background-color: $blue-d1;
font-size: 1.25rem; font-size: 1.25rem;
font-weight: 700; font-weight: 700;
margin-bottom: 1rem; margin-bottom: 1rem;
@include float(left); @include float(left);
} }
.vc-selling-points { .vc-selling-points {
@include clear(left); @include clear(left);
@include padding-left(0); @include padding-left(0);
font-size: 0.825rem; font-size: 0.825rem;
margin: 1rem 0; margin: 1rem 0;
display: table; display: table;
...@@ -42,19 +44,21 @@ $upgrade-message-background-color: $blue-d1; ...@@ -42,19 +44,21 @@ $upgrade-message-background-color: $blue-d1;
list-style: none; list-style: none;
display: table-row; display: table-row;
&:before { &::before {
content: "\2022"; content: "\2022";
display: table-cell; display: table-cell;
@include padding-right($baseline/2); @include padding-right($baseline/2);
} }
&:after { &::after {
content: ""; content: "";
display: table-row; display: table-row;
height: 0.25rem; height: 0.25rem;
} }
} }
} }
img { img {
max-width: 100%; max-width: 100%;
} }
...@@ -62,12 +66,14 @@ $upgrade-message-background-color: $blue-d1; ...@@ -62,12 +66,14 @@ $upgrade-message-background-color: $blue-d1;
// Show/hide button // Show/hide button
.vc-toggle { .vc-toggle {
@include float(right); @include float(right);
color: $white; color: $white;
} }
// Upgrade Button // Upgrade Button
.btn-upgrade { .btn-upgrade {
@extend %btn-primary-green; @extend %btn-primary-green;
background: $uxpl-green-base; background: $uxpl-green-base;
} }
...@@ -75,6 +81,7 @@ $upgrade-message-background-color: $blue-d1; ...@@ -75,6 +81,7 @@ $upgrade-message-background-color: $blue-d1;
.vc-hero { .vc-hero {
@include float(right); @include float(right);
@include padding-left(1rem); @include padding-left(1rem);
clear: both; clear: both;
width: 35%; width: 35%;
...@@ -95,6 +102,7 @@ $upgrade-message-background-color: $blue-d1; ...@@ -95,6 +102,7 @@ $upgrade-message-background-color: $blue-d1;
.vc-title { .vc-title {
margin: 0; margin: 0;
@include margin-right(auto); @include margin-right(auto);
} }
......
...@@ -59,6 +59,8 @@ ...@@ -59,6 +59,8 @@
"plato": "1.2.2", "plato": "1.2.2",
"selenium-webdriver": "3.4.0", "selenium-webdriver": "3.4.0",
"sinon": "2.3.5", "sinon": "2.3.5",
"squirejs": "^0.1.0" "squirejs": "^0.1.0",
"@edx/stylelint-config-edx": "^1.1.0",
"stylelint-formatter-pretty": "^1.0.3"
} }
} }
""" """
Tests for paver quality tasks Tests for Paver's Stylelint tasks.
""" """
import unittest import unittest
......
"""
Tests for Paver's Stylelint tasks.
"""
import ddt
from mock import MagicMock, patch
from paver.easy import call_task
from .utils import PaverTestCase
@ddt.ddt
class TestPaverStylelint(PaverTestCase):
"""
Tests for Paver's Stylelint tasks.
"""
def setUp(self):
super(TestPaverStylelint, self).setUp()
pass
@ddt.data(
[0, False],
[99, False],
[100, True],
)
@ddt.unpack
def test_run_stylelint(self, violations_limit, should_pass):
"""
Verify that the quality task fails with Stylelint violations.
"""
_mock_stylelint_violations = MagicMock(return_value=100)
with patch('pavelib.quality._get_stylelint_violations', _mock_stylelint_violations):
if should_pass:
call_task('pavelib.quality.run_stylelint', options={"limit": violations_limit})
else:
with self.assertRaises(SystemExit):
call_task('pavelib.quality.run_stylelint', options={"limit": violations_limit})
# coding=utf-8
""" """
Check code quality using pep8, pylint, and diff_quality. Check code quality using pep8, pylint, and diff_quality.
""" """
...@@ -6,7 +8,7 @@ import os ...@@ -6,7 +8,7 @@ import os
import re import re
from string import join from string import join
from paver.easy import BuildFailure, cmdopts, needs, sh, task from paver.easy import BuildFailure, call_task, cmdopts, needs, sh, task
from openedx.core.djangolib.markup import HTML from openedx.core.djangolib.markup import HTML
...@@ -189,7 +191,7 @@ def _get_pep8_violations(): ...@@ -189,7 +191,7 @@ def _get_pep8_violations():
"{report_dir}/pep8.report".format(report_dir=report_dir) "{report_dir}/pep8.report".format(report_dir=report_dir)
) )
return (count, violations_list) return count, violations_list
def _pep8_violations(report_file): def _pep8_violations(report_file):
...@@ -315,6 +317,60 @@ def run_eslint(options): ...@@ -315,6 +317,60 @@ def run_eslint(options):
) )
def _get_stylelint_violations():
"""
Returns the number of Stylelint violations.
"""
stylelint_report_dir = (Env.REPORT_DIR / "stylelint")
stylelint_report = stylelint_report_dir / "stylelint.report"
_prepare_report_dir(stylelint_report_dir)
formatter = 'node_modules/stylelint-formatter-pretty'
sh(
"stylelint **/*.scss --custom-formatter={formatter} | tee {stylelint_report}".format(
formatter=formatter,
stylelint_report=stylelint_report,
),
ignore_error=True
)
try:
return int(_get_count_from_last_line(stylelint_report, "stylelint"))
except TypeError:
raise BuildFailure(
"Error. Number of stylelint violations could not be found in {stylelint_report}".format(
stylelint_report=stylelint_report
)
)
@task
@needs('pavelib.prereqs.install_node_prereqs')
@cmdopts([
("limit=", "l", "limit for number of acceptable violations"),
])
@timed
def run_stylelint(options):
"""
Runs stylelint on Sass files.
If limit option is passed, fails build if more violations than the limit are found.
"""
violations_limit = int(getattr(options, 'limit', -1))
num_violations = _get_stylelint_violations()
# Record the metric
_write_metric(num_violations, (Env.METRICS_DIR / "stylelint"))
# Fail if number of violations is greater than the limit
if num_violations > violations_limit > -1:
raise BuildFailure(
"Stylelint failed with too many violations: ({count}).\nThe limit is {violations_limit}.".format(
count=num_violations,
violations_limit=violations_limit,
)
)
@task @task
@needs('pavelib.prereqs.install_python_prereqs') @needs('pavelib.prereqs.install_python_prereqs')
@cmdopts([ @cmdopts([
...@@ -518,7 +574,7 @@ def _get_count_from_last_line(filename, file_type): ...@@ -518,7 +574,7 @@ def _get_count_from_last_line(filename, file_type):
This will return the number in the last line of a file. This will return the number in the last line of a file.
It is returning only the value (as a floating number). It is returning only the value (as a floating number).
""" """
last_line = _get_report_contents(filename, last_line_only=True) last_line = _get_report_contents(filename, last_line_only=True).strip()
if file_type is "python_complexity": if file_type is "python_complexity":
# Example of the last line of a complexity report: "Average complexity: A (1.93953443446)" # Example of the last line of a complexity report: "Average complexity: A (1.93953443446)"
regex = r'\d+.\d+' regex = r'\d+.\d+'
......
...@@ -13,6 +13,7 @@ set -e ...@@ -13,6 +13,7 @@ set -e
# Violations thresholds for failing the build # Violations thresholds for failing the build
export PYLINT_THRESHOLD=3600 export PYLINT_THRESHOLD=3600
export ESLINT_THRESHOLD=9134 export ESLINT_THRESHOLD=9134
export STYLELINT_THRESHOLD=18416
XSSLINT_THRESHOLDS=`cat scripts/xsslint_thresholds.json` XSSLINT_THRESHOLDS=`cat scripts/xsslint_thresholds.json`
export XSSLINT_THRESHOLDS=${XSSLINT_THRESHOLDS//[[:space:]]/} export XSSLINT_THRESHOLDS=${XSSLINT_THRESHOLDS//[[:space:]]/}
......
...@@ -65,6 +65,9 @@ else ...@@ -65,6 +65,9 @@ else
echo "Finding ESLint violations and storing report..." echo "Finding ESLint violations and storing report..."
paver run_eslint -l $ESLINT_THRESHOLD > eslint.log || { cat eslint.log; EXIT=1; } paver run_eslint -l $ESLINT_THRESHOLD > eslint.log || { cat eslint.log; EXIT=1; }
echo "Finding Stylelint violations and storing report..."
paver run_stylelint -l $STYLELINT_THRESHOLD > stylelint.log || { cat stylelint.log; EXIT=1; }
# Run quality task. Pass in the 'fail-under' percentage to diff-quality # Run quality task. Pass in the 'fail-under' percentage to diff-quality
paver run_quality -p 100 || EXIT=1 paver run_quality -p 100 || EXIT=1
......
...@@ -84,6 +84,8 @@ case "$TEST_SUITE" in ...@@ -84,6 +84,8 @@ case "$TEST_SUITE" in
echo "Finding ESLint violations and storing report..." echo "Finding ESLint violations and storing report..."
paver run_eslint -l $ESLINT_THRESHOLD > eslint.log || { cat eslint.log; EXIT=1; } paver run_eslint -l $ESLINT_THRESHOLD > eslint.log || { cat eslint.log; EXIT=1; }
echo "Finding Stylelint violations and storing report..."
paver run_stylelint -l $STYLELINT_THRESHOLD > stylelint.log || { cat stylelint.log; EXIT=1; }
echo "Running code complexity report (python)." echo "Running code complexity report (python)."
paver run_complexity || echo "Unable to calculate code complexity. Ignoring error." paver run_complexity || echo "Unable to calculate code complexity. Ignoring error."
echo "Running xss linter report." echo "Running xss linter report."
......
module.exports = {
extends: '@edx/stylelint-config-edx'
};
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment