scss-lint 0.30.0 → 0.31.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/bin/scss-lint +1 -4
  3. data/config/default.yml +5 -4
  4. data/data/property-sort-orders/recess.txt +149 -0
  5. data/data/property-sort-orders/smacss.txt +138 -0
  6. data/lib/scss_lint.rb +1 -0
  7. data/lib/scss_lint/cli.rb +93 -153
  8. data/lib/scss_lint/config.rb +16 -13
  9. data/lib/scss_lint/control_comment_processor.rb +83 -0
  10. data/lib/scss_lint/engine.rb +21 -5
  11. data/lib/scss_lint/exceptions.rb +6 -0
  12. data/lib/scss_lint/linter.rb +6 -2
  13. data/lib/scss_lint/linter/bang_format.rb +20 -9
  14. data/lib/scss_lint/linter/duplicate_property.rb +35 -30
  15. data/lib/scss_lint/linter/empty_line_between_blocks.rb +1 -1
  16. data/lib/scss_lint/linter/id_selector.rb +10 -0
  17. data/lib/scss_lint/linter/indentation.rb +2 -1
  18. data/lib/scss_lint/linter/leading_zero.rb +6 -6
  19. data/lib/scss_lint/linter/name_format.rb +11 -0
  20. data/lib/scss_lint/linter/selector_format.rb +0 -4
  21. data/lib/scss_lint/linter/single_line_per_property.rb +13 -7
  22. data/lib/scss_lint/linter/single_line_per_selector.rb +19 -11
  23. data/lib/scss_lint/linter/trailing_semicolon.rb +5 -3
  24. data/lib/scss_lint/linter/trailing_zero.rb +4 -4
  25. data/lib/scss_lint/options.rb +113 -0
  26. data/lib/scss_lint/reporter/default_reporter.rb +15 -7
  27. data/lib/scss_lint/reporter/json_reporter.rb +15 -8
  28. data/lib/scss_lint/reporter/xml_reporter.rb +12 -6
  29. data/lib/scss_lint/runner.rb +4 -5
  30. data/lib/scss_lint/version.rb +1 -1
  31. data/spec/scss_lint/cli_spec.rb +9 -229
  32. data/spec/scss_lint/linter/bang_format_spec.rb +20 -0
  33. data/spec/scss_lint/linter/duplicate_property_spec.rb +13 -0
  34. data/spec/scss_lint/linter/empty_line_between_blocks_spec.rb +12 -11
  35. data/spec/scss_lint/linter/id_selector_spec.rb +62 -0
  36. data/spec/scss_lint/linter/indentation_spec.rb +11 -0
  37. data/spec/scss_lint/linter/name_format_spec.rb +147 -117
  38. data/spec/scss_lint/linter/selector_format_spec.rb +3 -66
  39. data/spec/scss_lint/linter/trailing_semicolon_spec.rb +20 -0
  40. data/spec/scss_lint/linter_spec.rb +248 -0
  41. data/spec/scss_lint/options_spec.rb +42 -0
  42. data/spec/spec_helper.rb +1 -1
  43. metadata +177 -183
  44. data/lib/scss_lint/linter/id_with_extraneous_selector.rb +0 -20
  45. data/spec/scss_lint/linter/id_with_extraneous_selector_spec.rb +0 -139
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 63daef837600174964f65634095dac45b13a1bb2
4
- data.tar.gz: 8b8e1fdebc6d40d577c02a0092c092212f0d46ee
3
+ metadata.gz: 67663cf8293192d8f0962e8fe04c86d2b2dafddb
4
+ data.tar.gz: 92271e0c11e57a9088be1bd94437b7c07c31e205
5
5
  SHA512:
6
- metadata.gz: 6ed4cbb25cacdfdf0645ea476ccc86032ae8032c22fdb1b3cf8fdd6934601bdc075aa4ed71fa1a05d2dec08785ceb591d53eeb2c6541b5567f434ff4ce161d20
7
- data.tar.gz: 07a85bc0d214819857e179babe4b465193adf01391f7eecadd25611264c28605e0990911e1eb6dd75ed79b65b0cb50b6529187513e6842674e5c5abeafeca5f2
6
+ metadata.gz: 7048b50c46c68b5d7cae9dea14a37791e550a40092b7d3443d266076fb5bfebf1d858b66eb8f6d8c147a75f54deafcbc3d72eb03740ed51f1b79a9406e925217
7
+ data.tar.gz: e89a5be79049adc3e1aa69e761a961ba711cab010843a54031e7ecdfc546c12c5647ff7b407f875be6577c3d22e817976cdb71fd39f3dc0d7f4bd045e2dfdca1
@@ -3,7 +3,4 @@
3
3
  require 'scss_lint'
4
4
  require 'scss_lint/cli'
5
5
 
6
- SCSSLint::CLI.new(ARGV).tap do |cli|
7
- cli.parse_arguments
8
- cli.run
9
- end
6
+ exit SCSSLint::CLI.new.run(ARGV)
@@ -52,7 +52,7 @@ linters:
52
52
  HexValidation:
53
53
  enabled: true
54
54
 
55
- IdWithExtraneousSelector:
55
+ IdSelector:
56
56
  enabled: true
57
57
 
58
58
  ImportPath:
@@ -75,6 +75,7 @@ linters:
75
75
 
76
76
  NameFormat:
77
77
  enabled: true
78
+ allow_leading_underscore: true
78
79
  convention: hyphenated_lowercase # or 'BEM', or a regex pattern
79
80
 
80
81
  NestingDepth:
@@ -94,9 +95,9 @@ linters:
94
95
 
95
96
  QualifyingElement:
96
97
  enabled: true
97
- allow_with_attribute: false
98
- allow_with_class: false
99
- allow_with_id: false
98
+ allow_element_with_attribute: false
99
+ allow_element_with_class: false
100
+ allow_element_with_id: false
100
101
 
101
102
  SelectorDepth:
102
103
  enabled: true
@@ -0,0 +1,149 @@
1
+ # RECESS Property Order
2
+ # https://github.com/twitter/recess
3
+
4
+ position
5
+ top
6
+ right
7
+ bottom
8
+ left
9
+ z-index
10
+ display
11
+ float
12
+ width
13
+ height
14
+ max-width
15
+ max-height
16
+ min-width
17
+ min-height
18
+ padding
19
+ padding-top
20
+ padding-right
21
+ padding-bottom
22
+ padding-left
23
+ margin
24
+ margin-top
25
+ margin-right
26
+ margin-bottom
27
+ margin-left
28
+ margin-collapse
29
+ margin-top-collapse
30
+ margin-right-collapse
31
+ margin-bottom-collapse
32
+ margin-left-collapse
33
+ overflow
34
+ overflow-x
35
+ overflow-y
36
+ clip
37
+ clear
38
+ font
39
+ font-family
40
+ font-size
41
+ font-smoothing
42
+ osx-font-smoothing
43
+ font-style
44
+ font-weight
45
+ hyphens
46
+ src
47
+ line-height
48
+ letter-spacing
49
+ word-spacing
50
+ color
51
+ text-align
52
+ text-decoration
53
+ text-indent
54
+ text-overflow
55
+ text-rendering
56
+ text-size-adjust
57
+ text-shadow
58
+ text-transform
59
+ word-break
60
+ word-wrap
61
+ white-space
62
+ vertical-align
63
+ list-style
64
+ list-style-type
65
+ list-style-position
66
+ list-style-image
67
+ pointer-events
68
+ cursor
69
+ background
70
+ background-attachment
71
+ background-color
72
+ background-image
73
+ background-position
74
+ background-repeat
75
+ background-size
76
+ border
77
+ border-collapse
78
+ border-top
79
+ border-right
80
+ border-bottom
81
+ border-left
82
+ border-color
83
+ border-image
84
+ border-top-color
85
+ border-right-color
86
+ border-bottom-color
87
+ border-left-color
88
+ border-spacing
89
+ border-style
90
+ border-top-style
91
+ border-right-style
92
+ border-bottom-style
93
+ border-left-style
94
+ border-width
95
+ border-top-width
96
+ border-right-width
97
+ border-bottom-width
98
+ border-left-width
99
+ border-radius
100
+ border-top-right-radius
101
+ border-bottom-right-radius
102
+ border-bottom-left-radius
103
+ border-top-left-radius
104
+ border-radius-topright
105
+ border-radius-bottomright
106
+ border-radius-bottomleft
107
+ border-radius-topleft
108
+ content
109
+ quotes
110
+ outline
111
+ outline-offset
112
+ opacity
113
+ filter
114
+ visibility
115
+ size
116
+ zoom
117
+ transform
118
+ box-align
119
+ box-flex
120
+ box-orient
121
+ box-pack
122
+ box-shadow
123
+ box-sizing
124
+ table-layout
125
+ animation
126
+ animation-delay
127
+ animation-duration
128
+ animation-iteration-count
129
+ animation-name
130
+ animation-play-state
131
+ animation-timing-function
132
+ animation-fill-mode
133
+ transition
134
+ transition-delay
135
+ transition-duration
136
+ transition-property
137
+ transition-timing-function
138
+ background-clip
139
+ backface-visibility
140
+ resize
141
+ appearance
142
+ user-select
143
+ interpolation-mode
144
+ direction
145
+ marks
146
+ page
147
+ set-link-source
148
+ unicode-bidi
149
+ speak
@@ -0,0 +1,138 @@
1
+ # SMACSS Property Order
2
+ # http://smacss.com/book/formatting
3
+
4
+ # Box
5
+
6
+ display
7
+ position
8
+ top
9
+ right
10
+ bottom
11
+ left
12
+
13
+ width
14
+ min-width
15
+ max-width
16
+
17
+ height
18
+ min-height
19
+ max-height
20
+
21
+ margin
22
+ margin-top
23
+ margin-right
24
+ margin-bottom
25
+ margin-left
26
+
27
+ padding
28
+ padding-top
29
+ padding-right
30
+ padding-bottom
31
+ padding-left
32
+
33
+ float
34
+ clear
35
+
36
+ columns
37
+ column-gap
38
+ column-fill
39
+ column-rule
40
+ column-span
41
+ column-count
42
+ column-width
43
+
44
+ transform
45
+ transition
46
+
47
+ # Border
48
+
49
+ border
50
+ border-top
51
+ border-right
52
+ border-bottom
53
+ border-left
54
+ border-width
55
+ border-top-width
56
+ border-right-width
57
+ border-bottom-width
58
+ border-left-width
59
+
60
+ border-style
61
+ border-top-style
62
+ border-right-style
63
+ border-bottom-style
64
+ border-left-style
65
+
66
+ border-radius
67
+ border-top-left-radius
68
+ border-top-right-radius
69
+ border-bottom-left-radius
70
+ border-bottom-right-radius
71
+
72
+ border-color
73
+ border-top-color
74
+ border-right-color
75
+ border-bottom-color
76
+ border-left-color
77
+
78
+ outline
79
+ outline-color
80
+ outline-offset
81
+ outline-style
82
+ outline-width
83
+
84
+ # Background
85
+
86
+ background
87
+ background-color
88
+ background-image
89
+ background-repeat
90
+ background-position
91
+ background-size
92
+ cursor
93
+
94
+ # Text
95
+
96
+ color
97
+
98
+ font
99
+ font-family
100
+ font-size
101
+ font-smoothing
102
+ font-style
103
+ font-variant
104
+ font-weight
105
+
106
+ letter-spacing
107
+ line-height
108
+ list-style
109
+
110
+ text-align
111
+ text-decoration
112
+ text-indent
113
+ text-overflow
114
+ text-rendering
115
+ text-shadow
116
+ text-transform
117
+ text-wrap
118
+
119
+ white-space
120
+ word-spacing
121
+
122
+ # Other
123
+
124
+ border-collapse
125
+ border-spacing
126
+ box-shadow
127
+ caption-side
128
+ content
129
+ cursor
130
+ empty-cells
131
+ opacity
132
+ overflow
133
+ quotes
134
+ speak
135
+ table-layout
136
+ vertical-align
137
+ visibility
138
+ z-index
@@ -7,6 +7,7 @@ require 'scss_lint/lint'
7
7
  require 'scss_lint/linter_registry'
8
8
  require 'scss_lint/runner'
9
9
  require 'scss_lint/selector_visitor'
10
+ require 'scss_lint/control_comment_processor'
10
11
  require 'scss_lint/version'
11
12
  require 'scss_lint/utils'
12
13
 
@@ -1,7 +1,7 @@
1
1
  require 'find'
2
- require 'optparse'
3
2
  require 'rainbow'
4
3
  require 'rainbow/ext/string'
4
+ require 'scss_lint/options'
5
5
 
6
6
  module SCSSLint
7
7
  # Responsible for parsing command-line options and executing the appropriate
@@ -20,151 +20,101 @@ module SCSSLint
20
20
  config: 78, # Configuration error
21
21
  }
22
22
 
23
- DEFAULT_REPORTER = [SCSSLint::Reporter::DefaultReporter, :stdout]
24
-
25
- # @param args [Array]
26
- def initialize(args = [])
27
- @args = args
28
- @options = { reporters: [DEFAULT_REPORTER] }
29
- @config = Config.default
30
- end
31
-
32
- def parse_arguments
33
- begin
34
- options_parser.parse!(@args)
35
-
36
- # Take the rest of the arguments as files/directories
37
-
38
- if @args.empty?
39
- @options[:files] = @config.scss_files
40
- else
41
- @options[:files] = @args
42
- end
43
-
44
- rescue OptionParser::InvalidOption => ex
45
- print_help options_parser.help, ex
46
- end
47
-
48
- begin
49
- setup_configuration
50
- rescue InvalidConfiguration, NoSuchLinter => ex
51
- puts ex.message
52
- halt :config
53
- end
23
+ def run(args)
24
+ options = SCSSLint::Options.new.parse(args)
25
+ act_on_options(options)
26
+ rescue => ex
27
+ handle_runtime_exception(ex)
54
28
  end
55
29
 
56
- # @return [OptionParser]
57
- def options_parser # rubocop:disable MethodLength
58
- @options_parser ||= OptionParser.new do |opts|
59
- opts.banner = "Usage: #{opts.program_name} [options] [scss-files]"
60
-
61
- opts.separator ''
62
- opts.separator 'Common options:'
63
-
64
- opts.on('-c', '--config file', 'Specify configuration file', String) do |file|
65
- @options[:config_file] = file
66
- end
67
-
68
- opts.on('-e', '--exclude file,...', Array,
69
- 'List of file names to exclude') do |files|
70
- @options[:excluded_files] = files
71
- end
72
-
73
- opts.on('-f', '--format Formatter', 'Specify how to display lints', String) do |format|
74
- define_output_format(format)
75
- end
76
-
77
- opts.on('-o', '--out path', 'Write output to a file instead of STDOUT', String) do |path|
78
- define_output_path(path)
79
- end
80
-
81
- opts.on('-r', '--require path', 'Require Ruby file', String) do |path|
82
- require path
83
- end
84
-
85
- opts.on_tail('--show-formatters', 'Shows available formatters') do
86
- print_formatters
87
- end
88
-
89
- opts.on('-i', '--include-linter linter,...', Array,
90
- 'Specify which linters you want to run') do |linters|
91
- @options[:included_linters] = linters
92
- end
93
-
94
- opts.on('-x', '--exclude-linter linter,...', Array,
95
- "Specify which linters you don't want to run") do |linters|
96
- @options[:excluded_linters] = linters
97
- end
98
-
99
- opts.on_tail('--show-linters', 'Shows available linters') do
100
- print_linters
101
- end
30
+ private
102
31
 
103
- opts.on_tail('-h', '--help', 'Show this message') do
104
- print_help opts.help
105
- end
32
+ def act_on_options(options)
33
+ load_required_paths(options)
106
34
 
107
- opts.on_tail('-v', '--version', 'Show version') do
108
- print_version opts.program_name, VERSION
109
- end
35
+ if options[:help]
36
+ print_help(options)
37
+ elsif options[:version]
38
+ print_version
39
+ elsif options[:show_linters]
40
+ print_linters
41
+ elsif options[:show_formatters]
42
+ print_formatters
43
+ else
44
+ config = setup_configuration(options)
45
+ scan_for_lints(options, config)
110
46
  end
111
47
  end
112
48
 
113
- def run # rubocop:disable MethodLength
114
- runner = Runner.new(@config)
115
- runner.run(files_to_lint)
116
- report_lints(runner.lints)
49
+ def scan_for_lints(options, config)
50
+ runner = Runner.new(config)
51
+ runner.run(files_to_lint(options, config))
52
+ report_lints(options, runner.lints)
117
53
 
118
54
  if runner.lints.any?(&:error?)
119
55
  halt :error
120
56
  elsif runner.lints.any?
121
57
  halt :warning
58
+ else
59
+ halt :ok
122
60
  end
123
- rescue InvalidConfiguration => ex
124
- puts ex
125
- halt :config
126
- rescue NoFilesError, Errno::ENOENT => ex
127
- puts ex.message
128
- halt :no_input
129
- rescue NoSuchLinter => ex
130
- puts ex.message
131
- halt :usage
132
- rescue => ex
133
- puts ex.message
134
- puts ex.backtrace
135
- puts 'Report this bug at '.color(:yellow) + BUG_REPORT_URL.color(:cyan)
136
- halt :software
137
61
  end
138
62
 
139
- private
140
-
141
- def setup_configuration
142
- if @options[:config_file]
143
- @config = Config.load(@options[:config_file])
144
- @config.preferred = true
145
- end
63
+ def handle_runtime_exception(exception) # rubocop:disable Metrics/AbcSize
64
+ case exception
65
+ when SCSSLint::Exceptions::InvalidCLIOption
66
+ puts exception.message
67
+ puts 'Run `scss-lint --help` for usage documentation'
68
+ halt :usage
69
+ when SCSSLint::Exceptions::InvalidConfiguration
70
+ puts exception.message
71
+ halt :config
72
+ when NoFilesError, Errno::ENOENT
73
+ puts exception.message
74
+ halt :no_input
75
+ when NoSuchLinter
76
+ puts exception.message
77
+ halt :usage
78
+ else
79
+ puts exception.message
80
+ puts exception.backtrace
81
+ puts 'Report this bug at '.color(:yellow) + BUG_REPORT_URL.color(:cyan)
82
+ halt :software
83
+ end
84
+ end
85
+
86
+ def setup_configuration(options)
87
+ config =
88
+ if options[:config_file]
89
+ Config.load(options[:config_file]).tap do |conf|
90
+ conf.preferred = true
91
+ end
92
+ else
93
+ Config.default
94
+ end
146
95
 
147
- merge_command_line_flags_with_config(@config)
96
+ merge_options_with_config(options, config)
148
97
  end
149
98
 
99
+ # @param options [Hash]
150
100
  # @param config [Config]
151
101
  # @return [Config]
152
- def merge_command_line_flags_with_config(config)
153
- if @options[:excluded_files]
154
- @options[:excluded_files].each do |file|
102
+ def merge_options_with_config(options, config)
103
+ if options[:excluded_files]
104
+ options[:excluded_files].each do |file|
155
105
  config.exclude_file(file)
156
106
  end
157
107
  end
158
108
 
159
- if @options[:included_linters]
109
+ if options[:included_linters]
160
110
  config.disable_all_linters
161
- LinterRegistry.extract_linters_from(@options[:included_linters]).each do |linter|
111
+ LinterRegistry.extract_linters_from(options[:included_linters]).each do |linter|
162
112
  config.enable_linter(linter)
163
113
  end
164
114
  end
165
115
 
166
- if @options[:excluded_linters]
167
- LinterRegistry.extract_linters_from(@options[:excluded_linters]).each do |linter|
116
+ if options[:excluded_linters]
117
+ LinterRegistry.extract_linters_from(options[:excluded_linters]).each do |linter|
168
118
  config.disable_linter(linter)
169
119
  end
170
120
  end
@@ -172,16 +122,20 @@ module SCSSLint
172
122
  config
173
123
  end
174
124
 
175
- def files_to_lint
176
- extract_files_from(@options[:files]).reject do |file|
177
- config =
178
- if !@config.preferred && (config_for_file = Config.for_file(file))
179
- merge_command_line_flags_with_config(config_for_file.dup)
125
+ def files_to_lint(options, config)
126
+ if options[:files].empty?
127
+ options[:files] = config.scss_files
128
+ end
129
+
130
+ extract_files_from(options[:files]).reject do |file|
131
+ actual_config =
132
+ if !config.preferred && (config_for_file = Config.for_file(file))
133
+ merge_options_with_config(options, config_for_file.dup)
180
134
  else
181
- @config
135
+ config
182
136
  end
183
137
 
184
- config.excluded_file?(file)
138
+ actual_config.excluded_file?(file)
185
139
  end
186
140
  end
187
141
 
@@ -205,32 +159,21 @@ module SCSSLint
205
159
  VALID_EXTENSIONS.include?(File.extname(file))
206
160
  end
207
161
 
162
+ # @param options [Hash]
208
163
  # @param lints [Array<Lint>]
209
- def report_lints(lints)
164
+ def report_lints(options, lints)
210
165
  sorted_lints = lints.sort_by { |l| [l.filename, l.location] }
211
- @options.fetch(:reporters).each do |reporter, output|
166
+ options.fetch(:reporters).each do |reporter, output|
212
167
  results = reporter.new(sorted_lints).report_lints
213
168
  io = (output == :stdout ? $stdout : File.new(output, 'w+'))
214
169
  io.print results if results
215
170
  end
216
171
  end
217
172
 
218
- # @param format [String]
219
- def define_output_format(format)
220
- unless @options[:reporters] == [DEFAULT_REPORTER] && format == 'Default'
221
- @options[:reporters].reject! { |i| i == DEFAULT_REPORTER }
222
- reporter = SCSSLint::Reporter.const_get(format + 'Reporter')
223
- @options[:reporters] << [reporter, :stdout]
173
+ def load_required_paths(options)
174
+ Array(options[:required_paths]).each do |path|
175
+ require path
224
176
  end
225
- rescue NameError
226
- puts "Invalid output format specified: #{format}"
227
- halt :config
228
- end
229
-
230
- # @param path [String]
231
- def define_output_path(path)
232
- last_reporter, _output = @options[:reporters].pop
233
- @options[:reporters] << [last_reporter, path]
234
177
  end
235
178
 
236
179
  def print_formatters
@@ -261,25 +204,22 @@ module SCSSLint
261
204
  halt
262
205
  end
263
206
 
264
- # @param help_message [String]
265
- # @param err [Exception]
266
- def print_help(help_message, err = nil)
267
- puts err, '' if err
268
- puts help_message
269
- halt(err ? :usage : :ok)
207
+ # @param options [Hash]
208
+ def print_help(options)
209
+ puts options[:help]
210
+ halt :ok
270
211
  end
271
212
 
272
- # @param program_name [String]
273
- # @param version [String]
274
- def print_version(program_name, version)
275
- puts "#{program_name} #{version}"
276
- halt
213
+ # @param options [Hash]
214
+ def print_version
215
+ puts "scss-lint #{SCSSLint::VERSION}"
216
+ halt :ok
277
217
  end
278
218
 
279
219
  # Used for ease-of testing
280
220
  # @param exit_status [Symbol]
281
221
  def halt(exit_status = :ok)
282
- exit(EXIT_CODES[exit_status])
222
+ EXIT_CODES[exit_status]
283
223
  end
284
224
  end
285
225
  end