scss_lint 0.43.2 → 0.44.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/scss-lint +2 -1
- data/config/default.yml +3 -0
- data/data/properties.txt +35 -0
- data/data/property-sort-orders/smacss.txt +9 -0
- data/data/pseudo-elements.txt +5 -0
- data/lib/scss_lint.rb +1 -0
- data/lib/scss_lint/cli.rb +50 -30
- data/lib/scss_lint/config.rb +28 -3
- data/lib/scss_lint/constants.rb +6 -4
- data/lib/scss_lint/control_comment_processor.rb +8 -7
- data/lib/scss_lint/engine.rb +1 -1
- data/lib/scss_lint/file_finder.rb +1 -1
- data/lib/scss_lint/linter.rb +8 -7
- data/lib/scss_lint/linter/bang_format.rb +2 -2
- data/lib/scss_lint/linter/border_zero.rb +2 -2
- data/lib/scss_lint/linter/color_variable.rb +1 -1
- data/lib/scss_lint/linter/declaration_order.rb +10 -8
- data/lib/scss_lint/linter/duplicate_property.rb +2 -2
- data/lib/scss_lint/linter/empty_line_between_blocks.rb +3 -1
- data/lib/scss_lint/linter/final_newline.rb +3 -3
- data/lib/scss_lint/linter/indentation.rb +20 -20
- data/lib/scss_lint/linter/leading_zero.rb +2 -2
- data/lib/scss_lint/linter/mergeable_selector.rb +3 -4
- data/lib/scss_lint/linter/name_format.rb +2 -1
- data/lib/scss_lint/linter/nesting_depth.rb +1 -1
- data/lib/scss_lint/linter/property_sort_order.rb +11 -13
- data/lib/scss_lint/linter/selector_depth.rb +9 -8
- data/lib/scss_lint/linter/selector_format.rb +1 -1
- data/lib/scss_lint/linter/shorthand.rb +1 -1
- data/lib/scss_lint/linter/single_line_per_selector.rb +3 -1
- data/lib/scss_lint/linter/space_around_operator.rb +4 -2
- data/lib/scss_lint/linter/space_before_brace.rb +8 -8
- data/lib/scss_lint/linter/space_between_parens.rb +11 -11
- data/lib/scss_lint/linter/string_quotes.rb +9 -10
- data/lib/scss_lint/linter/trailing_zero.rb +1 -1
- data/lib/scss_lint/linter/transition_all.rb +1 -1
- data/lib/scss_lint/linter/unnecessary_mantissa.rb +3 -1
- data/lib/scss_lint/linter/unnecessary_parent_reference.rb +9 -2
- data/lib/scss_lint/linter/url_quotes.rb +4 -2
- data/lib/scss_lint/linter/variable_for_property.rb +1 -1
- data/lib/scss_lint/linter/vendor_prefix.rb +3 -3
- data/lib/scss_lint/linter/zero_unit.rb +3 -1
- data/lib/scss_lint/location.rb +1 -1
- data/lib/scss_lint/logger.rb +149 -0
- data/lib/scss_lint/options.rb +5 -1
- data/lib/scss_lint/rake_task.rb +10 -3
- data/lib/scss_lint/reporter.rb +4 -2
- data/lib/scss_lint/reporter/default_reporter.rb +3 -3
- data/lib/scss_lint/version.rb +3 -1
- data/spec/scss_lint/cli_spec.rb +66 -14
- data/spec/scss_lint/config_spec.rb +25 -5
- data/spec/scss_lint/linter/name_format_spec.rb +10 -0
- data/spec/scss_lint/linter/property_sort_order_spec.rb +28 -0
- data/spec/scss_lint/linter/unnecessary_parent_reference_spec.rb +10 -0
- data/spec/scss_lint/linter/variable_for_property_spec.rb +10 -0
- data/spec/scss_lint/logger_spec.rb +27 -0
- data/spec/scss_lint/options_spec.rb +18 -0
- data/spec/scss_lint/plugins/linter_dir_spec.rb +1 -1
- data/spec/scss_lint/reporter/clean_files_reporter_spec.rb +1 -1
- data/spec/scss_lint/reporter/config_reporter_spec.rb +1 -1
- data/spec/scss_lint/reporter/default_reporter_spec.rb +2 -1
- data/spec/scss_lint/reporter/files_reporter_spec.rb +1 -1
- data/spec/scss_lint/reporter/json_reporter_spec.rb +5 -5
- metadata +10 -7
@@ -12,15 +12,15 @@ module SCSSLint
|
|
12
12
|
private
|
13
13
|
|
14
14
|
def location(lint)
|
15
|
-
"#{lint.filename
|
15
|
+
"#{log.cyan(lint.filename)}:#{log.magenta(lint.location.line.to_s)}"
|
16
16
|
end
|
17
17
|
|
18
18
|
def type(lint)
|
19
|
-
lint.error? ? '[E]'
|
19
|
+
lint.error? ? log.red('[E]') : log.yellow('[W]')
|
20
20
|
end
|
21
21
|
|
22
22
|
def message(lint)
|
23
|
-
linter_name = "#{lint.linter.name}: "
|
23
|
+
linter_name = log.green("#{lint.linter.name}: ") if lint.linter
|
24
24
|
"#{linter_name}#{lint.description}"
|
25
25
|
end
|
26
26
|
end
|
data/lib/scss_lint/version.rb
CHANGED
data/spec/scss_lint/cli_spec.rb
CHANGED
@@ -19,10 +19,6 @@ describe SCSSLint::CLI do
|
|
19
19
|
class SCSSLint::Linter::FakeTestLinter2 < SCSSLint::Linter; end
|
20
20
|
|
21
21
|
before do
|
22
|
-
# Silence console output
|
23
|
-
@output = ''
|
24
|
-
STDOUT.stub(:write) { |*args| @output.<<(*args) }
|
25
|
-
|
26
22
|
SCSSLint::Config.stub(:load)
|
27
23
|
.with(SCSSLint::Config::DEFAULT_FILE, merge_with_default: false)
|
28
24
|
.and_return(config)
|
@@ -32,9 +28,12 @@ describe SCSSLint::CLI do
|
|
32
28
|
end
|
33
29
|
|
34
30
|
describe '#run' do
|
35
|
-
let(:files)
|
36
|
-
let(:flags)
|
37
|
-
|
31
|
+
let(:files) { ['file1.scss', 'file2.scss'] }
|
32
|
+
let(:flags) { [] }
|
33
|
+
let(:io) { StringIO.new }
|
34
|
+
let(:output) { io.string }
|
35
|
+
let(:logger) { SCSSLint::Logger.new(io) }
|
36
|
+
subject { SCSSLint::CLI.new(logger) }
|
38
37
|
|
39
38
|
before do
|
40
39
|
SCSSLint::FileFinder.any_instance.stub(:find).and_return(files)
|
@@ -47,6 +46,59 @@ describe SCSSLint::CLI do
|
|
47
46
|
# Keep running tests
|
48
47
|
end
|
49
48
|
|
49
|
+
context 'when passed the --color flag' do
|
50
|
+
let(:flags) { ['--color'] }
|
51
|
+
|
52
|
+
it 'sets the logger to output in color' do
|
53
|
+
safe_run
|
54
|
+
logger.color_enabled.should == true
|
55
|
+
end
|
56
|
+
|
57
|
+
context 'and the output stream is not a TTY' do
|
58
|
+
before do
|
59
|
+
io.stub(:tty?).and_return(false)
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'sets the logger to output in color' do
|
63
|
+
safe_run
|
64
|
+
logger.color_enabled.should == true
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
context 'when passed the --no-color flag' do
|
70
|
+
let(:flags) { ['--no-color'] }
|
71
|
+
|
72
|
+
it 'sets the logger to not output in color' do
|
73
|
+
safe_run
|
74
|
+
logger.color_enabled.should == false
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
context 'when --[no-]color flag is not specified' do
|
79
|
+
before do
|
80
|
+
io.stub(:tty?).and_return(tty)
|
81
|
+
end
|
82
|
+
|
83
|
+
context 'and the output stream is a TTY' do
|
84
|
+
let(:tty) { true }
|
85
|
+
|
86
|
+
it 'sets the logger to output in color' do
|
87
|
+
safe_run
|
88
|
+
logger.color_enabled.should == true
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
context 'and the output stream is not a TTY' do
|
93
|
+
let(:tty) { false }
|
94
|
+
|
95
|
+
it 'sets the logger to not output in color' do
|
96
|
+
safe_run
|
97
|
+
logger.color_enabled.should == false
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
50
102
|
context 'when there are no lints' do
|
51
103
|
before do
|
52
104
|
SCSSLint::Runner.any_instance.stub(:lints).and_return([])
|
@@ -58,7 +110,7 @@ describe SCSSLint::CLI do
|
|
58
110
|
|
59
111
|
it 'outputs nothing' do
|
60
112
|
safe_run
|
61
|
-
|
113
|
+
output.should be_empty
|
62
114
|
end
|
63
115
|
end
|
64
116
|
|
@@ -81,7 +133,7 @@ describe SCSSLint::CLI do
|
|
81
133
|
|
82
134
|
it 'outputs the warnings' do
|
83
135
|
safe_run
|
84
|
-
|
136
|
+
output.should include 'Some description'
|
85
137
|
end
|
86
138
|
end
|
87
139
|
|
@@ -104,7 +156,7 @@ describe SCSSLint::CLI do
|
|
104
156
|
|
105
157
|
it 'outputs the errors' do
|
106
158
|
safe_run
|
107
|
-
|
159
|
+
output.should include 'Some description'
|
108
160
|
end
|
109
161
|
end
|
110
162
|
|
@@ -125,17 +177,17 @@ describe SCSSLint::CLI do
|
|
125
177
|
|
126
178
|
it 'outputs the error message' do
|
127
179
|
safe_run
|
128
|
-
|
180
|
+
output.should include message
|
129
181
|
end
|
130
182
|
|
131
183
|
it 'outputs the backtrace' do
|
132
184
|
safe_run
|
133
|
-
|
185
|
+
output.should include backtrace.join("\n")
|
134
186
|
end
|
135
187
|
|
136
188
|
it 'outputs a link to the issue tracker' do
|
137
189
|
safe_run
|
138
|
-
|
190
|
+
output.should include SCSSLint::BUG_REPORT_URL
|
139
191
|
end
|
140
192
|
end
|
141
193
|
|
@@ -171,7 +223,7 @@ describe SCSSLint::CLI do
|
|
171
223
|
context 'when specified SCSS file globs match no files' do
|
172
224
|
before do
|
173
225
|
SCSSLint::FileFinder.any_instance.stub(:find)
|
174
|
-
|
226
|
+
.and_raise(SCSSLint::Exceptions::NoFilesError)
|
175
227
|
end
|
176
228
|
|
177
229
|
it 'exits with an appropriate status code' do
|
@@ -132,15 +132,15 @@ describe SCSSLint::Config do
|
|
132
132
|
|
133
133
|
before do
|
134
134
|
SCSSLint::LinterRegistry.stub(:linters)
|
135
|
-
|
136
|
-
|
135
|
+
.and_return([SCSSLint::Linter::SomeNamespace::FakeLinter1,
|
136
|
+
SCSSLint::Linter::SomeNamespace::FakeLinter2])
|
137
137
|
end
|
138
138
|
|
139
139
|
it 'returns the same options for all linters under that namespace' do
|
140
140
|
subject.linter_options(SCSSLint::Linter::SomeNamespace::FakeLinter1)
|
141
|
-
|
141
|
+
.should include 'enabled' => true
|
142
142
|
subject.linter_options(SCSSLint::Linter::SomeNamespace::FakeLinter2)
|
143
|
-
|
143
|
+
.should include 'enabled' => true
|
144
144
|
end
|
145
145
|
end
|
146
146
|
|
@@ -229,7 +229,27 @@ describe SCSSLint::Config do
|
|
229
229
|
|
230
230
|
it 'returns the options for the specified linter' do
|
231
231
|
config.linter_options(SCSSLint::Linter::FakeConfigLinter.new)
|
232
|
-
|
232
|
+
.should include linter_options
|
233
|
+
end
|
234
|
+
|
235
|
+
context 'when global severity is specified' do
|
236
|
+
let(:options) { super().merge('severity' => 'some-severity') }
|
237
|
+
|
238
|
+
context 'and linter severity is not specified' do
|
239
|
+
it 'returns the global severity' do
|
240
|
+
config.linter_options(SCSSLint::Linter::FakeConfigLinter.new)
|
241
|
+
.should include 'severity' => 'some-severity'
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
context 'and linter severity is specified' do
|
246
|
+
let(:linter_options) { super().merge('severity' => 'custom-severity') }
|
247
|
+
|
248
|
+
it 'returns the custom linter severity' do
|
249
|
+
config.linter_options(SCSSLint::Linter::FakeConfigLinter.new)
|
250
|
+
.should include 'severity' => 'custom-severity'
|
251
|
+
end
|
252
|
+
end
|
233
253
|
end
|
234
254
|
end
|
235
255
|
|
@@ -48,6 +48,16 @@ describe SCSSLint::Linter::NameFormat do
|
|
48
48
|
it { should report_lint line: 1 }
|
49
49
|
end
|
50
50
|
|
51
|
+
context 'when a function contains variables with capital letters' do
|
52
|
+
let(:scss) { <<-SCSS }
|
53
|
+
p {
|
54
|
+
content: good-function($badVariable);
|
55
|
+
}
|
56
|
+
SCSS
|
57
|
+
|
58
|
+
it { should report_lint line: 2 }
|
59
|
+
end
|
60
|
+
|
51
61
|
context 'when a mixin is declared with a capital letter' do
|
52
62
|
let(:scss) { <<-SCSS }
|
53
63
|
@mixin badMixin() {
|
@@ -364,6 +364,20 @@ describe SCSSLint::Linter::PropertySortOrder do
|
|
364
364
|
SCSS
|
365
365
|
|
366
366
|
it { should_not report_lint }
|
367
|
+
|
368
|
+
context 'and there are duplicate properties' do
|
369
|
+
let(:scss) { <<-SCSS }
|
370
|
+
p {
|
371
|
+
position: absolute;
|
372
|
+
top: 0;
|
373
|
+
transition: -webkit-transform .33s;
|
374
|
+
transition: transform .33s;
|
375
|
+
background-color: #eee;
|
376
|
+
}
|
377
|
+
SCSS
|
378
|
+
|
379
|
+
it { should_not report_lint }
|
380
|
+
end
|
367
381
|
end
|
368
382
|
|
369
383
|
context 'and the properties do not match the order' do
|
@@ -377,6 +391,20 @@ describe SCSSLint::Linter::PropertySortOrder do
|
|
377
391
|
SCSS
|
378
392
|
|
379
393
|
it { should report_lint }
|
394
|
+
|
395
|
+
context 'and there are duplicate properties' do
|
396
|
+
let(:scss) { <<-SCSS }
|
397
|
+
p {
|
398
|
+
position: absolute;
|
399
|
+
transition: -webkit-transform .33s;
|
400
|
+
transition: transform .33s;
|
401
|
+
top: 0;
|
402
|
+
background-color: #eee;
|
403
|
+
}
|
404
|
+
SCSS
|
405
|
+
|
406
|
+
it { should report_lint line: 3 }
|
407
|
+
end
|
380
408
|
end
|
381
409
|
end
|
382
410
|
|
@@ -95,4 +95,14 @@ describe SCSSLint::Linter::UnnecessaryParentReference do
|
|
95
95
|
|
96
96
|
it { should_not report_lint }
|
97
97
|
end
|
98
|
+
|
99
|
+
context 'when an ampersand is used in concatentation following an ampersand' do
|
100
|
+
let(:scss) { <<-SCSS }
|
101
|
+
.icon {
|
102
|
+
& &-small {}
|
103
|
+
}
|
104
|
+
SCSS
|
105
|
+
|
106
|
+
it { should_not report_lint }
|
107
|
+
end
|
98
108
|
end
|
@@ -118,6 +118,16 @@ describe SCSSLint::Linter::VariableForProperty do
|
|
118
118
|
it { should_not report_lint }
|
119
119
|
end
|
120
120
|
|
121
|
+
context 'when property specifies `initial`' do
|
122
|
+
let(:scss) { <<-SCSS }
|
123
|
+
p {
|
124
|
+
color: initial;
|
125
|
+
}
|
126
|
+
SCSS
|
127
|
+
|
128
|
+
it { should_not report_lint }
|
129
|
+
end
|
130
|
+
|
121
131
|
context 'when property specifies `transparent`' do
|
122
132
|
let(:scss) { <<-SCSS }
|
123
133
|
p {
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe SCSSLint::Logger do
|
4
|
+
let(:io) { StringIO.new }
|
5
|
+
let(:logger) { described_class.new(io) }
|
6
|
+
|
7
|
+
describe '#color_enabled' do
|
8
|
+
subject { io.string }
|
9
|
+
|
10
|
+
before do
|
11
|
+
logger.color_enabled = enabled
|
12
|
+
logger.success('Success!')
|
13
|
+
end
|
14
|
+
|
15
|
+
context 'when color is enabled' do
|
16
|
+
let(:enabled) { true }
|
17
|
+
|
18
|
+
it { should include '32' }
|
19
|
+
end
|
20
|
+
|
21
|
+
context 'when color is disabled' do
|
22
|
+
let(:enabled) { false }
|
23
|
+
|
24
|
+
it { should_not include '32' }
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -30,5 +30,23 @@ describe SCSSLint::Options do
|
|
30
30
|
expect { subject }.to raise_error SCSSLint::Exceptions::InvalidCLIOption
|
31
31
|
end
|
32
32
|
end
|
33
|
+
|
34
|
+
context 'color' do
|
35
|
+
describe 'manually on' do
|
36
|
+
let(:args) { ['--color'] }
|
37
|
+
|
38
|
+
it 'sets the `color` option to true' do
|
39
|
+
subject.should include color: true
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe 'manually off' do
|
44
|
+
let(:args) { ['--no-color'] }
|
45
|
+
|
46
|
+
it 'sets the `color option to false' do
|
47
|
+
subject.should include color: false
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
33
51
|
end
|
34
52
|
end
|
@@ -13,7 +13,7 @@ describe SCSSLint::Plugins::LinterDir do
|
|
13
13
|
describe '#load' do
|
14
14
|
it 'requires each file in the plugin directory' do
|
15
15
|
subject.should_receive(:require)
|
16
|
-
|
16
|
+
.with(File.join(plugin_directory, 'linter_plugin.rb')).once
|
17
17
|
|
18
18
|
subject.load
|
19
19
|
end
|
@@ -2,7 +2,7 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe SCSSLint::Reporter::ConfigReporter do
|
4
4
|
subject { YAML.load(result) }
|
5
|
-
let(:result) { described_class.new(lints, []).report_lints }
|
5
|
+
let(:result) { described_class.new(lints, [], nil).report_lints }
|
6
6
|
|
7
7
|
describe '#report_lints' do
|
8
8
|
context 'when there are no lints' do
|
@@ -1,7 +1,8 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe SCSSLint::Reporter::DefaultReporter do
|
4
|
-
|
4
|
+
let(:logger) { SCSSLint::Logger.new($stdout) }
|
5
|
+
subject { SCSSLint::Reporter::DefaultReporter.new(lints, [], logger) }
|
5
6
|
|
6
7
|
describe '#report_lints' do
|
7
8
|
context 'when there are no lints' do
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe SCSSLint::Reporter::JSONReporter do
|
4
|
-
subject { SCSSLint::Reporter::JSONReporter.new(lints, []) }
|
4
|
+
subject { SCSSLint::Reporter::JSONReporter.new(lints, [], nil) }
|
5
5
|
|
6
6
|
describe '#report_lints' do
|
7
7
|
let(:json) { JSON.parse(subject.report_lints) }
|
@@ -56,22 +56,22 @@ describe SCSSLint::Reporter::JSONReporter do
|
|
56
56
|
|
57
57
|
it 'marks each issue with a line number' do
|
58
58
|
json.values.flat_map { |issues| issues.map { |issue| issue['line'] } }
|
59
|
-
|
59
|
+
.should =~ locations.map(&:line)
|
60
60
|
end
|
61
61
|
|
62
62
|
it 'marks each issue with a column number' do
|
63
63
|
json.values.flat_map { |issues| issues.map { |issue| issue['column'] } }
|
64
|
-
|
64
|
+
.should =~ locations.map(&:column)
|
65
65
|
end
|
66
66
|
|
67
67
|
it 'marks each issue with a length' do
|
68
68
|
json.values.flat_map { |issues| issues.map { |issue| issue['length'] } }
|
69
|
-
|
69
|
+
.should =~ locations.map(&:length)
|
70
70
|
end
|
71
71
|
|
72
72
|
it 'marks each issue with a reason containing the lint description' do
|
73
73
|
json.values.flat_map { |issues| issues.map { |issue| issue['reason'] } }
|
74
|
-
|
74
|
+
.should =~ descriptions
|
75
75
|
end
|
76
76
|
|
77
77
|
context 'when lints are warnings' do
|