scss_lint 0.48.0 → 0.49.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/config/default.yml +1 -1
- data/data/property-sort-orders/smacss.txt +2 -0
- data/lib/scss_lint/linter/debug_statement.rb +1 -1
- data/lib/scss_lint/linter/else_placement.rb +2 -2
- data/lib/scss_lint/linter/extend_directive.rb +1 -1
- data/lib/scss_lint/linter/length_variable.rb +107 -0
- data/lib/scss_lint/linter/name_format.rb +27 -9
- data/lib/scss_lint/linter/property_sort_order.rb +4 -4
- data/lib/scss_lint/linter/shorthand.rb +3 -0
- data/lib/scss_lint/linter/space_around_operator.rb +1 -2
- data/lib/scss_lint/linter/trailing_zero.rb +1 -1
- data/lib/scss_lint/reporter/default_reporter.rb +5 -1
- data/lib/scss_lint/version.rb +1 -1
- data/spec/scss_lint/linter/indentation_spec.rb +2 -1
- data/spec/scss_lint/linter/length_variable_spec.rb +388 -0
- data/spec/scss_lint/linter/property_sort_order_spec.rb +27 -0
- data/spec/scss_lint/linter/shorthand_spec.rb +11 -0
- data/spec/scss_lint/linter/trailing_zero_spec.rb +10 -0
- data/spec/scss_lint/reporter/default_reporter_spec.rb +11 -4
- data/spec/scss_lint/reporter/stats_reporter_spec.rb +3 -3
- metadata +9 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 881e2595ce6e859e53e9148db36e2f3d11bcb429
|
4
|
+
data.tar.gz: e28e168aa7ec435017b415278fe3fc68c8b911ca
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f27ed9d01d9a7920c3d88d0d9345b8ba107978fd536d90618d406af9cc8209221cc220054d1f118320af98927fce38b91144c4af1c4686d2a09b7dda2394aaaa
|
7
|
+
data.tar.gz: c6cfb9ba3bf3a0957cbd756b7e0cf9b4702432a94275214b97c98fd2884e63bc225adaec713148d41fae2b0078e070ed6e77ded6d3c4c4139b0cb8e4aaa0b3ec
|
data/config/default.yml
CHANGED
@@ -36,10 +36,10 @@ module SCSSLint
|
|
36
36
|
if same_line_preferred?
|
37
37
|
unless curly_on_same_line
|
38
38
|
add_lint(else_node,
|
39
|
-
'
|
39
|
+
'`@else` should be placed on same line as previous curly brace')
|
40
40
|
end
|
41
41
|
elsif curly_on_same_line
|
42
|
-
add_lint(else_node, '
|
42
|
+
add_lint(else_node, '`@else` should be placed on its own line')
|
43
43
|
end
|
44
44
|
end
|
45
45
|
|
@@ -0,0 +1,107 @@
|
|
1
|
+
module SCSSLint
|
2
|
+
# Ensures length literals are used only in variable declarations.
|
3
|
+
class Linter::LengthVariable < Linter
|
4
|
+
include LinterRegistry
|
5
|
+
|
6
|
+
LENGTH_UNITS = [
|
7
|
+
'ch', 'em', 'ex', 'rem', # Font-relative lengths
|
8
|
+
'cm', 'in', 'mm', 'pc', 'pt', 'px', 'q', # Absolute lengths
|
9
|
+
'vh', 'vw', 'vmin', 'vmax' # Viewport-percentage lengths
|
10
|
+
].freeze
|
11
|
+
|
12
|
+
LENGTH_RE = %r{
|
13
|
+
(?:^|[\s+\-/*()]) # math or space separated, or beginning of string
|
14
|
+
( # capture whole length
|
15
|
+
0 # unitless zero
|
16
|
+
|
|
17
|
+
[-+]? # optional sign
|
18
|
+
(?:
|
19
|
+
\.\d+ # with leading decimal, e.g. .5
|
20
|
+
|
|
21
|
+
\d+(\.\d+)? # whole or maybe with trailing decimal
|
22
|
+
)
|
23
|
+
(?:#{LENGTH_UNITS.join('|')}) # unit!
|
24
|
+
)
|
25
|
+
(?:$|[\s+\-/*()]) # math or space separated, or end of string
|
26
|
+
}x
|
27
|
+
|
28
|
+
def visit_prop(node)
|
29
|
+
return if allowed_prop?(node)
|
30
|
+
lint_lengths(node)
|
31
|
+
end
|
32
|
+
|
33
|
+
def visit_mixindef(node)
|
34
|
+
lint_lengths(node)
|
35
|
+
end
|
36
|
+
|
37
|
+
def visit_media(node)
|
38
|
+
lint_lengths(node)
|
39
|
+
end
|
40
|
+
|
41
|
+
def visit_mixin(node)
|
42
|
+
lint_lengths(node)
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def lint_lengths(node)
|
48
|
+
lengths = extract_lengths(node)
|
49
|
+
lengths = [lengths].flatten.compact.uniq
|
50
|
+
lengths -= config['allowed_lengths'] if config['allowed_lengths']
|
51
|
+
lengths.each do |length|
|
52
|
+
record_lint(node, length) unless lengths.empty?
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def record_lint(node, length)
|
57
|
+
add_lint node, "Length literals like `#{length}` should only be used in " \
|
58
|
+
'variable declarations; they should be referred to via ' \
|
59
|
+
'variables everywhere else.'
|
60
|
+
end
|
61
|
+
|
62
|
+
def allowed_prop?(node)
|
63
|
+
config['allowed_properties'] && config['allowed_properties'].include?(node.name.first.to_s)
|
64
|
+
end
|
65
|
+
|
66
|
+
# Though long, This method is clear enough in a boring, dispatch kind of way.
|
67
|
+
# rubocop:disable Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/AbcSize
|
68
|
+
def extract_lengths(node)
|
69
|
+
case node
|
70
|
+
when Sass::Tree::PropNode
|
71
|
+
extract_lengths(node.value)
|
72
|
+
when Sass::Script::Tree::Literal
|
73
|
+
extract_lengths_from_string(node.value)
|
74
|
+
when String
|
75
|
+
extract_lengths_from_string(node)
|
76
|
+
when Sass::Script::Tree::Funcall,
|
77
|
+
Sass::Tree::MixinNode,
|
78
|
+
Sass::Tree::MixinDefNode
|
79
|
+
extract_lengths_from_list(*node.args)
|
80
|
+
when Sass::Script::Tree::ListLiteral
|
81
|
+
extract_lengths_from_list(*node.elements)
|
82
|
+
when Sass::Tree::MediaNode
|
83
|
+
extract_lengths_from_list(*node.query)
|
84
|
+
when Array
|
85
|
+
extract_lengths_from_list(*node)
|
86
|
+
when Sass::Script::Tree::Interpolation
|
87
|
+
extract_lengths_from_list(node.before, node.mid, node.after)
|
88
|
+
when Sass::Script::Tree::Operation
|
89
|
+
extract_lengths_from_list(node.operand1, node.operand2)
|
90
|
+
when Sass::Script::Tree::UnaryOperation
|
91
|
+
extract_lengths(node.operand)
|
92
|
+
when Sass::Script::Tree::Variable
|
93
|
+
nil
|
94
|
+
end
|
95
|
+
end
|
96
|
+
# rubocop:enable Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/AbcSize
|
97
|
+
|
98
|
+
def extract_lengths_from_string(string)
|
99
|
+
matchdata = string.to_s.match(LENGTH_RE)
|
100
|
+
matchdata && matchdata.captures
|
101
|
+
end
|
102
|
+
|
103
|
+
def extract_lengths_from_list(*values)
|
104
|
+
values.map { |v| extract_lengths(v) }
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
@@ -3,13 +3,34 @@ module SCSSLint
|
|
3
3
|
class Linter::NameFormat < Linter
|
4
4
|
include LinterRegistry
|
5
5
|
|
6
|
+
CSS_FUNCTION_WHITELIST = %w[
|
7
|
+
rotateX rotateY rotateZ
|
8
|
+
scaleX scaleY scaleZ
|
9
|
+
skewX skewY
|
10
|
+
translateX translateY translateZ
|
11
|
+
linear-gradient repeating-linear-gradient
|
12
|
+
radial-gradient repeating-radial-gradient
|
13
|
+
].to_set.freeze
|
14
|
+
|
15
|
+
SCSS_FUNCTION_WHITELIST = %w[
|
16
|
+
adjust-hue adjust-color scale-color change-color ie-hex-str
|
17
|
+
str-length str-insert str-index str-slice to-upper-case to-lower-case
|
18
|
+
list-separator
|
19
|
+
map-get map-merge map-remove map-keys map-values map-has-key
|
20
|
+
selector-nest selector-append selector-extend selector-replace
|
21
|
+
selector-unify is-superselector simple-selectors selector-parse
|
22
|
+
feature-exists variable-exists global-variable-exists function-exists
|
23
|
+
mixin-exists type-of
|
24
|
+
unique-id
|
25
|
+
].to_set.freeze
|
26
|
+
|
6
27
|
def visit_function(node)
|
7
28
|
check_name(node, 'function')
|
8
29
|
yield # Continue into content block of this function definition
|
9
30
|
end
|
10
31
|
|
11
32
|
def visit_mixin(node)
|
12
|
-
check_name(node, 'mixin') unless
|
33
|
+
check_name(node, 'mixin') unless whitelist?(node.name)
|
13
34
|
yield # Continue into content block of this mixin's block
|
14
35
|
end
|
15
36
|
|
@@ -19,7 +40,7 @@ module SCSSLint
|
|
19
40
|
end
|
20
41
|
|
21
42
|
def visit_script_funcall(node)
|
22
|
-
check_name(node, 'function') unless
|
43
|
+
check_name(node, 'function') unless whitelist?(node.name)
|
23
44
|
yield # Continue linting any arguments of this function call
|
24
45
|
end
|
25
46
|
|
@@ -34,13 +55,10 @@ module SCSSLint
|
|
34
55
|
|
35
56
|
private
|
36
57
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
translateX translateY translateZ
|
42
|
-
linear-gradient
|
43
|
-
].to_set
|
58
|
+
def whitelist?(name)
|
59
|
+
CSS_FUNCTION_WHITELIST.include?(name) ||
|
60
|
+
SCSS_FUNCTION_WHITELIST.include?(name)
|
61
|
+
end
|
44
62
|
|
45
63
|
def check_name(node, node_type, node_text = node.name)
|
46
64
|
node_text = trim_underscore_prefix(node_text)
|
@@ -105,9 +105,9 @@ module SCSSLint
|
|
105
105
|
# we don't care, but at least one line that isn't another property).
|
106
106
|
next if first[:node].line < second[:node].line - 1
|
107
107
|
|
108
|
-
add_lint second[:node], "Property
|
109
|
-
'
|
110
|
-
"properties ending with
|
108
|
+
add_lint second[:node], "Property `#{second[:name]}` should have an " \
|
109
|
+
'empty line separating it from the previous ' \
|
110
|
+
"group of properties ending with `#{first[:name]}`"
|
111
111
|
end
|
112
112
|
end
|
113
113
|
|
@@ -163,7 +163,7 @@ module SCSSLint
|
|
163
163
|
file = File.open(File.join(SCSS_LINT_DATA,
|
164
164
|
'property-sort-orders',
|
165
165
|
"#{config['order']}.txt"))
|
166
|
-
file.read.split("\n").reject { |line| line =~
|
166
|
+
file.read.split("\n").reject { |line| line =~ /^\s*#/ }
|
167
167
|
rescue Errno::ENOENT
|
168
168
|
raise SCSSLint::Exceptions::LinterError,
|
169
169
|
"Preset property sort order '#{config['order']}' does not exist"
|
@@ -68,6 +68,9 @@ module SCSSLint
|
|
68
68
|
# @param node [Sass::Script::Value::String]
|
69
69
|
# @param values [Array<String>]
|
70
70
|
def check_shorthand(prop, node, values)
|
71
|
+
add_lint(node, "Shorthands of length `#{values.count}` are not allowed. " \
|
72
|
+
"Value was `#{values.join(' ')}`") unless allowed?(values.count)
|
73
|
+
|
71
74
|
return unless (2..4).member?(values.count)
|
72
75
|
|
73
76
|
shortest_form = condensed_shorthand(*values)
|
@@ -94,8 +94,7 @@ module SCSSLint
|
|
94
94
|
end
|
95
95
|
|
96
96
|
def adjust_for_interpolation
|
97
|
-
@source = normalize_source(
|
98
|
-
@linter.source_fm_range(slide_to_the_left(@node.source_range)))
|
97
|
+
@source = normalize_source(@linter.source_fm_range(slide_to_the_left(@node.source_range)))
|
99
98
|
@left_range = slide_to_the_left(@node.operand1.source_range)
|
100
99
|
@right_range = slide_to_the_left(@node.operand2.source_range)
|
101
100
|
end
|
@@ -25,7 +25,7 @@ module SCSSLint
|
|
25
25
|
FRACTIONAL_DIGIT_REGEX = /^-?(\d*\.\d+)/
|
26
26
|
|
27
27
|
def check_for_trailing_zeros(node, original_number)
|
28
|
-
return unless match = /^(\d
|
28
|
+
return unless match = /^(\d*\.(?:[0-9]*[1-9]|[1-9])*)0+$/.match(original_number)
|
29
29
|
|
30
30
|
fixed_number = match[1]
|
31
31
|
|
@@ -12,7 +12,11 @@ module SCSSLint
|
|
12
12
|
private
|
13
13
|
|
14
14
|
def location(lint)
|
15
|
-
|
15
|
+
[
|
16
|
+
log.cyan(lint.filename),
|
17
|
+
log.magenta(lint.location.line.to_s),
|
18
|
+
log.magenta(lint.location.column.to_s),
|
19
|
+
].join(':')
|
16
20
|
end
|
17
21
|
|
18
22
|
def type(lint)
|
data/lib/scss_lint/version.rb
CHANGED
@@ -274,7 +274,8 @@ describe SCSSLint::Linter::Indentation do
|
|
274
274
|
|
275
275
|
context 'when indentation in non-nested code is allowed' do
|
276
276
|
let(:linter_config) do
|
277
|
-
{
|
277
|
+
{
|
278
|
+
'allow_non_nested_indentation' => true,
|
278
279
|
'character' => 'space',
|
279
280
|
'width' => 2,
|
280
281
|
}
|
@@ -0,0 +1,388 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe SCSSLint::Linter::LengthVariable do
|
4
|
+
context 'when a length literal is used in a variable declaration' do
|
5
|
+
let(:scss) { <<-SCSS }
|
6
|
+
$my-length: 10px;
|
7
|
+
SCSS
|
8
|
+
|
9
|
+
it { should_not report_lint }
|
10
|
+
end
|
11
|
+
|
12
|
+
context 'when a length calculation containing literals is used in a variable declaration' do
|
13
|
+
let(:scss) { <<-SCSS }
|
14
|
+
$my-length: 10px / 2;
|
15
|
+
SCSS
|
16
|
+
|
17
|
+
it { should_not report_lint }
|
18
|
+
end
|
19
|
+
|
20
|
+
context 'when a length literal is used in a property' do
|
21
|
+
let(:scss) { <<-SCSS }
|
22
|
+
p {
|
23
|
+
width: 10px;
|
24
|
+
}
|
25
|
+
SCSS
|
26
|
+
|
27
|
+
it { should report_lint line: 2 }
|
28
|
+
end
|
29
|
+
|
30
|
+
context 'when a negative length literal is used in a property' do
|
31
|
+
let(:scss) { <<-SCSS }
|
32
|
+
p {
|
33
|
+
margin: -10px;
|
34
|
+
}
|
35
|
+
SCSS
|
36
|
+
|
37
|
+
it { should report_lint line: 2 }
|
38
|
+
end
|
39
|
+
|
40
|
+
context 'when a length literal is used in a function call' do
|
41
|
+
let(:scss) { <<-SCSS }
|
42
|
+
p {
|
43
|
+
width: my-func(10px);
|
44
|
+
}
|
45
|
+
SCSS
|
46
|
+
|
47
|
+
it { should report_lint line: 2 }
|
48
|
+
end
|
49
|
+
|
50
|
+
context 'when a length literal is used in a mixin' do
|
51
|
+
let(:scss) { <<-SCSS }
|
52
|
+
p {
|
53
|
+
@include my-mixin(10px);
|
54
|
+
}
|
55
|
+
SCSS
|
56
|
+
|
57
|
+
it { should report_lint line: 2 }
|
58
|
+
end
|
59
|
+
|
60
|
+
context 'when a length literal is used in a shorthand property' do
|
61
|
+
let(:scss) { <<-SCSS }
|
62
|
+
p {
|
63
|
+
text-shadow: 10px 10px black;
|
64
|
+
}
|
65
|
+
SCSS
|
66
|
+
|
67
|
+
it { should report_lint line: 2 }
|
68
|
+
end
|
69
|
+
|
70
|
+
context 'when a length literal is used as a mixin default argument' do
|
71
|
+
let(:scss) { <<-SCSS }
|
72
|
+
@mixin checkbox ($length: 10px) {
|
73
|
+
width: $length;
|
74
|
+
}
|
75
|
+
SCSS
|
76
|
+
|
77
|
+
it { should report_lint line: 1 }
|
78
|
+
end
|
79
|
+
|
80
|
+
context 'when a number is used in a property' do
|
81
|
+
let(:scss) { <<-SCSS }
|
82
|
+
p {
|
83
|
+
z-index: 9000;
|
84
|
+
transition-duration: 250ms;
|
85
|
+
line-height: 1;
|
86
|
+
}
|
87
|
+
SCSS
|
88
|
+
|
89
|
+
it { should_not report_lint }
|
90
|
+
end
|
91
|
+
|
92
|
+
context 'when a non-length keyword is used in a property' do
|
93
|
+
let(:scss) { <<-SCSS }
|
94
|
+
p {
|
95
|
+
width: auto;
|
96
|
+
}
|
97
|
+
SCSS
|
98
|
+
|
99
|
+
it { should_not report_lint }
|
100
|
+
end
|
101
|
+
|
102
|
+
context 'when a variable is used in a property' do
|
103
|
+
let(:scss) { <<-SCSS }
|
104
|
+
p {
|
105
|
+
width: $my-length;
|
106
|
+
}
|
107
|
+
SCSS
|
108
|
+
|
109
|
+
it { should_not report_lint }
|
110
|
+
end
|
111
|
+
|
112
|
+
context 'when a variable is used in a function call' do
|
113
|
+
let(:scss) { <<-SCSS }
|
114
|
+
p {
|
115
|
+
width: my-func($my-length);
|
116
|
+
}
|
117
|
+
SCSS
|
118
|
+
|
119
|
+
it { should_not report_lint }
|
120
|
+
end
|
121
|
+
|
122
|
+
context 'when a variable operated with a literal' do
|
123
|
+
let(:scss) { <<-SCSS }
|
124
|
+
p {
|
125
|
+
width: $my-length + 10px;
|
126
|
+
height: $my-length - 10px;
|
127
|
+
top: $my-length * 10px;
|
128
|
+
bottom: $my-length - 10px;
|
129
|
+
}
|
130
|
+
SCSS
|
131
|
+
|
132
|
+
it { should report_lint line: 2 }
|
133
|
+
it { should report_lint line: 3 }
|
134
|
+
it { should report_lint line: 4 }
|
135
|
+
it { should report_lint line: 5 }
|
136
|
+
end
|
137
|
+
|
138
|
+
context 'when a variable unary operation' do
|
139
|
+
let(:scss) { <<-SCSS }
|
140
|
+
p {
|
141
|
+
top: -$my-length;
|
142
|
+
bottom: +$my-length;
|
143
|
+
}
|
144
|
+
SCSS
|
145
|
+
|
146
|
+
it { should_not report_lint line: 2 }
|
147
|
+
it { should_not report_lint line: 3 }
|
148
|
+
end
|
149
|
+
|
150
|
+
context 'when a variable is used in a shorthand property' do
|
151
|
+
let(:scss) { <<-SCSS }
|
152
|
+
p {
|
153
|
+
border: $my-length solid black;
|
154
|
+
}
|
155
|
+
SCSS
|
156
|
+
|
157
|
+
it { should_not report_lint }
|
158
|
+
end
|
159
|
+
|
160
|
+
context 'when a property contains "auto"' do
|
161
|
+
let(:scss) { <<-SCSS }
|
162
|
+
p {
|
163
|
+
margin: auto;
|
164
|
+
}
|
165
|
+
SCSS
|
166
|
+
|
167
|
+
it { should_not report_lint }
|
168
|
+
end
|
169
|
+
|
170
|
+
context 'when a length literal is used in a map declaration' do
|
171
|
+
let(:scss) { <<-SCSS }
|
172
|
+
$margins: (
|
173
|
+
small: 4px,
|
174
|
+
medium: 8px,
|
175
|
+
large: 16px
|
176
|
+
);
|
177
|
+
SCSS
|
178
|
+
|
179
|
+
it { should_not report_lint }
|
180
|
+
end
|
181
|
+
|
182
|
+
context 'when a string with a length is used in a function call' do
|
183
|
+
let(:scss) { <<-SCSS }
|
184
|
+
p {
|
185
|
+
width: my-func('10px');
|
186
|
+
}
|
187
|
+
SCSS
|
188
|
+
|
189
|
+
it { should_not report_lint }
|
190
|
+
end
|
191
|
+
|
192
|
+
context 'when a variable is interpolated in a multiline comment' do
|
193
|
+
let(:scss) { <<-SCSS }
|
194
|
+
$a: 0;
|
195
|
+
|
196
|
+
/*!
|
197
|
+
* test \#{a}
|
198
|
+
*/
|
199
|
+
SCSS
|
200
|
+
|
201
|
+
it { should_not report_lint }
|
202
|
+
end
|
203
|
+
|
204
|
+
context 'when using calc' do
|
205
|
+
let(:scss) { <<-SCSS }
|
206
|
+
p {
|
207
|
+
width: calc(100em + 5px);
|
208
|
+
}
|
209
|
+
SCSS
|
210
|
+
|
211
|
+
it { should report_lint line: 2 }
|
212
|
+
end
|
213
|
+
|
214
|
+
context 'when using calc with no spacing' do
|
215
|
+
let(:scss) { <<-SCSS }
|
216
|
+
p {
|
217
|
+
width: calc(100em+5px);
|
218
|
+
}
|
219
|
+
SCSS
|
220
|
+
|
221
|
+
it { should report_lint line: 2 }
|
222
|
+
end
|
223
|
+
|
224
|
+
context 'when using calc with all interpolations' do
|
225
|
+
let(:scss) { <<-SCSS }
|
226
|
+
p {
|
227
|
+
width: calc(\#{$my-width} + \#{$my-spacing});
|
228
|
+
}
|
229
|
+
SCSS
|
230
|
+
|
231
|
+
it { should_not report_lint }
|
232
|
+
end
|
233
|
+
|
234
|
+
context 'when a variable is interpolated' do
|
235
|
+
let(:scss) { <<-SCSS }
|
236
|
+
p {
|
237
|
+
width: calc(\#{$my-length} + 5px)
|
238
|
+
}
|
239
|
+
SCSS
|
240
|
+
|
241
|
+
it { should report_lint line: 2 }
|
242
|
+
end
|
243
|
+
|
244
|
+
context 'when a literal is interpolated' do
|
245
|
+
let(:scss) { <<-SCSS }
|
246
|
+
p {
|
247
|
+
width: calc(\#{10px} + $my-length)
|
248
|
+
}
|
249
|
+
SCSS
|
250
|
+
|
251
|
+
it { should report_lint line: 2 }
|
252
|
+
end
|
253
|
+
|
254
|
+
context 'when a string is interpolated' do ## analogous to the ColorVariable linter
|
255
|
+
let(:scss) { <<-SCSS }
|
256
|
+
p {
|
257
|
+
width: calc(\#{'10px'} + $my-length)
|
258
|
+
}
|
259
|
+
SCSS
|
260
|
+
|
261
|
+
it { should_not report_lint }
|
262
|
+
end
|
263
|
+
|
264
|
+
context 'when disambiguating with brackets' do
|
265
|
+
let(:scss) { <<-SCSS }
|
266
|
+
p {
|
267
|
+
margin: (-10px) (-10px);
|
268
|
+
}
|
269
|
+
SCSS
|
270
|
+
|
271
|
+
it { should report_lint line: 2 }
|
272
|
+
end
|
273
|
+
|
274
|
+
context 'in the awkward looking font shorthand' do
|
275
|
+
let(:scss) { <<-SCSS }
|
276
|
+
strong { font: bold 10px/14px sans-serif; }
|
277
|
+
em { font: bold $my-font-size/14px sans-serif; }
|
278
|
+
blockquote { font: bold 10px/$my-line-height sans-serif; }
|
279
|
+
p { font: bold $my-font-size/1 sans-serif; }
|
280
|
+
SCSS
|
281
|
+
|
282
|
+
it { should report_lint line: 1 }
|
283
|
+
it { should report_lint line: 2 }
|
284
|
+
it { should report_lint line: 3 }
|
285
|
+
it { should_not report_lint line: 4 }
|
286
|
+
end
|
287
|
+
|
288
|
+
context 'when a length is used in a media query' do
|
289
|
+
let(:scss) { <<-SCSS }
|
290
|
+
@media (min-width:100px) {
|
291
|
+
p { color: red; }
|
292
|
+
}
|
293
|
+
@media (max-width: 100px ) {
|
294
|
+
p { color: blue; }
|
295
|
+
}
|
296
|
+
@media (max-width: 100px*5) {
|
297
|
+
p { color: orange; }
|
298
|
+
}
|
299
|
+
@media (min-device-pixel-ratio: 2) {
|
300
|
+
p { color: green; }
|
301
|
+
}
|
302
|
+
SCSS
|
303
|
+
|
304
|
+
it { should report_lint line: 1 }
|
305
|
+
it { should report_lint line: 4 }
|
306
|
+
it { should report_lint line: 7 }
|
307
|
+
it { should_not report_lint line: 10 }
|
308
|
+
end
|
309
|
+
|
310
|
+
context 'when length is allowed' do
|
311
|
+
let(:linter_config) { { 'allowed_lengths' => %w[100px 0 5px] } }
|
312
|
+
context 'when using an allowed length' do
|
313
|
+
let(:scss) { <<-SCSS }
|
314
|
+
p {
|
315
|
+
width: 100px;
|
316
|
+
border-width: 0;
|
317
|
+
}
|
318
|
+
SCSS
|
319
|
+
|
320
|
+
it { should_not report_lint }
|
321
|
+
end
|
322
|
+
|
323
|
+
context 'when using an allowed length in a calculation' do
|
324
|
+
let(:scss) { <<-SCSS }
|
325
|
+
p {
|
326
|
+
margin: -(5px);
|
327
|
+
border-width: $my-variable + 5px;
|
328
|
+
width: calc(100px + \#{$my-margin});
|
329
|
+
}
|
330
|
+
SCSS
|
331
|
+
|
332
|
+
it { should_not report_lint }
|
333
|
+
end
|
334
|
+
|
335
|
+
context 'when using a similar disallowed length' do
|
336
|
+
let(:scss) { <<-SCSS }
|
337
|
+
p {
|
338
|
+
width: 101px;
|
339
|
+
margin: 100em;
|
340
|
+
border-width: 0;
|
341
|
+
}
|
342
|
+
SCSS
|
343
|
+
|
344
|
+
it { should report_lint line: 2 }
|
345
|
+
it { should report_lint line: 3 }
|
346
|
+
it { should_not report_lint line: 4 }
|
347
|
+
end
|
348
|
+
end
|
349
|
+
|
350
|
+
context 'when using a length with an allowed property' do
|
351
|
+
let(:linter_config) { { 'allowed_properties' => ['text-shadow', 'box-shadow'] } }
|
352
|
+
let(:scss) { <<-SCSS }
|
353
|
+
p {
|
354
|
+
text-shadow: 10px 10px 5px blue;
|
355
|
+
box-shadow: 10px 10px 5px red;
|
356
|
+
width: $my-variable;
|
357
|
+
}
|
358
|
+
SCSS
|
359
|
+
|
360
|
+
it { should_not report_lint }
|
361
|
+
end
|
362
|
+
|
363
|
+
context 'when a length calculation containing literals is used in a property' do
|
364
|
+
let(:scss) { <<-SCSS }
|
365
|
+
p {
|
366
|
+
width: 10px + 10px;
|
367
|
+
}
|
368
|
+
a {
|
369
|
+
width: 10px - 10px;
|
370
|
+
}
|
371
|
+
i {
|
372
|
+
width: 10px / 4;
|
373
|
+
}
|
374
|
+
span {
|
375
|
+
width: 10px * 2;
|
376
|
+
}
|
377
|
+
.class {
|
378
|
+
width: -10px + 11;
|
379
|
+
}
|
380
|
+
SCSS
|
381
|
+
|
382
|
+
it { should report_lint line: 2 }
|
383
|
+
it { should report_lint line: 5 }
|
384
|
+
it { should report_lint line: 8 }
|
385
|
+
it { should report_lint line: 11 }
|
386
|
+
it { should report_lint line: 14 }
|
387
|
+
end
|
388
|
+
end
|
@@ -405,6 +405,33 @@ describe SCSSLint::Linter::PropertySortOrder do
|
|
405
405
|
|
406
406
|
it { should report_lint line: 3 }
|
407
407
|
end
|
408
|
+
|
409
|
+
context 'and `separate_groups` is enabled' do
|
410
|
+
let(:linter_config) { super().merge('separate_groups' => true) }
|
411
|
+
|
412
|
+
context 'and the properties are not separated' do
|
413
|
+
let(:scss) { <<-SCSS }
|
414
|
+
p {
|
415
|
+
visibility: hidden;
|
416
|
+
margin: 0;
|
417
|
+
}
|
418
|
+
SCSS
|
419
|
+
|
420
|
+
it { should report_lint }
|
421
|
+
end
|
422
|
+
|
423
|
+
context 'and the properties are separated' do
|
424
|
+
let(:scss) { <<-SCSS }
|
425
|
+
p {
|
426
|
+
visibility: hidden;
|
427
|
+
|
428
|
+
margin: 0;
|
429
|
+
}
|
430
|
+
SCSS
|
431
|
+
|
432
|
+
it { should_not report_lint }
|
433
|
+
end
|
434
|
+
end
|
408
435
|
end
|
409
436
|
end
|
410
437
|
|
@@ -194,5 +194,16 @@ describe SCSSLint::Linter::Shorthand do
|
|
194
194
|
|
195
195
|
it { should_not report_lint }
|
196
196
|
end
|
197
|
+
|
198
|
+
context 'is fine but length is not allowed' do
|
199
|
+
let(:allowed) { [1, 2, 3] }
|
200
|
+
let(:scss) { <<-SCSS }
|
201
|
+
p {
|
202
|
+
margin: 1px 2px 3px 4px;
|
203
|
+
}
|
204
|
+
SCSS
|
205
|
+
|
206
|
+
it { should report_lint }
|
207
|
+
end
|
197
208
|
end
|
198
209
|
end
|
@@ -47,6 +47,16 @@ describe SCSSLint::Linter::TrailingZero do
|
|
47
47
|
it { should_not report_lint }
|
48
48
|
end
|
49
49
|
|
50
|
+
context 'when a unitless fractional value with multiple trailing zero exists' do
|
51
|
+
let(:scss) { <<-SCSS }
|
52
|
+
p {
|
53
|
+
line-height: .600;
|
54
|
+
}
|
55
|
+
SCSS
|
56
|
+
|
57
|
+
it { should report_lint }
|
58
|
+
end
|
59
|
+
|
50
60
|
context 'when a negative unitless fractional value with no trailing zero exists' do
|
51
61
|
let(:scss) { <<-SCSS }
|
52
62
|
p {
|
@@ -15,12 +15,13 @@ describe SCSSLint::Reporter::DefaultReporter do
|
|
15
15
|
|
16
16
|
context 'when there are lints' do
|
17
17
|
let(:filenames) { ['some-filename.scss', 'other-filename.scss'] }
|
18
|
-
let(:
|
18
|
+
let(:locations) { [[502, 3], [724, 6]] }
|
19
19
|
let(:descriptions) { ['Description of lint 1', 'Description of lint 2'] }
|
20
20
|
let(:severities) { [:warning] * 2 }
|
21
21
|
let(:lints) do
|
22
22
|
filenames.each_with_index.map do |filename, index|
|
23
|
-
|
23
|
+
line, column = locations[index]
|
24
|
+
location = SCSSLint::Location.new(line, column, 10)
|
24
25
|
SCSSLint::Lint.new(nil, filename, location, descriptions[index],
|
25
26
|
severities[index])
|
26
27
|
end
|
@@ -41,8 +42,14 @@ describe SCSSLint::Reporter::DefaultReporter do
|
|
41
42
|
end
|
42
43
|
|
43
44
|
it 'prints the line number for each lint' do
|
44
|
-
|
45
|
-
subject.report_lints.scan(
|
45
|
+
locations.each do |location|
|
46
|
+
subject.report_lints.scan(location[0].to_s).count.should == 1
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'prints the column number for each lint' do
|
51
|
+
locations.each do |location|
|
52
|
+
subject.report_lints.scan(location[1].to_s).count.should == 1
|
46
53
|
end
|
47
54
|
end
|
48
55
|
|
@@ -44,7 +44,7 @@ describe SCSSLint::Reporter::StatsReporter do
|
|
44
44
|
end
|
45
45
|
|
46
46
|
it 'prints the total lints and total lines' do
|
47
|
-
subject.report_lints.should match
|
47
|
+
subject.report_lints.should match(/2 total +\(across 1/)
|
48
48
|
end
|
49
49
|
end
|
50
50
|
|
@@ -74,7 +74,7 @@ describe SCSSLint::Reporter::StatsReporter do
|
|
74
74
|
end
|
75
75
|
|
76
76
|
it 'prints the total lints and total lines' do
|
77
|
-
subject.report_lints.should match
|
77
|
+
subject.report_lints.should match(/3 total +\(across 1/)
|
78
78
|
end
|
79
79
|
end
|
80
80
|
|
@@ -108,7 +108,7 @@ describe SCSSLint::Reporter::StatsReporter do
|
|
108
108
|
end
|
109
109
|
|
110
110
|
it 'prints the total lints and total lines' do
|
111
|
-
subject.report_lints.should match
|
111
|
+
subject.report_lints.should match(/6 total +\(across 3/)
|
112
112
|
end
|
113
113
|
end
|
114
114
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: scss_lint
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.49.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brigade Engineering
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2016-
|
12
|
+
date: 2016-07-05 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rake
|
@@ -37,14 +37,14 @@ dependencies:
|
|
37
37
|
requirements:
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: 3.4.
|
40
|
+
version: 3.4.20
|
41
41
|
type: :runtime
|
42
42
|
prerelease: false
|
43
43
|
version_requirements: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: 3.4.
|
47
|
+
version: 3.4.20
|
48
48
|
description: Configurable tool for writing clean and consistent SCSS
|
49
49
|
email:
|
50
50
|
- eng@brigade.com
|
@@ -100,6 +100,7 @@ files:
|
|
100
100
|
- lib/scss_lint/linter/important_rule.rb
|
101
101
|
- lib/scss_lint/linter/indentation.rb
|
102
102
|
- lib/scss_lint/linter/leading_zero.rb
|
103
|
+
- lib/scss_lint/linter/length_variable.rb
|
103
104
|
- lib/scss_lint/linter/mergeable_selector.rb
|
104
105
|
- lib/scss_lint/linter/name_format.rb
|
105
106
|
- lib/scss_lint/linter/nesting_depth.rb
|
@@ -188,6 +189,7 @@ files:
|
|
188
189
|
- spec/scss_lint/linter/important_rule_spec.rb
|
189
190
|
- spec/scss_lint/linter/indentation_spec.rb
|
190
191
|
- spec/scss_lint/linter/leading_zero_spec.rb
|
192
|
+
- spec/scss_lint/linter/length_variable_spec.rb
|
191
193
|
- spec/scss_lint/linter/mergeable_selector_spec.rb
|
192
194
|
- spec/scss_lint/linter/name_format_spec.rb
|
193
195
|
- spec/scss_lint/linter/nesting_depth_spec.rb
|
@@ -268,7 +270,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
268
270
|
version: '0'
|
269
271
|
requirements: []
|
270
272
|
rubyforge_project:
|
271
|
-
rubygems_version: 2.
|
273
|
+
rubygems_version: 2.5.1
|
272
274
|
signing_key:
|
273
275
|
specification_version: 4
|
274
276
|
summary: SCSS lint tool
|
@@ -303,6 +305,7 @@ test_files:
|
|
303
305
|
- spec/scss_lint/linter/important_rule_spec.rb
|
304
306
|
- spec/scss_lint/linter/indentation_spec.rb
|
305
307
|
- spec/scss_lint/linter/leading_zero_spec.rb
|
308
|
+
- spec/scss_lint/linter/length_variable_spec.rb
|
306
309
|
- spec/scss_lint/linter/mergeable_selector_spec.rb
|
307
310
|
- spec/scss_lint/linter/name_format_spec.rb
|
308
311
|
- spec/scss_lint/linter/nesting_depth_spec.rb
|
@@ -363,3 +366,4 @@ test_files:
|
|
363
366
|
- spec/spec_helper.rb
|
364
367
|
- spec/support/isolated_environment.rb
|
365
368
|
- spec/support/matchers/report_lint.rb
|
369
|
+
has_rdoc:
|