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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 836d64855e532ba7edb008a354400fdb3a752b40
4
- data.tar.gz: 9712c133bc9cf2ff5b9bc5081fc27ab2a258263b
3
+ metadata.gz: 881e2595ce6e859e53e9148db36e2f3d11bcb429
4
+ data.tar.gz: e28e168aa7ec435017b415278fe3fc68c8b911ca
5
5
  SHA512:
6
- metadata.gz: 8da6137c2915033192ede52347dd8ed2384a134afb192f8f053957da5d6043ea24b100d93f8acf6391bbef92e88d36aa6d97e258413056996b4aef0538de090e
7
- data.tar.gz: e043ed88d75c13b5343f18c2cab961853016bfce1533a721ed8cc7f323fe2bd37d24d50cb90ba5b76931f4fb94a3be67f9b009183c28d8967e9a5b6e27663846
6
+ metadata.gz: f27ed9d01d9a7920c3d88d0d9345b8ba107978fd536d90618d406af9cc8209221cc220054d1f118320af98927fce38b91144c4af1c4686d2a09b7dda2394aaaa
7
+ data.tar.gz: c6cfb9ba3bf3a0957cbd756b7e0cf9b4702432a94275214b97c98fd2884e63bc225adaec713148d41fae2b0078e070ed6e77ded6d3c4c4139b0cb8e4aaa0b3ec
data/config/default.yml CHANGED
@@ -168,7 +168,7 @@ linters:
168
168
 
169
169
  Shorthand:
170
170
  enabled: true
171
- allowed_shorthands: [1, 2, 3]
171
+ allowed_shorthands: [1, 2, 3, 4]
172
172
 
173
173
  SingleLinePerProperty:
174
174
  enabled: true
@@ -45,6 +45,7 @@ padding-left
45
45
 
46
46
  float
47
47
  clear
48
+ clip
48
49
 
49
50
  columns
50
51
  column-gap
@@ -106,6 +107,7 @@ outline-width
106
107
 
107
108
  background
108
109
  background-attachment
110
+ background-clip
109
111
  background-color
110
112
  background-image
111
113
  background-repeat
@@ -4,7 +4,7 @@ module SCSSLint
4
4
  include LinterRegistry
5
5
 
6
6
  def visit_debug(node)
7
- add_lint(node, 'Remove @debug line')
7
+ add_lint(node, 'Remove `@debug` line')
8
8
  end
9
9
  end
10
10
  end
@@ -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
- '@else should be placed on same line as previous curly brace')
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, '@else should be placed on its own line')
42
+ add_lint(else_node, '`@else` should be placed on its own line')
43
43
  end
44
44
  end
45
45
 
@@ -4,7 +4,7 @@ module SCSSLint
4
4
  include LinterRegistry
5
5
 
6
6
  def visit_extend(node)
7
- add_lint(node, 'Do not use the @extend directive (@include a @mixin ' \
7
+ add_lint(node, 'Do not use the `@extend` directive (`@include` a `@mixin` ' \
8
8
  'instead)')
9
9
  end
10
10
  end
@@ -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 FUNCTION_WHITELIST.include?(node.name)
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 FUNCTION_WHITELIST.include?(node.name)
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
- FUNCTION_WHITELIST = %w[
38
- rotateX rotateY rotateZ
39
- scaleX scaleY scaleZ
40
- skewX skewY
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 #{second[:name]} should be " \
109
- 'separated from the previous group of ' \
110
- "properties ending with #{first[:name]}"
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 =~ /^(#|\s*$)/ }
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*\.\d*)0+$/.match(original_number)
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
- "#{log.cyan(lint.filename)}:#{log.magenta(lint.location.line.to_s)}"
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)
@@ -2,5 +2,5 @@
2
2
 
3
3
  # Defines the gem version.
4
4
  module SCSSLint
5
- VERSION = '0.48.0'.freeze
5
+ VERSION = '0.49.0'.freeze
6
6
  end
@@ -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
- { 'allow_non_nested_indentation' => true,
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(:lines) { [502, 724] }
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
- location = SCSSLint::Location.new(lines[index])
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
- lines.each do |line|
45
- subject.report_lints.scan(line.to_s).count.should == 1
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 /2 total +\(across 1/
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 /3 total +\(across 1/
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 /6 total +\(across 3/
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.48.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-04-16 00:00:00.000000000 Z
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.15
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.15
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.4.5.1
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: