scss-lint 0.13.0 → 0.14.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/config/default.yml +4 -0
- data/lib/scss_lint/cli.rb +11 -4
- data/lib/scss_lint/config.rb +40 -12
- data/lib/scss_lint/engine.rb +2 -0
- data/lib/scss_lint/lint.rb +1 -0
- data/lib/scss_lint/linter/color_keyword.rb +1 -1
- data/lib/scss_lint/linter/declaration_order.rb +2 -2
- data/lib/scss_lint/linter/duplicate_property.rb +1 -0
- data/lib/scss_lint/linter/empty_rule.rb +1 -0
- data/lib/scss_lint/linter/hex_format.rb +1 -0
- data/lib/scss_lint/linter/selector_depth.rb +61 -0
- data/lib/scss_lint/linter/single_line_per_selector.rb +2 -2
- data/lib/scss_lint/linter/usage_name.rb +2 -0
- data/lib/scss_lint/linter_registry.rb +2 -1
- data/lib/scss_lint/reporter.rb +1 -0
- data/lib/scss_lint/reporter/default_reporter.rb +1 -0
- data/lib/scss_lint/reporter/xml_reporter.rb +1 -0
- data/lib/scss_lint/sass/script.rb +3 -0
- data/lib/scss_lint/sass/tree.rb +3 -0
- data/lib/scss_lint/version.rb +2 -1
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e0c38097da925d1dcc77a8cc9c4d90468e598abb
|
4
|
+
data.tar.gz: e5e2f0352fc1e808b3ebe147c200c24727e425d0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0e65ae3133dbdefac6e650b8561db659671280f659d050d37c5dc0704b3b592ac1d7ab8303a936ccaf0aa6fab6a02c50a2e8be254039e5cfc2caa741890cf600
|
7
|
+
data.tar.gz: e7677e4fe7bbc9337884d8cc423105a08d77361d9d50369ae41c4677677cf8626e920e791592d715db56d763dca2d91292469453a61b4201dbe66c1e3be25419
|
data/config/default.yml
CHANGED
data/lib/scss_lint/cli.rb
CHANGED
@@ -57,6 +57,10 @@ module SCSSLint
|
|
57
57
|
@options[:excluded_files] = files
|
58
58
|
end
|
59
59
|
|
60
|
+
opts.on('-f', '--format Formatter', 'Specify how to display lints', String) do |format|
|
61
|
+
set_output_format(format)
|
62
|
+
end
|
63
|
+
|
60
64
|
opts.on('-i', '--include-linter linter,...', Array,
|
61
65
|
'Specify which linters you want to run') do |linters|
|
62
66
|
@options[:included_linters] = linters
|
@@ -78,10 +82,6 @@ module SCSSLint
|
|
78
82
|
opts.on_tail('-v', '--version', 'Show version') do
|
79
83
|
print_version opts.program_name, VERSION
|
80
84
|
end
|
81
|
-
|
82
|
-
opts.on('--xml', 'Output the results in XML format') do
|
83
|
-
@options[:reporter] = SCSSLint::Reporter::XMLReporter
|
84
|
-
end
|
85
85
|
end
|
86
86
|
end
|
87
87
|
|
@@ -175,6 +175,13 @@ module SCSSLint
|
|
175
175
|
print output if output
|
176
176
|
end
|
177
177
|
|
178
|
+
def set_output_format(format)
|
179
|
+
@options[:reporter] = SCSSLint::Reporter.const_get(format + 'Reporter')
|
180
|
+
rescue NameError
|
181
|
+
puts "Invalid output format specified: #{format}"
|
182
|
+
halt :config
|
183
|
+
end
|
184
|
+
|
178
185
|
def print_linters
|
179
186
|
puts 'Installed linters:'
|
180
187
|
|
data/lib/scss_lint/config.rb
CHANGED
@@ -68,27 +68,49 @@ module SCSSLint
|
|
68
68
|
YAML.load(file_contents).to_hash
|
69
69
|
end
|
70
70
|
|
71
|
+
options = convert_single_options_to_arrays(options)
|
72
|
+
options = extend_inherited_configs(options, file)
|
73
|
+
options = merge_wildcard_linter_options(options)
|
74
|
+
options = ensure_exclude_paths_are_absolute(options, file)
|
75
|
+
options
|
76
|
+
end
|
77
|
+
|
78
|
+
# Convert any config options that accept a single value or an array to an
|
79
|
+
# array form so that merging works.
|
80
|
+
def convert_single_options_to_arrays(options)
|
81
|
+
options = options.dup
|
82
|
+
|
71
83
|
if options['exclude']
|
72
84
|
# Ensure exclude is an array, since we allow user to specify a single
|
73
85
|
# string. We do this before merging with the config loaded via
|
74
|
-
#
|
86
|
+
# inherit_from since this allows us to merge the excludes from that,
|
75
87
|
# rather than overwriting them.
|
76
88
|
options['exclude'] = [options['exclude']].flatten
|
77
89
|
end
|
78
90
|
|
79
|
-
|
80
|
-
|
81
|
-
load_options_hash_from_file(path_relative_to_config(include_file, file))
|
82
|
-
end
|
91
|
+
options
|
92
|
+
end
|
83
93
|
|
84
|
-
|
85
|
-
|
86
|
-
|
94
|
+
# Loads and extends a list of inherited options with the given options.
|
95
|
+
def extend_inherited_configs(options, original_file)
|
96
|
+
return options unless options['inherit_from']
|
97
|
+
options = options.dup
|
87
98
|
|
88
|
-
|
99
|
+
includes = [options.delete('inherit_from')].flatten.map do |include_file|
|
100
|
+
load_options_hash_from_file(path_relative_to_config(include_file, original_file))
|
89
101
|
end
|
90
102
|
|
91
|
-
|
103
|
+
merged_includes = includes[1..-1].inject(includes.first) do |merged, include_file|
|
104
|
+
smart_merge(merged, include_file)
|
105
|
+
end
|
106
|
+
|
107
|
+
smart_merge(merged_includes, options)
|
108
|
+
end
|
109
|
+
|
110
|
+
# Merge options from wildcard linters into individual linter configs
|
111
|
+
def merge_wildcard_linter_options(options)
|
112
|
+
options = options.dup
|
113
|
+
|
92
114
|
options.fetch('linters', {}).keys.each do |class_name|
|
93
115
|
next unless class_name.include?('*')
|
94
116
|
|
@@ -106,7 +128,13 @@ module SCSSLint
|
|
106
128
|
end
|
107
129
|
end
|
108
130
|
|
109
|
-
|
131
|
+
options
|
132
|
+
end
|
133
|
+
|
134
|
+
# Ensure all excludes are absolute paths
|
135
|
+
def ensure_exclude_paths_are_absolute(options, original_file)
|
136
|
+
options = options.dup
|
137
|
+
|
110
138
|
if options['exclude']
|
111
139
|
excludes = [options['exclude']].flatten
|
112
140
|
|
@@ -115,7 +143,7 @@ module SCSSLint
|
|
115
143
|
exclusion_glob
|
116
144
|
else
|
117
145
|
# Expand the path assuming it is relative to the config file itself
|
118
|
-
File.expand_path(exclusion_glob, File.expand_path(File.dirname(
|
146
|
+
File.expand_path(exclusion_glob, File.expand_path(File.dirname(original_file)))
|
119
147
|
end
|
120
148
|
end
|
121
149
|
end
|
data/lib/scss_lint/engine.rb
CHANGED
data/lib/scss_lint/lint.rb
CHANGED
@@ -11,7 +11,7 @@ module SCSSLint
|
|
11
11
|
def visit_script_string(node)
|
12
12
|
return unless node.type == :identifier
|
13
13
|
|
14
|
-
remove_quoted_strings(node.value).scan(/[a-z]
|
14
|
+
remove_quoted_strings(node.value).scan(/(^|\s)([a-z]+)(?=\s|$)/i) do |_, word|
|
15
15
|
add_color_lint(node, word) if color_keyword?(word)
|
16
16
|
end
|
17
17
|
end
|
@@ -10,8 +10,8 @@ module SCSSLint
|
|
10
10
|
]
|
11
11
|
|
12
12
|
def visit_rule(node)
|
13
|
-
children = node.children.select { |
|
14
|
-
|
13
|
+
children = node.children.select { |n| important_node?(n) }
|
14
|
+
.map { |n| n.class }
|
15
15
|
|
16
16
|
sorted_children = children.sort do |a, b|
|
17
17
|
DECLARATION_ORDER.index(a) <=> DECLARATION_ORDER.index(b)
|
@@ -0,0 +1,61 @@
|
|
1
|
+
module SCSSLint
|
2
|
+
# Checks for selectors with large depths of applicability.
|
3
|
+
class Linter::SelectorDepth < Linter
|
4
|
+
include LinterRegistry
|
5
|
+
|
6
|
+
def visit_root(node)
|
7
|
+
@max_depth = config['max_depth']
|
8
|
+
@depth = 0
|
9
|
+
yield # Continue
|
10
|
+
end
|
11
|
+
|
12
|
+
def visit_rule(node)
|
13
|
+
old_depth = @depth
|
14
|
+
@depth = max_sequence_depth(node.parsed_rules, @depth)
|
15
|
+
|
16
|
+
if @depth > @max_depth
|
17
|
+
add_lint(node.parsed_rules || node,
|
18
|
+
'Selector should have depth of applicability no greater ' <<
|
19
|
+
"than #{@max_depth}, but was #{@depth}")
|
20
|
+
end
|
21
|
+
|
22
|
+
yield # Continue linting children
|
23
|
+
@depth = old_depth
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
# Find the maximum depth of all sequences in a comma sequence.
|
29
|
+
def max_sequence_depth(comma_sequence, current_depth)
|
30
|
+
# Sequence contains interpolation; assume a depth of 1
|
31
|
+
return current_depth + 1 unless comma_sequence
|
32
|
+
|
33
|
+
comma_sequence.members.map { |sequence| sequence_depth(sequence, current_depth) }.max
|
34
|
+
end
|
35
|
+
|
36
|
+
def sequence_depth(sequence, current_depth)
|
37
|
+
separators, simple_sequences = sequence.members.partition do |item|
|
38
|
+
item.is_a?(String)
|
39
|
+
end
|
40
|
+
|
41
|
+
parent_selectors = simple_sequences.count { |item| item.to_s == '&' }
|
42
|
+
|
43
|
+
# Take the number of simple sequences and subtract one for each sibling
|
44
|
+
# combinator, as these "combine" simple sequences such that they do not
|
45
|
+
# increase depth.
|
46
|
+
depth = simple_sequences.size -
|
47
|
+
separators.count { |item| item == '~' || item == '+' }
|
48
|
+
|
49
|
+
if parent_selectors > 0
|
50
|
+
# If parent selectors are present, add the current depth for each
|
51
|
+
# additional parent selector.
|
52
|
+
depth += parent_selectors * (current_depth - 1)
|
53
|
+
else
|
54
|
+
# Otherwise this just descends from the containing selector
|
55
|
+
depth += current_depth
|
56
|
+
end
|
57
|
+
|
58
|
+
depth
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -24,8 +24,8 @@ module SCSSLint
|
|
24
24
|
# can run a regex against.
|
25
25
|
def condense_to_string(sequence_list)
|
26
26
|
sequence_list.inject('') do |combined, string_or_script|
|
27
|
-
combined +
|
28
|
-
|
27
|
+
combined +
|
28
|
+
(string_or_script.is_a?(String) ? string_or_script : string_or_script.to_sass)
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
@@ -1,6 +1,7 @@
|
|
1
1
|
module SCSSLint
|
2
2
|
class NoSuchLinter < StandardError; end
|
3
3
|
|
4
|
+
# Stores all linters available to the application.
|
4
5
|
module LinterRegistry
|
5
6
|
@linters = []
|
6
7
|
|
@@ -16,7 +17,7 @@ module SCSSLint
|
|
16
17
|
begin
|
17
18
|
Linter.const_get(linter_name)
|
18
19
|
rescue NameError
|
19
|
-
raise NoSuchLinter
|
20
|
+
raise NoSuchLinter, "Linter #{linter_name} does not exist"
|
20
21
|
end
|
21
22
|
end
|
22
23
|
end
|
data/lib/scss_lint/reporter.rb
CHANGED
@@ -1,4 +1,7 @@
|
|
1
1
|
module Sass::Script
|
2
|
+
# Ignore documentation lints as these aren't original implementations.
|
3
|
+
# rubocop:disable Documentation
|
4
|
+
|
2
5
|
# Redefine some of the lexer helpers in order to store the original string
|
3
6
|
# with the created object so that the original string can be inspected rather
|
4
7
|
# than a typically normalized version.
|
data/lib/scss_lint/sass/tree.rb
CHANGED
@@ -3,6 +3,9 @@
|
|
3
3
|
# breaks the Sass compiler, but since we're only doing lints this is fine for
|
4
4
|
# now.
|
5
5
|
module Sass::Tree
|
6
|
+
# Ignore documentation lints as these aren't original implementations.
|
7
|
+
# rubocop:disable Documentation
|
8
|
+
|
6
9
|
# Define some common helper code for use in the various monkey patchings.
|
7
10
|
class Node
|
8
11
|
# Stores node for which this node is a direct child
|
data/lib/scss_lint/version.rb
CHANGED
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.
|
4
|
+
version: 0.14.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Causes Engineering
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-12-
|
12
|
+
date: 2013-12-12 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: colorize
|
@@ -103,6 +103,7 @@ files:
|
|
103
103
|
- lib/scss_lint/linter/declaration_order.rb
|
104
104
|
- lib/scss_lint/linter/zero_unit.rb
|
105
105
|
- lib/scss_lint/linter/placeholder_in_extend.rb
|
106
|
+
- lib/scss_lint/linter/selector_depth.rb
|
106
107
|
- lib/scss_lint/linter/compass/property_with_mixin.rb
|
107
108
|
- lib/scss_lint/linter/space_after_property_name.rb
|
108
109
|
- lib/scss_lint/linter/usage_name.rb
|
@@ -141,9 +142,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
141
142
|
version: '0'
|
142
143
|
requirements: []
|
143
144
|
rubyforge_project:
|
144
|
-
rubygems_version: 2.0.
|
145
|
+
rubygems_version: 2.0.14
|
145
146
|
signing_key:
|
146
147
|
specification_version: 4
|
147
148
|
summary: SCSS lint tool
|
148
149
|
test_files: []
|
149
|
-
has_rdoc:
|