scss_lint 0.38.0 → 0.39.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: 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