scss_lint 0.38.0 → 0.39.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: cb1cc64b17da57ae25e2562d08665b6bb4712a55
4
- data.tar.gz: d66077cdb7b9abcc5b4f69bf03035d08851726b0
3
+ metadata.gz: 246cc4b3c9ca9fe6b52f8ef4edd262694b701809
4
+ data.tar.gz: 18a0b888b01b4ddc391a17719b3853a77075ff92
5
5
  SHA512:
6
- metadata.gz: 9ea54c1649b43fb5dc69e26623c6b7c8be57e9487b309af18160cdbc7afae8104175566bb571b24e923f59091df2d7cf9b751c1a852b7cce3729882295d5a941
7
- data.tar.gz: a36364675cff2a840104d1e31262b2db9b3d0f35e14d77b04979f15ef1d4c52eafadac1ccdcf8960994c05a9a121a4c5f65f704922c13f244b0e38475408a7d2
6
+ metadata.gz: 49174f90f307f91898c0c409b4e8e711f9b0d99088005f5e1e979a1663b9be89c953a2a2431497c06b224a48d3e9dd7113392ac891c6bba6e08f9b0c67a2263b
7
+ data.tar.gz: 14098a3c8478fc0a65c222052054f3190a623a0bfc85fc4b107bb15b4cc5d802a1f95f341413a0dafe9f06d8fef74f6a9e845e1587c0ef1e317034c39dac2d15
data/config/default.yml CHANGED
@@ -8,6 +8,10 @@ linters:
8
8
  space_before_bang: true
9
9
  space_after_bang: false
10
10
 
11
+ BemDepth:
12
+ enabled: false
13
+ max_elements: 1
14
+
11
15
  BorderZero:
12
16
  enabled: true
13
17
  convention: zero # or `none`
@@ -108,8 +112,7 @@ linters:
108
112
  'ms', 's', # Duration
109
113
  'Hz', 'kHz', # Frequency
110
114
  'dpi', 'dpcm', 'dppx', # Resolution
111
- '%', # Other
112
- ]
115
+ '%'] # Other
113
116
  properties: {}
114
117
 
115
118
  PropertySortOrder:
data/lib/scss_lint/cli.rb CHANGED
@@ -26,7 +26,7 @@ module SCSSLint
26
26
  options = SCSSLint::Options.new.parse(args)
27
27
  act_on_options(options)
28
28
  rescue => ex
29
- handle_runtime_exception(ex)
29
+ handle_runtime_exception(ex, options)
30
30
  end
31
31
 
32
32
  private
@@ -63,7 +63,7 @@ module SCSSLint
63
63
  end
64
64
  end
65
65
 
66
- def handle_runtime_exception(exception) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/LineLength, Metrics/MethodLength
66
+ def handle_runtime_exception(exception, options) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/LineLength, Metrics/MethodLength
67
67
  case exception
68
68
  when SCSSLint::Exceptions::InvalidCLIOption
69
69
  puts exception.message
@@ -88,26 +88,42 @@ module SCSSLint
88
88
  puts exception.message
89
89
  halt :usage
90
90
  else
91
+ config_file = relevant_configuration_file(options) if options
92
+
91
93
  puts exception.message
92
94
  puts exception.backtrace
93
95
  puts 'Report this bug at '.color(:yellow) + BUG_REPORT_URL.color(:cyan)
96
+ puts
97
+ puts 'To help fix this issue, please include:'.color(:green)
98
+ puts '- The above stack trace'
99
+ puts "- SCSS-Lint version: #{SCSSLint::VERSION.color(:cyan)}"
100
+ puts "- Sass version: #{Gem.loaded_specs['sass'].version.to_s.color(:cyan)}"
101
+ puts "- Ruby version: #{RUBY_VERSION.color(:cyan)}"
102
+ puts "- Contents of #{File.expand_path(config_file).color(:cyan)}" if config_file
94
103
  halt :software
95
104
  end
96
105
  end
97
106
 
98
107
  def setup_configuration(options)
99
- config =
100
- if options[:config_file]
101
- Config.load(options[:config_file])
102
- elsif File.exist?(Config::FILE_NAME)
103
- Config.load(Config::FILE_NAME)
104
- else
105
- Config.default
106
- end
107
-
108
+ config_file = relevant_configuration_file(options)
109
+ config = config_file ? Config.load(config_file) : Config.default
108
110
  merge_options_with_config(options, config)
109
111
  end
110
112
 
113
+ # Return the path of the configuration file that should be loaded.
114
+ #
115
+ # @param options [Hash]
116
+ # @return [String]
117
+ def relevant_configuration_file(options)
118
+ if options[:config_file]
119
+ options[:config_file]
120
+ elsif File.exist?(Config::FILE_NAME)
121
+ Config::FILE_NAME
122
+ elsif File.exist?(Config.user_file)
123
+ Config.user_file
124
+ end
125
+ end
126
+
111
127
  # @param options [Hash]
112
128
  # @param config [Config]
113
129
  # @return [Config]
@@ -25,6 +25,14 @@ module SCSSLint
25
25
  Config.new(config_options)
26
26
  end
27
27
 
28
+ # Returns the location of the user-wide scss-lint configuration.
29
+ #
30
+ # This needs to be a method instead of a constant so that we can change
31
+ # the user's home directory in tests.
32
+ def user_file
33
+ File.join(Dir.home, FILE_NAME)
34
+ end
35
+
28
36
  def linter_name(linter)
29
37
  linter = linter.is_a?(Class) ? linter : linter.class
30
38
  linter.name.split('::')[2..-1].join('::')
@@ -0,0 +1,32 @@
1
+ module SCSSLint
2
+ # Checks for BEM selectors with more elements than a specified maximum number.
3
+ class Linter::BemDepth < Linter
4
+ include LinterRegistry
5
+
6
+ def visit_root(_node)
7
+ @max_elements = config['max_elements']
8
+ yield # Continue linting children
9
+ end
10
+
11
+ def visit_class(klass)
12
+ check_depth(klass, 'selectors')
13
+ end
14
+
15
+ def visit_placeholder(placeholder)
16
+ check_depth(placeholder, 'placeholders')
17
+ end
18
+
19
+ private
20
+
21
+ def check_depth(node, plural_type)
22
+ selector = node.name
23
+ parts = selector.split('__')
24
+ num_elements = (parts[1..-1] || []).length
25
+ return if num_elements <= @max_elements
26
+
27
+ found_elements = pluralize(@max_elements, 'element')
28
+ add_lint(node, "BEM #{plural_type} should have no more than #{found_elements}, " \
29
+ "but `#{selector}` has #{num_elements}")
30
+ end
31
+ end
32
+ end
@@ -20,6 +20,8 @@ module SCSSLint
20
20
  private
21
21
 
22
22
  def add_color_lint(node, original)
23
+ return if in_map?(node)
24
+
23
25
  hex_form = Sass::Script::Value::Color.new(color_keyword_to_code(original)).tap do |color|
24
26
  color.options = {} # `inspect` requires options to be set
25
27
  end.inspect
@@ -28,5 +30,9 @@ module SCSSLint
28
30
  "Color `#{original}` should be written in hexadecimal form " \
29
31
  "as `#{hex_form}`")
30
32
  end
33
+
34
+ def in_map?(node)
35
+ node_ancestor(node, 2).is_a?(Sass::Script::Tree::MapLiteral)
36
+ end
31
37
  end
32
38
  end
@@ -40,17 +40,28 @@ module SCSSLint
40
40
  (next_start_line = following_node.line)
41
41
 
42
42
  # Special case: ignore comments immediately after a closing brace
43
- line = engine.lines[next_start_line - 1].strip
44
- return if following_node.is_a?(Sass::Tree::CommentNode) &&
45
- line =~ %r{\s*\}?\s*/(/|\*)}
43
+ return if comment_after_closing_brace?(following_node, next_start_line)
44
+
45
+ # Special case: ignore `@else` nodes which are children of the parent `@if`
46
+ return if else_node?(following_node)
46
47
 
47
48
  # Otherwise check if line before the next node's starting line is blank
48
- line = engine.lines[next_start_line - 2].strip
49
- return if line.empty?
49
+ return if next_line_blank?(next_start_line)
50
50
 
51
51
  add_lint(next_start_line - 1, MESSAGE_FORMAT % [type, 'followed'])
52
52
  end
53
53
 
54
+ def comment_after_closing_brace?(node, next_start_line)
55
+ line = engine.lines[next_start_line - 1].strip
56
+
57
+ node.is_a?(Sass::Tree::CommentNode) &&
58
+ line =~ %r{\s*\}?\s*/(/|\*)}
59
+ end
60
+
61
+ def next_line_blank?(next_start_line)
62
+ engine.lines[next_start_line - 2].strip.empty?
63
+ end
64
+
54
65
  # In cases where the previous node is not a block declaration, we won't
55
66
  # have run any checks against it, so we need to check here if the previous
56
67
  # line is an empty line
@@ -56,10 +56,16 @@ module SCSSLint
56
56
  end
57
57
  end
58
58
 
59
- # Deal with `else` statements
60
- def visit_if(node, &block)
61
- check_and_visit_children(node, &block)
62
- visit(node.else) if node.else
59
+ # Deal with `else` statements, which require special care since they are
60
+ # considered children of `if` statements.
61
+ def visit_if(node)
62
+ check_indentation(node)
63
+
64
+ if config['allow_non_nested_indentation']
65
+ yield # Continue linting else statement
66
+ else
67
+ visit(node.else) if node.else
68
+ end
63
69
  end
64
70
 
65
71
  # Need to define this explicitly since @at-root directives can contain
@@ -89,6 +95,12 @@ module SCSSLint
89
95
  end
90
96
  end
91
97
 
98
+ def visit_import(node)
99
+ prev = previous_node(node)
100
+ return if prev.is_a?(Sass::Tree::ImportNode) && source_from_range(prev.source_range) =~ /,$/
101
+ check_indentation(node)
102
+ end
103
+
92
104
  # Define node types that increase indentation level
93
105
  alias_method :visit_directive, :check_and_visit_children
94
106
  alias_method :visit_each, :check_and_visit_children
@@ -107,7 +119,6 @@ module SCSSLint
107
119
  alias_method :visit_content, :check_indentation
108
120
  alias_method :visit_cssimport, :check_indentation
109
121
  alias_method :visit_extend, :check_indentation
110
- alias_method :visit_import, :check_indentation
111
122
  alias_method :visit_return, :check_indentation
112
123
  alias_method :visit_variable, :check_indentation
113
124
  alias_method :visit_warn, :check_indentation
@@ -157,7 +168,7 @@ module SCSSLint
157
168
  return true
158
169
  end
159
170
  elsif !one_shift_greater_than_parent?(node, actual_indent)
160
- parent_indent = node_indent(node.node_parent).length
171
+ parent_indent = node_indent(node_indent_parent(node)).length
161
172
  expected_indent = parent_indent + @indent_width
162
173
 
163
174
  add_lint(node.line,
@@ -181,7 +192,7 @@ module SCSSLint
181
192
  # @param node [Sass::Tree::Node]
182
193
  # @return [true,false]
183
194
  def one_shift_greater_than_parent?(node, actual_indent)
184
- parent_indent = node_indent(node.node_parent).length
195
+ parent_indent = node_indent(node_indent_parent(node)).length
185
196
  expected_indent = parent_indent + @indent_width
186
197
  expected_indent == actual_indent
187
198
  end
@@ -193,5 +204,16 @@ module SCSSLint
193
204
  def node_indent(node)
194
205
  engine.lines[node.line - 1][/^(\s*)/, 1]
195
206
  end
207
+
208
+ def node_indent_parent(node)
209
+ if else_node?(node)
210
+ while node.node_parent.is_a?(Sass::Tree::IfNode) &&
211
+ node.node_parent.else == node
212
+ node = node.node_parent
213
+ end
214
+ end
215
+
216
+ node.node_parent
217
+ end
196
218
  end
197
219
  end
@@ -104,7 +104,7 @@ module Sass::Tree
104
104
 
105
105
  class IfNode
106
106
  def children
107
- concat_expr_lists super, expr
107
+ concat_expr_lists super, expr, self.else
108
108
  end
109
109
  end
110
110
 
@@ -165,4 +165,15 @@ module Sass::Tree
165
165
  concat_expr_lists super, expr
166
166
  end
167
167
  end
168
+
169
+ class ImportNode
170
+ # Compares the names and values of two imports.
171
+ #
172
+ # @param other [Object] The object to compare with
173
+ # @return [Boolean] Whether or not this node and the other object
174
+ # are the same
175
+ def ==(other)
176
+ self.class == other.class && imported_filename == other.imported_filename && super
177
+ end
178
+ end
168
179
  end
@@ -35,6 +35,15 @@ module SCSSLint
35
35
  Sass::Script::Value::Color::COLOR_NAMES[string]
36
36
  end
37
37
 
38
+ # Returns whether a node is an IfNode corresponding to an @else/@else if
39
+ # statement.
40
+ #
41
+ # @param node [Sass::Tree::Node]
42
+ # @return [true,false]
43
+ def else_node?(node)
44
+ source_from_range(node.source_range).strip.start_with?('@else')
45
+ end
46
+
38
47
  # Given a selector array which is a list of strings with Sass::Script::Nodes
39
48
  # interspersed within them, return an array of strings representing those
40
49
  # selectors with the Sass::Script::Nodes removed (i.e., ignoring
@@ -1,4 +1,4 @@
1
1
  # Defines the gem version.
2
2
  module SCSSLint
3
- VERSION = '0.38.0'
3
+ VERSION = '0.39.0'
4
4
  end
@@ -2,6 +2,8 @@ require 'spec_helper'
2
2
  require 'scss_lint/cli'
3
3
 
4
4
  describe SCSSLint::CLI do
5
+ include_context 'isolated environment'
6
+
5
7
  let(:config_options) do
6
8
  {
7
9
  'linters' => {
@@ -21,7 +23,9 @@ describe SCSSLint::CLI do
21
23
  @output = ''
22
24
  STDOUT.stub(:write) { |*args| @output.<<(*args) }
23
25
 
24
- SCSSLint::Config.stub(:load).and_return(config)
26
+ SCSSLint::Config.stub(:load)
27
+ .with(SCSSLint::Config::DEFAULT_FILE, merge_with_default: false)
28
+ .and_return(config)
25
29
  SCSSLint::LinterRegistry.stub(:linters)
26
30
  .and_return([SCSSLint::Linter::FakeTestLinter1,
27
31
  SCSSLint::Linter::FakeTestLinter2])
@@ -173,5 +177,44 @@ describe SCSSLint::CLI do
173
177
  safe_run
174
178
  end
175
179
  end
180
+
181
+ context 'when a config file is specified' do
182
+ let(:flags) { ['--config', 'custom_config.yml'] }
183
+
184
+ before do
185
+ File.stub(:exist?).with('.scss-lint.yml').and_return(true)
186
+ File.stub(:exist?).with(SCSSLint::Config.user_file).and_return(true)
187
+ end
188
+
189
+ it 'loads config from the specified file' do
190
+ SCSSLint::Config.should_receive(:load).with('custom_config.yml').and_return(config)
191
+ safe_run
192
+ end
193
+ end
194
+
195
+ context 'when a config file exists in the current directory and home directory' do
196
+ before do
197
+ File.stub(:exist?).with('.scss-lint.yml').and_return(true)
198
+ File.stub(:exist?).with(SCSSLint::Config.user_file).and_return(true)
199
+ end
200
+
201
+ it 'loads config from the current directory' do
202
+ SCSSLint::Config.should_receive(:load).with('.scss-lint.yml').and_return(config)
203
+ safe_run
204
+ end
205
+ end
206
+
207
+ context 'when a config file exists only in the user home directory' do
208
+ before do
209
+ File.stub(:exist?).with('.scss-lint.yml').and_return(false)
210
+ File.stub(:exist?).with(SCSSLint::Config.user_file).and_return(true)
211
+ end
212
+
213
+ it 'loads config from the home directory' do
214
+ config_path = File.expand_path('.scss-lint.yml', Dir.home)
215
+ SCSSLint::Config.should_receive(:load).with(config_path).and_return(config)
216
+ safe_run
217
+ end
218
+ end
176
219
  end
177
220
  end
@@ -0,0 +1,117 @@
1
+ require 'spec_helper'
2
+
3
+ describe SCSSLint::Linter::BemDepth do
4
+ context 'with the default maximum number of elements' do
5
+ context 'when a selector lacks elements' do
6
+ let(:scss) { <<-SCSS }
7
+ .block {
8
+ background: #f00;
9
+ }
10
+ %block {
11
+ background: #0f0;
12
+ }
13
+ SCSS
14
+
15
+ it { should_not report_lint }
16
+ end
17
+
18
+ context 'when a selector contains one element' do
19
+ let(:scss) { <<-SCSS }
20
+ .block__element {
21
+ background: #f00;
22
+ }
23
+ %block__element {
24
+ background: #f00;
25
+ }
26
+ SCSS
27
+
28
+ it { should_not report_lint }
29
+ end
30
+
31
+ context 'when a selector contains one element with a modifier' do
32
+ let(:scss) { <<-SCSS }
33
+ .block__element--modifier {
34
+ background: #f00;
35
+ }
36
+ %block__element--modifier {
37
+ background: #f00;
38
+ }
39
+ SCSS
40
+
41
+ it { should_not report_lint }
42
+ end
43
+
44
+ context 'when a selector contains more than one element' do
45
+ let(:scss) { <<-SCSS }
46
+ .block__element__subelement {
47
+ background: #f00;
48
+ }
49
+ %block__element__subelement {
50
+ background: #f00;
51
+ }
52
+ SCSS
53
+
54
+ it { should report_lint line: 1 }
55
+ it { should report_lint line: 4 }
56
+ end
57
+
58
+ context 'when a selector contains more than one element with a modifier' do
59
+ let(:scss) { <<-SCSS }
60
+ .block__element__subelement--modifier {
61
+ background: #f00;
62
+ }
63
+ %block__element__subelement--modifier {
64
+ background: #f00;
65
+ }
66
+ SCSS
67
+
68
+ it { should report_lint line: 1 }
69
+ it { should report_lint line: 4 }
70
+ end
71
+ end
72
+
73
+ context 'with a custom maximum number of elements' do
74
+ let(:linter_config) { { 'max_elements' => 2 } }
75
+
76
+ context 'when selectors have up to the custom number of elements' do
77
+ let(:scss) { <<-SCSS }
78
+ .block__element__subelement {
79
+ background: #f00;
80
+ }
81
+ %block__element__subelement {
82
+ background: #f00;
83
+ }
84
+ .block__element__subelement--modifier {
85
+ background: #0f0;
86
+ }
87
+ %block__element__subelement--modifier {
88
+ background: #0f0;
89
+ }
90
+ SCSS
91
+
92
+ it { should_not report_lint }
93
+ end
94
+
95
+ context 'when selectors have more than the custom number of elements' do
96
+ let(:scss) { <<-SCSS }
97
+ .block__element__subelement__other {
98
+ background: #f00;
99
+ }
100
+ %block__element__subelement__other {
101
+ background: #f00;
102
+ }
103
+ .block__element__subelement__other--modifier {
104
+ background: #0f0;
105
+ }
106
+ %block__element__subelement__other--modifier {
107
+ background: #0f0;
108
+ }
109
+ SCSS
110
+
111
+ it { should report_lint line: 1 }
112
+ it { should report_lint line: 4 }
113
+ it { should report_lint line: 7 }
114
+ it { should report_lint line: 10 }
115
+ end
116
+ end
117
+ end
@@ -80,4 +80,23 @@ describe SCSSLint::Linter::ColorKeyword do
80
80
 
81
81
  it { should_not report_lint }
82
82
  end
83
+
84
+ context 'when a color keyword is used in a map declaration as keys' do
85
+ let(:scss) { <<-SCSS }
86
+ $palette: (
87
+ white: (
88
+ first: #fff,
89
+ second: #ccc,
90
+ third: #000
91
+ ),
92
+ 'black': (
93
+ first: #000,
94
+ second: #ccc,
95
+ third: #fff
96
+ )
97
+ );
98
+ SCSS
99
+
100
+ it { should_not report_lint }
101
+ end
83
102
  end
@@ -88,6 +88,20 @@ describe SCSSLint::Linter::EmptyLineBetweenBlocks do
88
88
  end
89
89
  end
90
90
 
91
+ context 'when a rule set is in an @if statement with an @else following it' do
92
+ let(:scss) { <<-SCSS }
93
+ @if $condition {
94
+ p {
95
+ }
96
+ } @else {
97
+ p {
98
+ }
99
+ }
100
+ SCSS
101
+
102
+ it { should_not report_lint }
103
+ end
104
+
91
105
  context 'when mixins are defined' do
92
106
  context 'and there is no blank line between them' do
93
107
  let(:scss) { <<-SCSS }
@@ -217,6 +217,15 @@ describe SCSSLint::Linter::Indentation do
217
217
  it { should report_lint line: 2 }
218
218
  end
219
219
 
220
+ context 'when an @import spans multiple lines' do
221
+ let(:scss) { <<-SCSS }
222
+ @import 'foo',
223
+ 'bar';
224
+ SCSS
225
+
226
+ it { should_not report_lint }
227
+ end
228
+
220
229
  context 'when tabs are preferred' do
221
230
  let(:linter_config) { { 'character' => 'tab', 'width' => 1 } }
222
231
 
@@ -259,6 +268,20 @@ describe SCSSLint::Linter::Indentation do
259
268
  }
260
269
  end
261
270
 
271
+ context 'and an if statement is accompanied by a correctly indented else statement' do
272
+ let(:scss) { <<-SCSS }
273
+ @mixin my-func() {
274
+ @if $condition {
275
+ padding: 0;
276
+ } @else {
277
+ margin: 0;
278
+ }
279
+ }
280
+ SCSS
281
+
282
+ it { should_not report_lint }
283
+ end
284
+
262
285
  context 'and non-nested code is indented' do
263
286
  let(:scss) { <<-SCSS }
264
287
  .component {}
@@ -77,7 +77,7 @@ describe SCSSLint::Reporter::JSONReporter do
77
77
  context 'when lints are warnings' do
78
78
  it 'marks each issue with a severity of "warning"' do
79
79
  json.values.inject(0) do |sum, issues|
80
- sum + issues.select { |i| i['severity'] == 'warning' }.size
80
+ sum + issues.count { |i| i['severity'] == 'warning' }
81
81
  end.should == 3
82
82
  end
83
83
  end
@@ -87,7 +87,7 @@ describe SCSSLint::Reporter::JSONReporter do
87
87
 
88
88
  it 'marks each issue with a severity of "error"' do
89
89
  json.values.inject(0) do |sum, issues|
90
- sum + issues.select { |i| i['severity'] == 'error' }.size
90
+ sum + issues.count { |i| i['severity'] == 'error' }
91
91
  end.should == 3
92
92
  end
93
93
  end
data/spec/spec_helper.rb CHANGED
@@ -1,5 +1,4 @@
1
1
  require 'scss_lint'
2
- require 'nokogiri'
3
2
 
4
3
  Dir[File.dirname(__FILE__) + '/support/**/*.rb'].each { |f| require f }
5
4
 
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.38.0
4
+ version: 0.39.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: 2015-05-03 00:00:00.000000000 Z
12
+ date: 2015-05-23 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rainbow
@@ -39,20 +39,6 @@ dependencies:
39
39
  - - "~>"
40
40
  - !ruby/object:Gem::Version
41
41
  version: 3.4.1
42
- - !ruby/object:Gem::Dependency
43
- name: nokogiri
44
- requirement: !ruby/object:Gem::Requirement
45
- requirements:
46
- - - "~>"
47
- - !ruby/object:Gem::Version
48
- version: 1.6.0
49
- type: :development
50
- prerelease: false
51
- version_requirements: !ruby/object:Gem::Requirement
52
- requirements:
53
- - - "~>"
54
- - !ruby/object:Gem::Version
55
- version: 1.6.0
56
42
  - !ruby/object:Gem::Dependency
57
43
  name: rspec
58
44
  requirement: !ruby/object:Gem::Requirement
@@ -95,6 +81,7 @@ files:
95
81
  - lib/scss_lint/lint.rb
96
82
  - lib/scss_lint/linter.rb
97
83
  - lib/scss_lint/linter/bang_format.rb
84
+ - lib/scss_lint/linter/bem_depth.rb
98
85
  - lib/scss_lint/linter/border_zero.rb
99
86
  - lib/scss_lint/linter/color_keyword.rb
100
87
  - lib/scss_lint/linter/color_variable.rb
@@ -154,7 +141,6 @@ files:
154
141
  - lib/scss_lint/reporter/default_reporter.rb
155
142
  - lib/scss_lint/reporter/files_reporter.rb
156
143
  - lib/scss_lint/reporter/json_reporter.rb
157
- - lib/scss_lint/reporter/xml_reporter.rb
158
144
  - lib/scss_lint/runner.rb
159
145
  - lib/scss_lint/sass/script.rb
160
146
  - lib/scss_lint/sass/tree.rb
@@ -166,6 +152,7 @@ files:
166
152
  - spec/scss_lint/engine_spec.rb
167
153
  - spec/scss_lint/file_finder_spec.rb
168
154
  - spec/scss_lint/linter/bang_format_spec.rb
155
+ - spec/scss_lint/linter/bem_depth_spec.rb
169
156
  - spec/scss_lint/linter/border_zero_spec.rb
170
157
  - spec/scss_lint/linter/color_keyword_spec.rb
171
158
  - spec/scss_lint/linter/color_variable_spec.rb
@@ -224,7 +211,6 @@ files:
224
211
  - spec/scss_lint/reporter/default_reporter_spec.rb
225
212
  - spec/scss_lint/reporter/files_reporter_spec.rb
226
213
  - spec/scss_lint/reporter/json_reporter_spec.rb
227
- - spec/scss_lint/reporter/xml_reporter_spec.rb
228
214
  - spec/scss_lint/reporter_spec.rb
229
215
  - spec/scss_lint/runner_spec.rb
230
216
  - spec/scss_lint/selector_visitor_spec.rb
@@ -261,6 +247,7 @@ test_files:
261
247
  - spec/scss_lint/engine_spec.rb
262
248
  - spec/scss_lint/file_finder_spec.rb
263
249
  - spec/scss_lint/linter/bang_format_spec.rb
250
+ - spec/scss_lint/linter/bem_depth_spec.rb
264
251
  - spec/scss_lint/linter/border_zero_spec.rb
265
252
  - spec/scss_lint/linter/color_keyword_spec.rb
266
253
  - spec/scss_lint/linter/color_variable_spec.rb
@@ -319,7 +306,6 @@ test_files:
319
306
  - spec/scss_lint/reporter/default_reporter_spec.rb
320
307
  - spec/scss_lint/reporter/files_reporter_spec.rb
321
308
  - spec/scss_lint/reporter/json_reporter_spec.rb
322
- - spec/scss_lint/reporter/xml_reporter_spec.rb
323
309
  - spec/scss_lint/reporter_spec.rb
324
310
  - spec/scss_lint/runner_spec.rb
325
311
  - spec/scss_lint/selector_visitor_spec.rb
@@ -1,33 +0,0 @@
1
- module SCSSLint
2
- # Reports lints in an XML format.
3
- class Reporter::XMLReporter < Reporter
4
- def report_lints
5
- output = '<?xml version="1.0" encoding="utf-8"?>'
6
-
7
- output << '<lint>'
8
- lints.group_by(&:filename).each do |filename, file_lints|
9
- output << "<file name=#{filename.encode(xml: :attr)}>"
10
-
11
- file_lints.each do |lint|
12
- output << issue_tag(lint)
13
- end
14
-
15
- output << '</file>'
16
- end
17
- output << '</lint>'
18
-
19
- output
20
- end
21
-
22
- private
23
-
24
- def issue_tag(lint)
25
- "<issue linter=\"#{lint.linter.name if lint.linter}\" " \
26
- "line=\"#{lint.location.line}\" " \
27
- "column=\"#{lint.location.column}\" " \
28
- "length=\"#{lint.location.length}\" " \
29
- "severity=\"#{lint.severity}\" " \
30
- "reason=#{lint.description.encode(xml: :attr)} />"
31
- end
32
- end
33
- end
@@ -1,103 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe SCSSLint::Reporter::XMLReporter do
4
- subject { SCSSLint::Reporter::XMLReporter.new(lints) }
5
-
6
- describe '#report_lints' do
7
- let(:xml) { Nokogiri::XML(subject.report_lints) }
8
-
9
- shared_examples_for 'XML document' do
10
- it 'has an encoding of UTF-8' do
11
- xml.encoding.should == 'utf-8'
12
- end
13
-
14
- it 'has an XML version of 1.0' do
15
- xml.version.should == '1.0'
16
- end
17
-
18
- it 'contains a <lint> root element' do
19
- xml.root.name.should == 'lint'
20
- end
21
- end
22
-
23
- context 'when there are no lints' do
24
- let(:lints) { [] }
25
-
26
- it_should_behave_like 'XML document'
27
- end
28
-
29
- context 'when there are lints' do
30
- let(:filenames) { ['f1.scss', 'f2.scss', 'f1.scss'] }
31
- # Include invalid XML characters in the third description to validate
32
- # that escaping happens for preventing broken XML output
33
- let(:descriptions) { ['lint 1', 'lint 2', 'lint 3 " \' < & >'] }
34
- let(:severities) { [:warning] * 3 }
35
-
36
- let(:locations) do
37
- [
38
- SCSSLint::Location.new(5, 2, 3),
39
- SCSSLint::Location.new(7, 6, 2),
40
- SCSSLint::Location.new(9, 10, 1)
41
- ]
42
- end
43
-
44
- let(:lints) do
45
- filenames.each_with_index.map do |filename, index|
46
- SCSSLint::Lint.new(nil, filename, locations[index],
47
- descriptions[index], severities[index])
48
- end
49
- end
50
-
51
- it_should_behave_like 'XML document'
52
-
53
- it 'contains an <issue> node for each lint' do
54
- xml.xpath('//issue').count.should == 3
55
- end
56
-
57
- it 'contains a <file> node for each file' do
58
- xml.xpath('//file').map { |node| node[:name] }
59
- .should =~ filenames.uniq
60
- end
61
-
62
- it 'contains <issue> nodes grouped by <file>' do
63
- xml.xpath('//file').map do |file_node|
64
- file_node.xpath('./issue').count
65
- end.should =~ [1, 2]
66
- end
67
-
68
- it 'marks each issue with a line number' do
69
- xml.xpath('//issue[@line]').map { |node| node[:line] }
70
- .should =~ locations.map { |location| location.line.to_s }
71
- end
72
-
73
- it 'marks each issue with a column number' do
74
- xml.xpath('//issue[@column]').map { |node| node[:column] }
75
- .should =~ locations.map { |location| location.column.to_s }
76
- end
77
-
78
- it 'marks each issue with a length' do
79
- xml.xpath('//issue[@length]').map { |node| node[:length] }
80
- .should =~ locations.map { |location| location.length.to_s }
81
- end
82
-
83
- it 'marks each issue with a reason containing the lint description' do
84
- xml.xpath('//issue[@reason]').map { |node| node[:reason] }
85
- .should =~ descriptions
86
- end
87
-
88
- context 'when lints are warnings' do
89
- it 'marks each issue with a severity of "warning"' do
90
- xml.xpath("//issue[@severity='warning']").count == 3
91
- end
92
- end
93
-
94
- context 'when lints are errors' do
95
- let(:severities) { [:error] * 3 }
96
-
97
- it 'marks each issue with a severity of "error"' do
98
- xml.xpath("//issue[@severity='error']").count == 3
99
- end
100
- end
101
- end
102
- end
103
- end