scss_lint 0.46.0 → 0.47.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: 9c199f69c02fbbb36ce36e564adaa78528fd5b49
4
- data.tar.gz: 7372af4e048f1935dc730dfffacf89bcc4a1faed
3
+ metadata.gz: 220e8895bebf7c06f86e7fd713590d1a000f39a5
4
+ data.tar.gz: 2ba553b10d57c144b4d70872969be373973f0d77
5
5
  SHA512:
6
- metadata.gz: dad57b1b932447052533abef8b58f2bd0288badf398b2eb946ed7bcfa8dc225e2615e7b90fce017092d5647c1057600b1e7edde12f5fd50781c358530b84e88e
7
- data.tar.gz: 3581b2b0fb3d039346241eec26c889083fca38b0d3f1021052e94107bc0b766e636dd370af2c0e9c92fad70a9df7a5e3494c6f50f4d00005427ceb3b22fab54d
6
+ metadata.gz: 9f1c249c6885cedd4d7f33355e4b97206b0f2e84296d0cdd588016a3598d32af9f68920db045b85c8824c6ef1790297701c6430795f892f292291f591e88ebfa
7
+ data.tar.gz: f8f7e66b89debe64c3ae32d69212e1f9513e32dad3288ef69c203be65b130d65a2238d884708fda84c5571107c6ccb44233c2eaca9051147607753182f89d067
data/lib/scss_lint/cli.rb CHANGED
@@ -18,6 +18,7 @@ module SCSSLint
18
18
  config: 78, # Configuration error
19
19
  no_files: 80, # No files matched by specified glob patterns
20
20
  plugin: 82, # Plugin loading error
21
+ preprocessor: 84, # Preprocessor error
21
22
  }.freeze
22
23
 
23
24
  # Create a CLI that outputs to the specified logger.
@@ -106,6 +107,9 @@ module SCSSLint
106
107
  when NoSuchLinter
107
108
  log.error exception.message
108
109
  halt :usage
110
+ when SCSSLint::Exceptions::PreprocessorError
111
+ log.error exception.message
112
+ halt :preprocessor
109
113
  else
110
114
  config_file = relevant_configuration_file(options) if options
111
115
 
@@ -1,5 +1,7 @@
1
1
  require 'sass'
2
2
 
3
+ require 'open3'
4
+
3
5
  module SCSSLint
4
6
  class FileEncodingError < StandardError; end
5
7
 
@@ -15,13 +17,14 @@ module SCSSLint
15
17
  #
16
18
  # @param options [Hash]
17
19
  # @option options [String] :file The file to load
20
+ # @option options [String] :path The path of the file to load
18
21
  # @option options [String] :code The code to parse
22
+ # @option options [String] :preprocess_command A preprocessing command
23
+ # @option options [List<String>] :preprocess_files A list of files that should be preprocessed
19
24
  def initialize(options = {})
20
- if options[:path]
21
- build_from_file(options)
22
- elsif options[:code]
23
- build_from_string(options[:code])
24
- end
25
+ @preprocess_command = options[:preprocess_command]
26
+ @preprocess_files = options[:preprocess_files]
27
+ build(options)
25
28
 
26
29
  # Need to force encoding to avoid Windows-related bugs.
27
30
  # Need to encode with universal newline to avoid other Windows-related bugs.
@@ -45,6 +48,14 @@ module SCSSLint
45
48
 
46
49
  private
47
50
 
51
+ def build(options)
52
+ if options[:path]
53
+ build_from_file(options)
54
+ elsif options[:code]
55
+ build_from_string(options[:code])
56
+ end
57
+ end
58
+
48
59
  # @param options [Hash]
49
60
  # @option file [IO] if provided, us this as the file object
50
61
  # @option path [String] path of file, loading from this if `file` object not
@@ -52,18 +63,30 @@ module SCSSLint
52
63
  def build_from_file(options)
53
64
  @filename = options[:path]
54
65
  @contents = options[:file] ? options[:file].read : File.read(@filename)
66
+ preprocess_contents
55
67
  @engine = Sass::Engine.new(@contents, ENGINE_OPTIONS.merge(filename: @filename))
56
68
  end
57
69
 
58
70
  # @param scss [String]
59
71
  def build_from_string(scss)
60
- @engine = Sass::Engine.new(scss, ENGINE_OPTIONS)
61
72
  @contents = scss
73
+ preprocess_contents
74
+ @engine = Sass::Engine.new(@contents, ENGINE_OPTIONS)
62
75
  end
63
76
 
64
77
  def find_any_control_commands
65
78
  @any_control_commands =
66
79
  @lines.any? { |line| line['scss-lint:disable'] || line['scss-line:enable'] }
67
80
  end
81
+
82
+ def preprocess_contents # rubocop:disable CyclomaticComplexity
83
+ return unless @preprocess_command
84
+ # Never preprocess :code scss if @preprocess_files is specified.
85
+ return if @preprocess_files && @filename.nil?
86
+ return if @preprocess_files &&
87
+ @preprocess_files.none? { |pattern| File.fnmatch(pattern, @filename) }
88
+ @contents, status = Open3.capture2(@preprocess_command, stdin_data: @contents)
89
+ raise SCSSLint::Exceptions::PreprocessorError if status != 0
90
+ end
68
91
  end
69
92
  end
@@ -17,4 +17,7 @@ module SCSSLint::Exceptions
17
17
 
18
18
  # Raised when a linter gem plugin is required but not installed.
19
19
  class PluginGemLoadError < StandardError; end
20
+
21
+ # Raised when the preprocessor tool exits with a non-zero code.
22
+ class PreprocessorError < StandardError; end
20
23
  end
@@ -105,10 +105,7 @@ module SCSSLint
105
105
  return true # We found a match, so we are done
106
106
  end
107
107
 
108
- # We are at the top of the branch and don't want to check the root branch,
109
- # since that is handled elsewhere, which means that we did not find a
110
- # match.
111
- return false unless node_to_look_in.node_parent.node_parent
108
+ return false unless node_to_look_in.node_parent
112
109
 
113
110
  # We did not find a match yet, and haven't reached the top of the branch,
114
111
  # so recurse.
@@ -122,6 +119,7 @@ module SCSSLint
122
119
  end
123
120
 
124
121
  def before?(node, before_location)
122
+ return true unless node.source_range
125
123
  location = location_from_range(node.source_range)
126
124
  return true if location.line < before_location.line
127
125
  if location.line == before_location.line &&
@@ -97,7 +97,7 @@ not ok #{test_number} - #{test_line_description}
97
97
  file: #{lint.filename}
98
98
  line: #{lint.location.line}
99
99
  column: #{lint.location.column}
100
- ---
100
+ ...
101
101
  EOS
102
102
  end
103
103
 
@@ -25,8 +25,10 @@ module SCSSLint
25
25
  # @param file [Hash]
26
26
  # @option file [String] File object
27
27
  # @option path [String] path to File (determines which Linter config to apply)
28
- def find_lints(file)
29
- engine = Engine.new(file)
28
+ def find_lints(file) # rubocop:disable AbcSize
29
+ options = file.merge(preprocess_command: @config.options['preprocess_command'],
30
+ preprocess_files: @config.options['preprocess_files'])
31
+ engine = Engine.new(options)
30
32
 
31
33
  @linters.each do |linter|
32
34
  begin
@@ -2,5 +2,5 @@
2
2
 
3
3
  # Defines the gem version.
4
4
  module SCSSLint
5
- VERSION = '0.46.0'.freeze
5
+ VERSION = '0.47.0'.freeze
6
6
  end
@@ -60,6 +60,52 @@ describe SCSSLint::Linter::PrivateNamingConvention do
60
60
  it { should_not report_lint }
61
61
  end
62
62
 
63
+ context 'is defined and used in the same file that starts with an @import' do
64
+ let(:scss) { <<-SCSS }
65
+ @import 'bar';
66
+
67
+ $_foo: red;
68
+
69
+ p {
70
+ color: $_foo;
71
+ }
72
+ SCSS
73
+
74
+ it { should_not report_lint }
75
+ end
76
+
77
+ context 'is defined and used in a for loop when the file begins with a comment' do
78
+ let(:scss) { <<-SCSS }
79
+ // A comment
80
+ @function _foo() {
81
+ @return red;
82
+ }
83
+
84
+ @for $i from 0 through 1 {
85
+ .foo {
86
+ color: _foo();
87
+ }
88
+ }
89
+ SCSS
90
+
91
+ it { should_not report_lint }
92
+ end
93
+
94
+ context 'is defined and used in the same file when the file begins with a comment' do
95
+ let(:scss) { <<-SCSS }
96
+ // A comment
97
+ @function _foo() {
98
+ @return red;
99
+ }
100
+
101
+ .foo {
102
+ color: _foo();
103
+ }
104
+ SCSS
105
+
106
+ it { should_not report_lint }
107
+ end
108
+
63
109
  context 'is defined within a selector and not used' do
64
110
  let(:scss) { <<-SCSS }
65
111
  p {
@@ -0,0 +1,85 @@
1
+ require 'spec_helper'
2
+
3
+ describe SCSSLint::Engine do
4
+ let(:engine) { described_class.new(options) }
5
+ let(:command) { 'my-command' }
6
+ let(:scss) { <<-SCSS }
7
+ ---
8
+ ---
9
+ $red: #f00;
10
+ SCSS
11
+ let(:processed) { <<-SCSS }
12
+ $red: #f00;
13
+ SCSS
14
+
15
+ context 'preprocess_command is specified' do
16
+ let(:options) { { code: scss, preprocess_command: command } }
17
+
18
+ it 'preprocesses, and Sass is able to parse' do
19
+ open3 = class_double('Open3').as_stubbed_const
20
+ open3.should_receive(:capture2).with(command, stdin_data: scss).and_return([processed, 0])
21
+
22
+ variable = engine.tree.children[0]
23
+ expect(variable).to be_instance_of(Sass::Tree::VariableNode)
24
+ expect(variable.name).to eq('red')
25
+ end
26
+ end
27
+
28
+ context 'preprocessor fails' do
29
+ let(:options) { { code: scss, preprocess_command: command } }
30
+
31
+ it 'preprocesses, and Sass is able to parse' do
32
+ open3 = class_double('Open3').as_stubbed_const
33
+ open3.should_receive(:capture2).with(command, stdin_data: scss).and_return([processed, 1])
34
+
35
+ expect { engine }.to raise_error(SCSSLint::Exceptions::PreprocessorError)
36
+ end
37
+ end
38
+
39
+ context 'both preprocess_command and preprocess_files are specified' do
40
+ let(:path) { 'foo/a.scss' }
41
+
42
+ context 'file should be preprocessed' do
43
+ let(:options) do
44
+ { path: path,
45
+ preprocess_command: command,
46
+ preprocess_files: ['foo/*.scss'] }
47
+ end
48
+
49
+ it 'preprocesses, and Sass is able to parse' do
50
+ open3 = class_double('Open3').as_stubbed_const
51
+ open3.should_receive(:capture2).with(command, stdin_data: scss).and_return([processed, 0])
52
+ File.should_receive(:read).with(path).and_return(scss)
53
+
54
+ variable = engine.tree.children[0]
55
+ expect(variable).to be_instance_of(Sass::Tree::VariableNode)
56
+ expect(variable.name).to eq('red')
57
+ end
58
+ end
59
+
60
+ context 'file should not be preprocessed' do
61
+ let(:options) do
62
+ { path: path,
63
+ preprocess_command: command,
64
+ preprocess_files: ['bar/*.scss'] }
65
+ end
66
+
67
+ it 'does not preprocess, and Sass throws' do
68
+ File.should_receive(:read).with(path).and_return(scss)
69
+ expect { engine }.to raise_error(Sass::SyntaxError)
70
+ end
71
+ end
72
+
73
+ context 'code should never be preprocessed' do
74
+ let(:options) do
75
+ { code: scss,
76
+ preprocess_command: command,
77
+ preprocess_files: ['foo/*.scss'] }
78
+ end
79
+
80
+ it 'does not preprocess, and Sass throws' do
81
+ expect { engine }.to raise_error(Sass::SyntaxError)
82
+ end
83
+ end
84
+ end
85
+ end
@@ -70,7 +70,7 @@ not ok 2 - not-ok1.scss:123:10 SCSSLint::Linter::PrivateNamingConvention
70
70
  file: not-ok1.scss
71
71
  line: 123
72
72
  column: 10
73
- ---
73
+ ...
74
74
  not ok 3 - not-ok2.scss:20:2 SCSSLint::Linter::PrivateNamingConvention
75
75
  ---
76
76
  message: Description of lint 2
@@ -79,7 +79,7 @@ not ok 3 - not-ok2.scss:20:2 SCSSLint::Linter::PrivateNamingConvention
79
79
  file: not-ok2.scss
80
80
  line: 20
81
81
  column: 2
82
- ---
82
+ ...
83
83
  not ok 4 - not-ok2.scss:21:3 SCSSLint::Linter::PrivateNamingConvention
84
84
  ---
85
85
  message: Description of lint 3
@@ -88,7 +88,7 @@ not ok 4 - not-ok2.scss:21:3 SCSSLint::Linter::PrivateNamingConvention
88
88
  file: not-ok2.scss
89
89
  line: 21
90
90
  column: 3
91
- ---
91
+ ...
92
92
  ok 5 - ok2.scss
93
93
  EOS
94
94
  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.46.0
4
+ version: 0.47.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brigade Engineering
@@ -245,6 +245,7 @@ files:
245
245
  - spec/scss_lint/plugins/linter_dir_spec.rb
246
246
  - spec/scss_lint/plugins/linter_gem_spec.rb
247
247
  - spec/scss_lint/plugins_spec.rb
248
+ - spec/scss_lint/preprocess_spec.rb
248
249
  - spec/scss_lint/rake_task_spec.rb
249
250
  - spec/scss_lint/report_lint_spec.rb
250
251
  - spec/scss_lint/reporter/clean_files_reporter_spec.rb
@@ -358,6 +359,7 @@ test_files:
358
359
  - spec/scss_lint/plugins/linter_dir_spec.rb
359
360
  - spec/scss_lint/plugins/linter_gem_spec.rb
360
361
  - spec/scss_lint/plugins_spec.rb
362
+ - spec/scss_lint/preprocess_spec.rb
361
363
  - spec/scss_lint/rake_task_spec.rb
362
364
  - spec/scss_lint/report_lint_spec.rb
363
365
  - spec/scss_lint/reporter/clean_files_reporter_spec.rb