scss_lint 0.38.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 +7 -0
- data/bin/scss-lint +6 -0
- data/config/default.yml +205 -0
- data/data/prefixed-identifiers/base.txt +107 -0
- data/data/prefixed-identifiers/bourbon.txt +71 -0
- data/data/properties.txt +477 -0
- data/data/property-sort-orders/concentric.txt +134 -0
- data/data/property-sort-orders/recess.txt +149 -0
- data/data/property-sort-orders/smacss.txt +137 -0
- data/lib/scss_lint.rb +31 -0
- data/lib/scss_lint/cli.rb +215 -0
- data/lib/scss_lint/config.rb +251 -0
- data/lib/scss_lint/constants.rb +8 -0
- data/lib/scss_lint/control_comment_processor.rb +126 -0
- data/lib/scss_lint/engine.rb +56 -0
- data/lib/scss_lint/exceptions.rb +21 -0
- data/lib/scss_lint/file_finder.rb +68 -0
- data/lib/scss_lint/lint.rb +24 -0
- data/lib/scss_lint/linter.rb +161 -0
- data/lib/scss_lint/linter/bang_format.rb +52 -0
- data/lib/scss_lint/linter/border_zero.rb +39 -0
- data/lib/scss_lint/linter/color_keyword.rb +32 -0
- data/lib/scss_lint/linter/color_variable.rb +60 -0
- data/lib/scss_lint/linter/comment.rb +21 -0
- data/lib/scss_lint/linter/compass.rb +7 -0
- data/lib/scss_lint/linter/compass/property_with_mixin.rb +47 -0
- data/lib/scss_lint/linter/debug_statement.rb +10 -0
- data/lib/scss_lint/linter/declaration_order.rb +71 -0
- data/lib/scss_lint/linter/duplicate_property.rb +58 -0
- data/lib/scss_lint/linter/else_placement.rb +48 -0
- data/lib/scss_lint/linter/empty_line_between_blocks.rb +85 -0
- data/lib/scss_lint/linter/empty_rule.rb +11 -0
- data/lib/scss_lint/linter/final_newline.rb +20 -0
- data/lib/scss_lint/linter/hex_length.rb +56 -0
- data/lib/scss_lint/linter/hex_notation.rb +38 -0
- data/lib/scss_lint/linter/hex_validation.rb +23 -0
- data/lib/scss_lint/linter/id_selector.rb +10 -0
- data/lib/scss_lint/linter/import_path.rb +62 -0
- data/lib/scss_lint/linter/important_rule.rb +12 -0
- data/lib/scss_lint/linter/indentation.rb +197 -0
- data/lib/scss_lint/linter/leading_zero.rb +49 -0
- data/lib/scss_lint/linter/mergeable_selector.rb +60 -0
- data/lib/scss_lint/linter/name_format.rb +117 -0
- data/lib/scss_lint/linter/nesting_depth.rb +24 -0
- data/lib/scss_lint/linter/placeholder_in_extend.rb +22 -0
- data/lib/scss_lint/linter/property_count.rb +44 -0
- data/lib/scss_lint/linter/property_sort_order.rb +198 -0
- data/lib/scss_lint/linter/property_spelling.rb +49 -0
- data/lib/scss_lint/linter/property_units.rb +59 -0
- data/lib/scss_lint/linter/qualifying_element.rb +42 -0
- data/lib/scss_lint/linter/selector_depth.rb +64 -0
- data/lib/scss_lint/linter/selector_format.rb +102 -0
- data/lib/scss_lint/linter/shorthand.rb +139 -0
- data/lib/scss_lint/linter/single_line_per_property.rb +59 -0
- data/lib/scss_lint/linter/single_line_per_selector.rb +35 -0
- data/lib/scss_lint/linter/space_after_comma.rb +110 -0
- data/lib/scss_lint/linter/space_after_property_colon.rb +92 -0
- data/lib/scss_lint/linter/space_after_property_name.rb +27 -0
- data/lib/scss_lint/linter/space_before_brace.rb +72 -0
- data/lib/scss_lint/linter/space_between_parens.rb +35 -0
- data/lib/scss_lint/linter/string_quotes.rb +94 -0
- data/lib/scss_lint/linter/trailing_semicolon.rb +67 -0
- data/lib/scss_lint/linter/trailing_zero.rb +41 -0
- data/lib/scss_lint/linter/unnecessary_mantissa.rb +42 -0
- data/lib/scss_lint/linter/unnecessary_parent_reference.rb +49 -0
- data/lib/scss_lint/linter/url_format.rb +56 -0
- data/lib/scss_lint/linter/url_quotes.rb +27 -0
- data/lib/scss_lint/linter/variable_for_property.rb +30 -0
- data/lib/scss_lint/linter/vendor_prefix.rb +64 -0
- data/lib/scss_lint/linter/zero_unit.rb +39 -0
- data/lib/scss_lint/linter_registry.rb +26 -0
- data/lib/scss_lint/location.rb +38 -0
- data/lib/scss_lint/options.rb +109 -0
- data/lib/scss_lint/rake_task.rb +106 -0
- data/lib/scss_lint/reporter.rb +18 -0
- data/lib/scss_lint/reporter/config_reporter.rb +26 -0
- data/lib/scss_lint/reporter/default_reporter.rb +27 -0
- data/lib/scss_lint/reporter/files_reporter.rb +8 -0
- data/lib/scss_lint/reporter/json_reporter.rb +30 -0
- data/lib/scss_lint/reporter/xml_reporter.rb +33 -0
- data/lib/scss_lint/runner.rb +51 -0
- data/lib/scss_lint/sass/script.rb +78 -0
- data/lib/scss_lint/sass/tree.rb +168 -0
- data/lib/scss_lint/selector_visitor.rb +34 -0
- data/lib/scss_lint/utils.rb +112 -0
- data/lib/scss_lint/version.rb +4 -0
- data/spec/scss_lint/cli_spec.rb +177 -0
- data/spec/scss_lint/config_spec.rb +253 -0
- data/spec/scss_lint/engine_spec.rb +24 -0
- data/spec/scss_lint/file_finder_spec.rb +134 -0
- data/spec/scss_lint/linter/bang_format_spec.rb +121 -0
- data/spec/scss_lint/linter/border_zero_spec.rb +118 -0
- data/spec/scss_lint/linter/color_keyword_spec.rb +83 -0
- data/spec/scss_lint/linter/color_variable_spec.rb +155 -0
- data/spec/scss_lint/linter/comment_spec.rb +79 -0
- data/spec/scss_lint/linter/compass/property_with_mixin_spec.rb +55 -0
- data/spec/scss_lint/linter/debug_statement_spec.rb +21 -0
- data/spec/scss_lint/linter/declaration_order_spec.rb +575 -0
- data/spec/scss_lint/linter/duplicate_property_spec.rb +189 -0
- data/spec/scss_lint/linter/else_placement_spec.rb +106 -0
- data/spec/scss_lint/linter/empty_line_between_blocks_spec.rb +276 -0
- data/spec/scss_lint/linter/empty_rule_spec.rb +27 -0
- data/spec/scss_lint/linter/final_newline_spec.rb +49 -0
- data/spec/scss_lint/linter/hex_length_spec.rb +104 -0
- data/spec/scss_lint/linter/hex_notation_spec.rb +104 -0
- data/spec/scss_lint/linter/hex_validation_spec.rb +40 -0
- data/spec/scss_lint/linter/id_selector_spec.rb +62 -0
- data/spec/scss_lint/linter/import_path_spec.rb +300 -0
- data/spec/scss_lint/linter/important_rule_spec.rb +43 -0
- data/spec/scss_lint/linter/indentation_spec.rb +347 -0
- data/spec/scss_lint/linter/leading_zero_spec.rb +233 -0
- data/spec/scss_lint/linter/mergeable_selector_spec.rb +283 -0
- data/spec/scss_lint/linter/name_format_spec.rb +282 -0
- data/spec/scss_lint/linter/nesting_depth_spec.rb +114 -0
- data/spec/scss_lint/linter/placeholder_in_extend_spec.rb +63 -0
- data/spec/scss_lint/linter/property_count_spec.rb +104 -0
- data/spec/scss_lint/linter/property_sort_order_spec.rb +482 -0
- data/spec/scss_lint/linter/property_spelling_spec.rb +84 -0
- data/spec/scss_lint/linter/property_units_spec.rb +229 -0
- data/spec/scss_lint/linter/qualifying_element_spec.rb +125 -0
- data/spec/scss_lint/linter/selector_depth_spec.rb +159 -0
- data/spec/scss_lint/linter/selector_format_spec.rb +632 -0
- data/spec/scss_lint/linter/shorthand_spec.rb +198 -0
- data/spec/scss_lint/linter/single_line_per_property_spec.rb +73 -0
- data/spec/scss_lint/linter/single_line_per_selector_spec.rb +130 -0
- data/spec/scss_lint/linter/space_after_comma_spec.rb +332 -0
- data/spec/scss_lint/linter/space_after_property_colon_spec.rb +373 -0
- data/spec/scss_lint/linter/space_after_property_name_spec.rb +37 -0
- data/spec/scss_lint/linter/space_before_brace_spec.rb +829 -0
- data/spec/scss_lint/linter/space_between_parens_spec.rb +263 -0
- data/spec/scss_lint/linter/string_quotes_spec.rb +335 -0
- data/spec/scss_lint/linter/trailing_semicolon_spec.rb +304 -0
- data/spec/scss_lint/linter/trailing_zero_spec.rb +176 -0
- data/spec/scss_lint/linter/unnecessary_mantissa_spec.rb +67 -0
- data/spec/scss_lint/linter/unnecessary_parent_reference_spec.rb +98 -0
- data/spec/scss_lint/linter/url_format_spec.rb +55 -0
- data/spec/scss_lint/linter/url_quotes_spec.rb +73 -0
- data/spec/scss_lint/linter/variable_for_property_spec.rb +145 -0
- data/spec/scss_lint/linter/vendor_prefix_spec.rb +371 -0
- data/spec/scss_lint/linter/zero_unit_spec.rb +113 -0
- data/spec/scss_lint/linter_registry_spec.rb +50 -0
- data/spec/scss_lint/linter_spec.rb +292 -0
- data/spec/scss_lint/location_spec.rb +42 -0
- data/spec/scss_lint/options_spec.rb +34 -0
- data/spec/scss_lint/rake_task_spec.rb +43 -0
- data/spec/scss_lint/reporter/config_reporter_spec.rb +42 -0
- data/spec/scss_lint/reporter/default_reporter_spec.rb +73 -0
- data/spec/scss_lint/reporter/files_reporter_spec.rb +38 -0
- data/spec/scss_lint/reporter/json_reporter_spec.rb +96 -0
- data/spec/scss_lint/reporter/xml_reporter_spec.rb +103 -0
- data/spec/scss_lint/reporter_spec.rb +11 -0
- data/spec/scss_lint/runner_spec.rb +123 -0
- data/spec/scss_lint/selector_visitor_spec.rb +264 -0
- data/spec/spec_helper.rb +34 -0
- data/spec/support/isolated_environment.rb +25 -0
- data/spec/support/matchers/report_lint.rb +48 -0
- metadata +328 -0
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
module SCSSLint
|
|
2
|
+
# Stores a location of {Lint} in a source.
|
|
3
|
+
class Location
|
|
4
|
+
include Comparable
|
|
5
|
+
|
|
6
|
+
attr_reader :line, :column, :length
|
|
7
|
+
|
|
8
|
+
# @param line [Integer] One-based index
|
|
9
|
+
# @param column [Integer] One-based index
|
|
10
|
+
# @param length [Integer] Number of characters, including the first character
|
|
11
|
+
def initialize(line = 1, column = 1, length = 1)
|
|
12
|
+
raise ArgumentError, "Line must be more than 0, passed #{line}" if line < 1
|
|
13
|
+
raise ArgumentError, "Column must be more than 0, passed #{column}" if column < 1
|
|
14
|
+
raise ArgumentError, "Length must be more than 0, passed #{length}" if length < 1
|
|
15
|
+
|
|
16
|
+
@line = line
|
|
17
|
+
@column = column
|
|
18
|
+
@length = length
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def ==(other)
|
|
22
|
+
[:line, :column, :length].all? do |attr|
|
|
23
|
+
send(attr) == other.send(attr)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
alias_method :eql?, :==
|
|
28
|
+
|
|
29
|
+
def <=>(other)
|
|
30
|
+
[:line, :column, :length].each do |attr|
|
|
31
|
+
result = send(attr) <=> other.send(attr)
|
|
32
|
+
return result unless result == 0
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
0
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
require 'optparse'
|
|
2
|
+
|
|
3
|
+
module SCSSLint
|
|
4
|
+
# Handles option parsing for the command line application.
|
|
5
|
+
class Options
|
|
6
|
+
DEFAULT_REPORTER = ['Default', :stdout]
|
|
7
|
+
|
|
8
|
+
# Parses command line options into an options hash.
|
|
9
|
+
#
|
|
10
|
+
# @param args [Array<String>] arguments passed via the command line
|
|
11
|
+
# @return [Hash] parsed options
|
|
12
|
+
def parse(args)
|
|
13
|
+
@options = {
|
|
14
|
+
reporters: [DEFAULT_REPORTER],
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
OptionParser.new do |parser|
|
|
18
|
+
parser.banner = "Usage: #{parser.program_name} [options] [scss-files]"
|
|
19
|
+
|
|
20
|
+
add_display_options parser
|
|
21
|
+
add_linter_options parser
|
|
22
|
+
add_file_options parser
|
|
23
|
+
add_info_options parser
|
|
24
|
+
end.parse!(args)
|
|
25
|
+
|
|
26
|
+
# Any remaining arguments are assumed to be files
|
|
27
|
+
@options[:files] = args
|
|
28
|
+
|
|
29
|
+
@options
|
|
30
|
+
rescue OptionParser::InvalidOption => ex
|
|
31
|
+
raise SCSSLint::Exceptions::InvalidCLIOption,
|
|
32
|
+
ex.message,
|
|
33
|
+
ex.backtrace
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
private
|
|
37
|
+
|
|
38
|
+
def add_display_options(parser)
|
|
39
|
+
parser.on('-f', '--format Formatter', 'Specify how to display lints', String) do |format|
|
|
40
|
+
define_output_format(format)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
parser.on('-r', '--require path', 'Require Ruby file', String) do |path|
|
|
44
|
+
@options[:required_paths] ||= []
|
|
45
|
+
@options[:required_paths] << path
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# @param format [String]
|
|
50
|
+
def define_output_format(format)
|
|
51
|
+
return if @options[:reporters] == [DEFAULT_REPORTER] && format == 'Default'
|
|
52
|
+
|
|
53
|
+
@options[:reporters].reject! { |i| i == DEFAULT_REPORTER }
|
|
54
|
+
@options[:reporters] << [format, :stdout]
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def add_linter_options(parser)
|
|
58
|
+
parser.on('-i', '--include-linter linter,...', Array,
|
|
59
|
+
'Specify which linters you want to run') do |linters|
|
|
60
|
+
@options[:included_linters] = linters
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
parser.on('-x', '--exclude-linter linter,...', Array,
|
|
64
|
+
"Specify which linters you don't want to run") do |linters|
|
|
65
|
+
@options[:excluded_linters] = linters
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def add_file_options(parser)
|
|
70
|
+
parser.on('-c', '--config config-file', String,
|
|
71
|
+
'Specify which configuration file you want to use') do |conf_file|
|
|
72
|
+
@options[:config_file] = conf_file
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
parser.on('-e', '--exclude file,...', Array,
|
|
76
|
+
'List of file names to exclude') do |files|
|
|
77
|
+
@options[:excluded_files] = files
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
parser.on('-o', '--out path', 'Write output to a file instead of STDOUT', String) do |path|
|
|
81
|
+
define_output_path(path)
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# @param path [String]
|
|
86
|
+
def define_output_path(path)
|
|
87
|
+
last_reporter, _output = @options[:reporters].pop
|
|
88
|
+
@options[:reporters] << [last_reporter, path]
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def add_info_options(parser)
|
|
92
|
+
parser.on_tail('--show-formatters', 'Shows available formatters') do
|
|
93
|
+
@options[:show_formatters] = true
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
parser.on_tail('--show-linters', 'Display available linters') do
|
|
97
|
+
@options[:show_linters] = true
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
parser.on_tail('-h', '--help', 'Display help documentation') do
|
|
101
|
+
@options[:help] = parser.help
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
parser.on_tail('-v', '--version', 'Display version') do
|
|
105
|
+
@options[:version] = true
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
require 'rake'
|
|
2
|
+
require 'rake/tasklib'
|
|
3
|
+
|
|
4
|
+
module SCSSLint
|
|
5
|
+
# Rake task for scss-lint CLI.
|
|
6
|
+
#
|
|
7
|
+
# @example
|
|
8
|
+
# # Add the following to your Rakefile...
|
|
9
|
+
# require 'scss_lint/rake_task'
|
|
10
|
+
# SCSSLint::RakeTask.new
|
|
11
|
+
#
|
|
12
|
+
# # ...and then execute from the command line:
|
|
13
|
+
# rake scss_lint
|
|
14
|
+
#
|
|
15
|
+
# You can also specify the list of files as explicit task arguments:
|
|
16
|
+
#
|
|
17
|
+
# @example
|
|
18
|
+
# # Add the following to your Rakefile...
|
|
19
|
+
# require 'scss_lint/rake_task'
|
|
20
|
+
# SCSSLint::RakeTask.new
|
|
21
|
+
#
|
|
22
|
+
# # ...and then execute from the command line (single quotes prevent shell
|
|
23
|
+
# # glob expansion and allow us to have a space after commas):
|
|
24
|
+
# rake 'scss_lint[app/assets/**/*.scss, other_files/**/*.scss]'
|
|
25
|
+
class RakeTask < Rake::TaskLib
|
|
26
|
+
# Name of the task.
|
|
27
|
+
# @return [String]
|
|
28
|
+
attr_accessor :name
|
|
29
|
+
|
|
30
|
+
# Configuration file to use.
|
|
31
|
+
# @return [String]
|
|
32
|
+
attr_accessor :config
|
|
33
|
+
|
|
34
|
+
# List of files to lint (can contain shell globs).
|
|
35
|
+
#
|
|
36
|
+
# Note that this will be ignored if you explicitly pass a list of files as
|
|
37
|
+
# task arguments via the command line or in the task definition.
|
|
38
|
+
# @return [Array<String>]
|
|
39
|
+
attr_accessor :files
|
|
40
|
+
|
|
41
|
+
# Create the task so it is accessible via +Rake::Task['scss_lint']+.
|
|
42
|
+
def initialize(name = :scss_lint)
|
|
43
|
+
@name = name
|
|
44
|
+
@files = ['.'] # Search for everything under current directory by default
|
|
45
|
+
@quiet = false
|
|
46
|
+
|
|
47
|
+
yield self if block_given?
|
|
48
|
+
|
|
49
|
+
define
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
private
|
|
53
|
+
|
|
54
|
+
def define
|
|
55
|
+
# Generate a default description if one hasn't been provided
|
|
56
|
+
desc default_description unless ::Rake.application.last_description
|
|
57
|
+
|
|
58
|
+
task(name, [:files]) do |_task, task_args|
|
|
59
|
+
# Lazy-load so task doesn't affect Rakefile load time
|
|
60
|
+
require 'scss_lint'
|
|
61
|
+
require 'scss_lint/cli'
|
|
62
|
+
|
|
63
|
+
run_cli(task_args)
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def run_cli(task_args)
|
|
68
|
+
cli_args = ['--config', config] if config
|
|
69
|
+
|
|
70
|
+
result = SCSSLint::CLI.new.run(Array(cli_args) + files_to_lint(task_args))
|
|
71
|
+
|
|
72
|
+
message =
|
|
73
|
+
case result
|
|
74
|
+
when CLI::EXIT_CODES[:error], CLI::EXIT_CODES[:warning]
|
|
75
|
+
'scss-lint found one or more lints'
|
|
76
|
+
when CLI::EXIT_CODES[:ok]
|
|
77
|
+
'scss-lint found no lints'
|
|
78
|
+
else
|
|
79
|
+
'scss-lint failed with an error'
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
puts message
|
|
83
|
+
exit result unless result == 0
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def files_to_lint(task_args)
|
|
87
|
+
# Note: we're abusing Rake's argument handling a bit here. We call the
|
|
88
|
+
# first argument `files` but it's actually only the first file--we pull
|
|
89
|
+
# the rest out of the `extras` from the task arguments. This is so we
|
|
90
|
+
# can specify an arbitrary list of files separated by commas on the
|
|
91
|
+
# command line or in a custom task definition.
|
|
92
|
+
explicit_files = Array(task_args[:files]) + Array(task_args.extras)
|
|
93
|
+
|
|
94
|
+
explicit_files.any? ? explicit_files : files
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# Friendly description that shows the full command that will be executed.
|
|
98
|
+
def default_description
|
|
99
|
+
description = 'Run `scss-lint'
|
|
100
|
+
description += " --config #{config}" if config
|
|
101
|
+
description += " #{files.join(' ')}" if files.any?
|
|
102
|
+
description += ' [files...]`'
|
|
103
|
+
description
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
module SCSSLint
|
|
2
|
+
# Responsible for displaying lints to the user in some format.
|
|
3
|
+
class Reporter
|
|
4
|
+
attr_reader :lints
|
|
5
|
+
|
|
6
|
+
def self.descendants
|
|
7
|
+
ObjectSpace.each_object(Class).select { |klass| klass < self }
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def initialize(lints)
|
|
11
|
+
@lints = lints
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def report_lints
|
|
15
|
+
raise NotImplementedError, 'You must implement report_lints'
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
module SCSSLint
|
|
2
|
+
# Returns a YAML configuration where all linters are disabled which
|
|
3
|
+
# caused a lint.
|
|
4
|
+
class Reporter::ConfigReporter < Reporter
|
|
5
|
+
def report_lints
|
|
6
|
+
{ 'linters' => disabled_linters }.to_yaml unless lints.empty?
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
private
|
|
10
|
+
|
|
11
|
+
def disabled_linters
|
|
12
|
+
linters.each_with_object({}) do |linter, m|
|
|
13
|
+
m[linter] = { 'enabled' => false }
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def linters
|
|
18
|
+
lints.map { |lint| linter_name(lint.linter) }.compact.uniq.sort
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def linter_name(linter)
|
|
22
|
+
return unless linter
|
|
23
|
+
linter.class.to_s.split('::').last
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
module SCSSLint
|
|
2
|
+
# Reports a single line per lint.
|
|
3
|
+
class Reporter::DefaultReporter < Reporter
|
|
4
|
+
def report_lints
|
|
5
|
+
return unless lints.any?
|
|
6
|
+
|
|
7
|
+
lints.map do |lint|
|
|
8
|
+
"#{location(lint)} #{type(lint)} #{message(lint)}"
|
|
9
|
+
end.join("\n") + "\n"
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
private
|
|
13
|
+
|
|
14
|
+
def location(lint)
|
|
15
|
+
"#{lint.filename.color(:cyan)}:#{lint.location.line.to_s.color(:magenta)}"
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def type(lint)
|
|
19
|
+
lint.error? ? '[E]'.color(:red) : '[W]'.color(:yellow)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def message(lint)
|
|
23
|
+
linter_name = "#{lint.linter.name}: ".color(:green) if lint.linter
|
|
24
|
+
"#{linter_name}#{lint.description}"
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
require 'json'
|
|
2
|
+
|
|
3
|
+
module SCSSLint
|
|
4
|
+
# Reports lints in a JSON format.
|
|
5
|
+
class Reporter::JSONReporter < Reporter
|
|
6
|
+
def report_lints
|
|
7
|
+
output = {}
|
|
8
|
+
lints.group_by(&:filename).each do |filename, file_lints|
|
|
9
|
+
output[filename] = file_lints.map do |lint|
|
|
10
|
+
issue_hash(lint)
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
JSON.pretty_generate(output)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
private
|
|
17
|
+
|
|
18
|
+
def issue_hash(lint)
|
|
19
|
+
{
|
|
20
|
+
'line' => lint.location.line,
|
|
21
|
+
'column' => lint.location.column,
|
|
22
|
+
'length' => lint.location.length,
|
|
23
|
+
'severity' => lint.severity,
|
|
24
|
+
'reason' => lint.description,
|
|
25
|
+
}.tap do |hash|
|
|
26
|
+
hash['linter'] = lint.linter.name if lint.linter
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
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
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
module SCSSLint
|
|
2
|
+
# Finds and aggregates all lints found by running the registered linters
|
|
3
|
+
# against a set of SCSS files.
|
|
4
|
+
class Runner
|
|
5
|
+
attr_reader :lints
|
|
6
|
+
|
|
7
|
+
# @param config [Config]
|
|
8
|
+
def initialize(config)
|
|
9
|
+
@config = config
|
|
10
|
+
@lints = []
|
|
11
|
+
@linters = LinterRegistry.linters.map(&:new)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# @param files [Array]
|
|
15
|
+
def run(files)
|
|
16
|
+
files.each do |file|
|
|
17
|
+
find_lints(file)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
private
|
|
22
|
+
|
|
23
|
+
# @param file [String]
|
|
24
|
+
def find_lints(file)
|
|
25
|
+
engine = Engine.new(file: file)
|
|
26
|
+
|
|
27
|
+
@linters.each do |linter|
|
|
28
|
+
begin
|
|
29
|
+
run_linter(linter, engine, file)
|
|
30
|
+
rescue => error
|
|
31
|
+
raise SCSSLint::Exceptions::LinterError,
|
|
32
|
+
"#{linter.class} raised unexpected error linting file #{file}: " \
|
|
33
|
+
"'#{error.message}'",
|
|
34
|
+
error.backtrace
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
rescue Sass::SyntaxError => ex
|
|
38
|
+
@lints << Lint.new(nil, ex.sass_filename, Location.new(ex.sass_line),
|
|
39
|
+
"Syntax Error: #{ex}", :error)
|
|
40
|
+
rescue FileEncodingError => ex
|
|
41
|
+
@lints << Lint.new(nil, file, Location.new, ex.to_s, :error)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# For stubbing in tests.
|
|
45
|
+
def run_linter(linter, engine, file)
|
|
46
|
+
return unless @config.linter_enabled?(linter)
|
|
47
|
+
return if @config.excluded_file_for_linter?(file, linter)
|
|
48
|
+
@lints += linter.run(engine, @config.linter_options(linter))
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|