scss_lint 0.39.0 → 0.40.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 +15 -0
- data/lib/scss_lint.rb +1 -0
- data/lib/scss_lint/cli.rb +10 -3
- data/lib/scss_lint/config.rb +54 -2
- data/lib/scss_lint/control_comment_processor.rb +15 -6
- data/lib/scss_lint/exceptions.rb +3 -0
- data/lib/scss_lint/linter/color_variable.rb +7 -0
- data/lib/scss_lint/linter/else_placement.rb +1 -0
- data/lib/scss_lint/linter/extend_directive.rb +11 -0
- data/lib/scss_lint/linter/final_newline.rb +1 -0
- data/lib/scss_lint/linter/name_format.rb +1 -12
- data/lib/scss_lint/linter/nesting_depth.rb +22 -1
- data/lib/scss_lint/linter/property_sort_order.rb +8 -0
- data/lib/scss_lint/linter/property_units.rb +21 -3
- data/lib/scss_lint/linter/space_after_variable_name.rb +18 -0
- data/lib/scss_lint/linter/space_between_parens.rb +1 -0
- data/lib/scss_lint/linter/trailing_whitespace.rb +15 -0
- data/lib/scss_lint/plugins.rb +33 -0
- data/lib/scss_lint/plugins/linter_dir.rb +24 -0
- data/lib/scss_lint/plugins/linter_gem.rb +51 -0
- data/lib/scss_lint/version.rb +1 -1
- data/spec/scss_lint/config_spec.rb +64 -0
- data/spec/scss_lint/fixtures/plugins/linter_plugin.rb +7 -0
- data/spec/scss_lint/linter/color_variable_spec.rb +12 -0
- data/spec/scss_lint/linter/else_placement_spec.rb +34 -0
- data/spec/scss_lint/linter/extend_directive_spec.rb +73 -0
- data/spec/scss_lint/linter/nesting_depth_spec.rb +72 -0
- data/spec/scss_lint/linter/property_sort_order_spec.rb +32 -0
- data/spec/scss_lint/linter/property_units_spec.rb +40 -0
- data/spec/scss_lint/linter/space_after_variable_name_spec.rb +13 -0
- data/spec/scss_lint/linter/trailing_whitespace_spec.rb +33 -0
- data/spec/scss_lint/linter_spec.rb +15 -2
- data/spec/scss_lint/plugins/linter_dir_spec.rb +21 -0
- data/spec/scss_lint/plugins/linter_gem_spec.rb +60 -0
- data/spec/scss_lint/plugins_spec.rb +53 -0
- data/spec/spec_helper.rb +10 -0
- metadata +26 -5
@@ -0,0 +1,33 @@
|
|
1
|
+
require_relative 'plugins/linter_gem'
|
2
|
+
require_relative 'plugins/linter_dir'
|
3
|
+
|
4
|
+
module SCSSLint
|
5
|
+
# Loads external linter plugins.
|
6
|
+
class Plugins
|
7
|
+
def initialize(config)
|
8
|
+
@config = config
|
9
|
+
end
|
10
|
+
|
11
|
+
def load
|
12
|
+
all.map(&:load)
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def all
|
18
|
+
[plugin_gems, plugin_directories].flatten
|
19
|
+
end
|
20
|
+
|
21
|
+
def plugin_gems
|
22
|
+
Array(@config['plugin_gems']).map do |gem_name|
|
23
|
+
LinterGem.new(gem_name)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def plugin_directories
|
28
|
+
Array(@config['plugin_directories']).map do |directory|
|
29
|
+
LinterDir.new(directory)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module SCSSLint
|
2
|
+
class Plugins
|
3
|
+
# Load ruby files from linter plugin directories.
|
4
|
+
class LinterDir
|
5
|
+
attr_reader :config
|
6
|
+
|
7
|
+
def initialize(dir)
|
8
|
+
@dir = dir
|
9
|
+
@config = SCSSLint::Config.new({}) # Will always be empty
|
10
|
+
end
|
11
|
+
|
12
|
+
def load
|
13
|
+
ruby_files.each { |file| require file }
|
14
|
+
self
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def ruby_files
|
20
|
+
Dir.glob(File.expand_path(File.join(@dir, '**', '*.rb')))
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module SCSSLint
|
2
|
+
class Plugins
|
3
|
+
# Load linter plugin gems
|
4
|
+
class LinterGem
|
5
|
+
attr_reader :config
|
6
|
+
|
7
|
+
def initialize(name)
|
8
|
+
@name = name
|
9
|
+
end
|
10
|
+
|
11
|
+
def load
|
12
|
+
require @name
|
13
|
+
@config = plugin_config
|
14
|
+
self
|
15
|
+
rescue Gem::LoadError, LoadError
|
16
|
+
raise SCSSLint::Exceptions::PluginGemLoadError,
|
17
|
+
"Unable to load linter plugin gem '#{@name}'. Try running " \
|
18
|
+
"`gem install #{@name}`, or adding it to your Gemfile and " \
|
19
|
+
'running `bundle install`. See the `plugin_gems` section of ' \
|
20
|
+
'your .scss-lint.yml file to add/remove gem plugins.'
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
# Returns the {SCSSLint::Config} for this plugin.
|
26
|
+
#
|
27
|
+
# This is intended to be merged with the configuration that loaded this
|
28
|
+
# plugin.
|
29
|
+
#
|
30
|
+
# @return [SCSSLint::Config]
|
31
|
+
def plugin_config
|
32
|
+
file = plugin_config_file
|
33
|
+
|
34
|
+
if File.exist?(file)
|
35
|
+
Config.load(file, merge_with_default: false)
|
36
|
+
else
|
37
|
+
Config.new({})
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# Path of the configuration file to attempt to load for this plugin.
|
42
|
+
#
|
43
|
+
# @return [String]
|
44
|
+
def plugin_config_file
|
45
|
+
gem_specification = Gem::Specification.find_by_name(@name)
|
46
|
+
|
47
|
+
File.join(gem_specification.gem_dir, Config::FILE_NAME)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
data/lib/scss_lint/version.rb
CHANGED
@@ -143,6 +143,70 @@ describe SCSSLint::Config do
|
|
143
143
|
.should eq('enabled' => true)
|
144
144
|
end
|
145
145
|
end
|
146
|
+
|
147
|
+
context 'when configuration loads a plugin configuration' do
|
148
|
+
let!(:plugins_manager) { SCSSLint::Plugins.new(double) }
|
149
|
+
|
150
|
+
before do
|
151
|
+
SCSSLint::Plugins.stub(:new).and_return(plugins_manager)
|
152
|
+
|
153
|
+
plugins_manager.stub(:load).and_return([
|
154
|
+
double(config: SCSSLint::Config.new(
|
155
|
+
'linters' => {
|
156
|
+
'FakeConfigLinter' => plugin_linter_config,
|
157
|
+
}
|
158
|
+
))
|
159
|
+
])
|
160
|
+
end
|
161
|
+
|
162
|
+
context 'and the plugin configuration does not set the value' do
|
163
|
+
let(:plugin_linter_config) { {} }
|
164
|
+
|
165
|
+
context 'and the local configuration sets the value' do
|
166
|
+
let(:config_file) { <<-FILE }
|
167
|
+
linters:
|
168
|
+
FakeConfigLinter:
|
169
|
+
list: [4, 5, 6]
|
170
|
+
FILE
|
171
|
+
|
172
|
+
it 'uses the local configuration value' do
|
173
|
+
subject.options['linters']['FakeConfigLinter']['list'].should == [4, 5, 6]
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
context 'and the local configuration does not set the value' do
|
178
|
+
let(:config_file) { '' }
|
179
|
+
|
180
|
+
it 'uses the default configuration value' do
|
181
|
+
subject.options['linters']['FakeConfigLinter']['list'].should == [1, 2, 3]
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
context 'and the plugin configuration sets the value' do
|
187
|
+
let(:plugin_linter_config) { { 'list' => [2, 3, 4] } }
|
188
|
+
|
189
|
+
context 'and the local configuration sets the value' do
|
190
|
+
let(:config_file) { <<-FILE }
|
191
|
+
linters:
|
192
|
+
FakeConfigLinter:
|
193
|
+
list: [4, 5, 6]
|
194
|
+
FILE
|
195
|
+
|
196
|
+
it 'uses the local configuration value' do
|
197
|
+
subject.options['linters']['FakeConfigLinter']['list'].should == [4, 5, 6]
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
context 'and the local configuration does not set the value' do
|
202
|
+
let(:config_file) { '' }
|
203
|
+
|
204
|
+
it 'uses the plugin configuration value' do
|
205
|
+
subject.options['linters']['FakeConfigLinter']['list'].should == [2, 3, 4]
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
209
|
+
end
|
146
210
|
end
|
147
211
|
|
148
212
|
describe '#linter_options' do
|
@@ -152,4 +152,16 @@ describe SCSSLint::Linter::ColorVariable do
|
|
152
152
|
|
153
153
|
it { should_not report_lint }
|
154
154
|
end
|
155
|
+
|
156
|
+
context 'when a variable is interpolated in a multiline comment' do
|
157
|
+
let(:scss) { <<-SCSS }
|
158
|
+
$a: 0;
|
159
|
+
|
160
|
+
/*!
|
161
|
+
* test \#{a}
|
162
|
+
*/
|
163
|
+
SCSS
|
164
|
+
|
165
|
+
it { should_not report_lint }
|
166
|
+
end
|
155
167
|
end
|
@@ -75,6 +75,40 @@ describe SCSSLint::Linter::ElsePlacement do
|
|
75
75
|
it { should_not report_lint }
|
76
76
|
end
|
77
77
|
|
78
|
+
context 'when @else nested in an @if is on new line' do
|
79
|
+
let(:scss) { <<-SCSS }
|
80
|
+
@if $condition {
|
81
|
+
@if $condition2 {
|
82
|
+
$var: 2;
|
83
|
+
}
|
84
|
+
@else {
|
85
|
+
$var: 0;
|
86
|
+
}
|
87
|
+
} @else {
|
88
|
+
$var: 1;
|
89
|
+
}
|
90
|
+
SCSS
|
91
|
+
|
92
|
+
it { should report_lint line: 5 }
|
93
|
+
end
|
94
|
+
|
95
|
+
context 'when @else nested in an @else is on new line' do
|
96
|
+
let(:scss) { <<-SCSS }
|
97
|
+
@if $condition {
|
98
|
+
$var: 1;
|
99
|
+
} @else {
|
100
|
+
@if $condition2 {
|
101
|
+
$var: 2;
|
102
|
+
}
|
103
|
+
@else {
|
104
|
+
$var: 0;
|
105
|
+
}
|
106
|
+
}
|
107
|
+
SCSS
|
108
|
+
|
109
|
+
it { should report_lint line: 7 }
|
110
|
+
end
|
111
|
+
|
78
112
|
context 'when placement of @else on a new line is preferred' do
|
79
113
|
let(:linter_config) { { 'style' => 'new_line' } }
|
80
114
|
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe SCSSLint::Linter::ExtendDirective do
|
4
|
+
context 'when extending with a class' do
|
5
|
+
let(:scss) { <<-SCSS }
|
6
|
+
p {
|
7
|
+
@extend .error;
|
8
|
+
}
|
9
|
+
SCSS
|
10
|
+
|
11
|
+
it { should report_lint line: 2 }
|
12
|
+
end
|
13
|
+
|
14
|
+
context 'when extending with a type' do
|
15
|
+
let(:scss) { <<-SCSS }
|
16
|
+
p {
|
17
|
+
@extend span;
|
18
|
+
}
|
19
|
+
SCSS
|
20
|
+
|
21
|
+
it { should report_lint line: 2 }
|
22
|
+
end
|
23
|
+
|
24
|
+
context 'when extending with an id' do
|
25
|
+
let(:scss) { <<-SCSS }
|
26
|
+
p {
|
27
|
+
@extend #some-identifer;
|
28
|
+
}
|
29
|
+
SCSS
|
30
|
+
|
31
|
+
it { should report_lint line: 2 }
|
32
|
+
end
|
33
|
+
|
34
|
+
context 'when extending with a placeholder' do
|
35
|
+
let(:scss) { <<-SCSS }
|
36
|
+
p {
|
37
|
+
@extend %placeholder;
|
38
|
+
}
|
39
|
+
SCSS
|
40
|
+
|
41
|
+
it { should report_lint line: 2 }
|
42
|
+
end
|
43
|
+
|
44
|
+
context 'when extending with a selector whose prefix is not a placeholder' do
|
45
|
+
let(:scss) { <<-SCSS }
|
46
|
+
p {
|
47
|
+
@extend .blah-\#{$dynamically_generated_name};
|
48
|
+
}
|
49
|
+
SCSS
|
50
|
+
|
51
|
+
it { should report_lint line: 2 }
|
52
|
+
end
|
53
|
+
|
54
|
+
context 'when extending with a selector whose prefix is dynamic' do
|
55
|
+
let(:scss) { <<-SCSS }
|
56
|
+
p {
|
57
|
+
@extend \#{$dynamically_generated_placeholder_name};
|
58
|
+
}
|
59
|
+
SCSS
|
60
|
+
|
61
|
+
it { should report_lint line: 2 }
|
62
|
+
end
|
63
|
+
|
64
|
+
context 'when not using extend' do
|
65
|
+
let(:scss) { <<-SCSS }
|
66
|
+
p {
|
67
|
+
@include mixin;
|
68
|
+
}
|
69
|
+
SCSS
|
70
|
+
|
71
|
+
it { should_not report_lint }
|
72
|
+
end
|
73
|
+
end
|
@@ -111,4 +111,76 @@ describe SCSSLint::Linter::NestingDepth do
|
|
111
111
|
it { should_not report_lint }
|
112
112
|
end
|
113
113
|
end
|
114
|
+
|
115
|
+
context 'nesting parent selectors' do
|
116
|
+
let(:scss) { <<-SCSS }
|
117
|
+
.one {
|
118
|
+
.two {
|
119
|
+
.three {
|
120
|
+
&:hover,
|
121
|
+
&-suffix {
|
122
|
+
.five {
|
123
|
+
background: #f00;
|
124
|
+
}
|
125
|
+
}
|
126
|
+
}
|
127
|
+
|
128
|
+
.another-three { }
|
129
|
+
}
|
130
|
+
}
|
131
|
+
SCSS
|
132
|
+
|
133
|
+
context 'when parent selectors are ignored' do
|
134
|
+
let(:linter_config) { { 'ignore_parent_selectors' => true } }
|
135
|
+
|
136
|
+
context 'and max depth is set to 2' do
|
137
|
+
let(:linter_config) { super().merge('max_depth' => 2) }
|
138
|
+
|
139
|
+
it { should report_lint line: 3 }
|
140
|
+
it { should report_lint line: 12 }
|
141
|
+
it { should_not report_lint line: 4 }
|
142
|
+
it { should_not report_lint line: 6 }
|
143
|
+
end
|
144
|
+
|
145
|
+
context 'and max depth is set to 3' do
|
146
|
+
let(:linter_config) { super().merge('max_depth' => 3) }
|
147
|
+
|
148
|
+
it { should_not report_lint line: 4 }
|
149
|
+
it { should_not report_lint line: 5 }
|
150
|
+
it { should report_lint line: 6 }
|
151
|
+
end
|
152
|
+
|
153
|
+
context 'and max depth is set to 4' do
|
154
|
+
let(:linter_config) { super().merge('max_depth' => 4) }
|
155
|
+
|
156
|
+
it { should_not report_lint }
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
context 'when not ignoring parent selectors' do
|
161
|
+
let(:linter_config) { { 'ignore_parent_selectors' => false } }
|
162
|
+
|
163
|
+
context 'and max depth is set to 2' do
|
164
|
+
let(:linter_config) { super().merge('max_depth' => 2) }
|
165
|
+
|
166
|
+
it { should report_lint line: 3 }
|
167
|
+
it { should report_lint line: 12 }
|
168
|
+
it { should_not report_lint line: 4 }
|
169
|
+
it { should_not report_lint line: 6 }
|
170
|
+
end
|
171
|
+
|
172
|
+
context 'and max depth is set to 3' do
|
173
|
+
let(:linter_config) { super().merge('max_depth' => 3) }
|
174
|
+
|
175
|
+
it { should report_lint line: 4 }
|
176
|
+
it { should_not report_lint line: 12 }
|
177
|
+
end
|
178
|
+
|
179
|
+
context 'and max depth is set to 4' do
|
180
|
+
let(:linter_config) { super().merge('max_depth' => 4) }
|
181
|
+
|
182
|
+
it { should report_lint line: 6 }
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
114
186
|
end
|
@@ -316,6 +316,38 @@ describe SCSSLint::Linter::PropertySortOrder do
|
|
316
316
|
it { should report_lint }
|
317
317
|
end
|
318
318
|
end
|
319
|
+
|
320
|
+
context 'and there are properties not specified in the explicit ordering at the end' do
|
321
|
+
let(:linter_config) do
|
322
|
+
super().merge('order' => %w[position top bottom padding width background])
|
323
|
+
end
|
324
|
+
|
325
|
+
let(:scss) { <<-SCSS }
|
326
|
+
p {
|
327
|
+
position: absolute;
|
328
|
+
top: 0;
|
329
|
+
bottom: 0;
|
330
|
+
padding: 20px;
|
331
|
+
width: $drawer-narrow-width;
|
332
|
+
background: $drawer-bg-color;
|
333
|
+
overflow-y: auto;
|
334
|
+
box-sizing: border-box;
|
335
|
+
transition: left .25s ease-out;
|
336
|
+
}
|
337
|
+
SCSS
|
338
|
+
|
339
|
+
context 'and the ignore_unspecified option is enabled' do
|
340
|
+
let(:linter_config) { super().merge('ignore_unspecified' => true) }
|
341
|
+
|
342
|
+
it { should_not report_lint }
|
343
|
+
end
|
344
|
+
|
345
|
+
context 'and the ignore_unspecified option is disabled' do
|
346
|
+
let(:linter_config) { super().merge('ignore_unspecified' => false) }
|
347
|
+
|
348
|
+
it { should_not report_lint }
|
349
|
+
end
|
350
|
+
end
|
319
351
|
end
|
320
352
|
|
321
353
|
context 'when sort order is set to a preset order' do
|