scss_lint 0.46.0 → 0.47.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: 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