scss-lint 0.16.1 → 0.17.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 +4 -4
- data/config/default.yml +7 -0
- data/lib/scss_lint/config.rb +25 -3
- data/lib/scss_lint/engine.rb +11 -0
- data/lib/scss_lint/linter.rb +23 -0
- data/lib/scss_lint/linter/selector_depth.rb +1 -0
- data/lib/scss_lint/linter/single_line_per_selector.rb +5 -9
- data/lib/scss_lint/linter/space_between_parens.rb +0 -15
- data/lib/scss_lint/linter/string_quotes.rb +75 -0
- data/lib/scss_lint/linter/url_quotes.rb +26 -0
- data/lib/scss_lint/reporter/files_reporter.rb +8 -0
- data/lib/scss_lint/runner.rb +3 -0
- data/lib/scss_lint/version.rb +1 -1
- metadata +9 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ee3e032cedba8042a60c3553efab8f57256e6d29
|
4
|
+
data.tar.gz: 4cc0c97f401c7d3fb69809a10a018ed6b963d5dd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a96e204786ee1c9c03753f89e76aabd7db21a6a65f595cfa757f7b6b02c3d69cb1b7c1aac4cdc0a97cd39038e39fd7aacf41e9bced89fd7913681af4eb4dfc3a
|
7
|
+
data.tar.gz: 65f3a369a456c75dcbfaa2a046c210e276a6f8a32d18c37bc32a7e646269a350eb3a599e9953d622a94e984d03349392072d74b881ee54779d21a0bbfa690797
|
data/config/default.yml
CHANGED
@@ -79,9 +79,16 @@ linters:
|
|
79
79
|
enabled: true
|
80
80
|
spaces: 0
|
81
81
|
|
82
|
+
StringQuotes:
|
83
|
+
enabled: true
|
84
|
+
style: single_quotes # or double_quotes
|
85
|
+
|
82
86
|
TrailingSemicolonAfterPropertyValue:
|
83
87
|
enabled: true
|
84
88
|
|
89
|
+
UrlQuotes:
|
90
|
+
enabled: true
|
91
|
+
|
85
92
|
UsageName:
|
86
93
|
enabled: true
|
87
94
|
|
data/lib/scss_lint/config.rb
CHANGED
@@ -62,16 +62,17 @@ module SCSSLint
|
|
62
62
|
file_contents = load_file_contents(file)
|
63
63
|
|
64
64
|
options =
|
65
|
-
if file_contents
|
66
|
-
|
65
|
+
if yaml = YAML.load(file_contents)
|
66
|
+
yaml.to_hash
|
67
67
|
else
|
68
|
-
|
68
|
+
{}
|
69
69
|
end
|
70
70
|
|
71
71
|
options = convert_single_options_to_arrays(options)
|
72
72
|
options = extend_inherited_configs(options, file)
|
73
73
|
options = merge_wildcard_linter_options(options)
|
74
74
|
options = ensure_exclude_paths_are_absolute(options, file)
|
75
|
+
options = ensure_linter_exclude_paths_are_absolute(options, file)
|
75
76
|
options
|
76
77
|
end
|
77
78
|
|
@@ -131,6 +132,19 @@ module SCSSLint
|
|
131
132
|
options
|
132
133
|
end
|
133
134
|
|
135
|
+
def ensure_linter_exclude_paths_are_absolute(options, original_file)
|
136
|
+
options = options.dup
|
137
|
+
|
138
|
+
options['linters'] ||= {}
|
139
|
+
|
140
|
+
options['linters'].keys.each do |linter_name|
|
141
|
+
options['linters'][linter_name] =
|
142
|
+
ensure_exclude_paths_are_absolute(options['linters'][linter_name], original_file)
|
143
|
+
end
|
144
|
+
|
145
|
+
options
|
146
|
+
end
|
147
|
+
|
134
148
|
# Ensure all excludes are absolute paths
|
135
149
|
def ensure_exclude_paths_are_absolute(options, original_file)
|
136
150
|
options = options.dup
|
@@ -227,6 +241,14 @@ module SCSSLint
|
|
227
241
|
end
|
228
242
|
end
|
229
243
|
|
244
|
+
def excluded_file_for_linter?(file_path, linter)
|
245
|
+
abs_path = File.expand_path(file_path)
|
246
|
+
|
247
|
+
linter_options(linter).fetch('exclude', []).any? do |exclusion_glob|
|
248
|
+
File.fnmatch(exclusion_glob, abs_path)
|
249
|
+
end
|
250
|
+
end
|
251
|
+
|
230
252
|
def exclude_file(file_path)
|
231
253
|
abs_path = File.expand_path(file_path)
|
232
254
|
|
data/lib/scss_lint/engine.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
require 'sass'
|
2
2
|
|
3
3
|
module SCSSLint
|
4
|
+
class FileEncodingError < StandardError; end
|
5
|
+
|
4
6
|
# Contains all information for a parsed SCSS file, including its name,
|
5
7
|
# contents, and parse tree.
|
6
8
|
class Engine
|
@@ -20,6 +22,15 @@ module SCSSLint
|
|
20
22
|
|
21
23
|
@lines = @contents.split("\n")
|
22
24
|
@tree = @engine.to_tree
|
25
|
+
rescue Encoding::UndefinedConversionError, ArgumentError => error
|
26
|
+
if error.is_a?(Encoding::UndefinedConversionError) ||
|
27
|
+
error.message.include?('invalid byte sequence')
|
28
|
+
raise FileEncodingError,
|
29
|
+
"Unable to parse SCSS file: #{error.to_s}",
|
30
|
+
error.backtrace
|
31
|
+
else
|
32
|
+
raise
|
33
|
+
end
|
23
34
|
end
|
24
35
|
end
|
25
36
|
end
|
data/lib/scss_lint/linter.rb
CHANGED
@@ -41,6 +41,29 @@ module SCSSLint
|
|
41
41
|
engine.lines[actual_line][actual_offset]
|
42
42
|
end
|
43
43
|
|
44
|
+
# Extracts the original source code given a range.
|
45
|
+
def source_from_range(source_range)
|
46
|
+
current_line = source_range.start_pos.line - 1
|
47
|
+
last_line = source_range.end_pos.line - 1
|
48
|
+
|
49
|
+
source = engine.lines[current_line][(source_range.start_pos.offset - 1)..-1]
|
50
|
+
|
51
|
+
current_line += 1
|
52
|
+
while current_line < last_line
|
53
|
+
source += "#{engine.lines[current_line]}\n"
|
54
|
+
current_line += 1
|
55
|
+
end
|
56
|
+
|
57
|
+
if source_range.start_pos.line != source_range.end_pos.line &&
|
58
|
+
# Sometimes the parser reports ranges ending on the first column of the
|
59
|
+
# line after the last line; don't include the last line in this case.
|
60
|
+
engine.lines.count == current_line - 1
|
61
|
+
source += "#{engine.lines[current_line][0...source_range.end_pos.offset]}\n"
|
62
|
+
end
|
63
|
+
|
64
|
+
source
|
65
|
+
end
|
66
|
+
|
44
67
|
# Monkey-patched implementation that adds support for traversing
|
45
68
|
# Sass::Script::Nodes (original implementation only supports
|
46
69
|
# Sass::Tree::Nodes).
|
@@ -4,16 +4,14 @@ module SCSSLint
|
|
4
4
|
include LinterRegistry
|
5
5
|
|
6
6
|
def visit_rule(node)
|
7
|
-
add_lint(node) if invalid_comma_placement?
|
7
|
+
add_lint(node, MESSAGE) if invalid_comma_placement?(node)
|
8
8
|
yield # Continue linting children
|
9
9
|
end
|
10
10
|
|
11
|
-
def description
|
12
|
-
'Each selector should be on its own line'
|
13
|
-
end
|
14
|
-
|
15
11
|
private
|
16
12
|
|
13
|
+
MESSAGE = 'Each selector in a comma sequence should be on its own line'
|
14
|
+
|
17
15
|
# A comma is invalid if it starts the line or is not the end of the line
|
18
16
|
def invalid_comma_placement?(node)
|
19
17
|
normalize_spacing(condense_to_string(node.rule)) =~ /\n,|,[^\n]/
|
@@ -23,10 +21,8 @@ module SCSSLint
|
|
23
21
|
# Sass::Script::Nodes, we need to condense it into a single string that we
|
24
22
|
# can run a regex against.
|
25
23
|
def condense_to_string(sequence_list)
|
26
|
-
sequence_list.
|
27
|
-
|
28
|
-
(string_or_script.is_a?(String) ? string_or_script : string_or_script.to_sass)
|
29
|
-
end
|
24
|
+
sequence_list.select { |item| item.is_a?(String) }
|
25
|
+
.inject('') { |combined, item| combined + item }
|
30
26
|
end
|
31
27
|
|
32
28
|
# Removes extra spacing between lines in a comma-separated sequence due to
|
@@ -19,21 +19,6 @@ module SCSSLint
|
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
22
|
-
#def visit_script_number(node)
|
23
|
-
#puts node.class
|
24
|
-
#puts node.node_parent.class
|
25
|
-
#puts node.node_parent.node_parent.class
|
26
|
-
#puts node.inspect
|
27
|
-
#yield
|
28
|
-
#end
|
29
|
-
|
30
|
-
#def visit_script_operation(node)
|
31
|
-
#puts node.node_parent.class
|
32
|
-
#puts node.inspect
|
33
|
-
#puts node.source_range.inspect
|
34
|
-
#yield
|
35
|
-
#end
|
36
|
-
|
37
22
|
private
|
38
23
|
|
39
24
|
def check(str, index, engine)
|
@@ -0,0 +1,75 @@
|
|
1
|
+
module SCSSLint
|
2
|
+
# Checks the type of quotes used in string literals.
|
3
|
+
class Linter::StringQuotes < Linter
|
4
|
+
include LinterRegistry
|
5
|
+
|
6
|
+
def visit_script_string(node)
|
7
|
+
check_quotes(node, source_from_range(node.source_range))
|
8
|
+
end
|
9
|
+
|
10
|
+
def visit_import(node)
|
11
|
+
# @import source range conveniently includes only the quoted string
|
12
|
+
check_quotes(node, source_from_range(node.source_range))
|
13
|
+
end
|
14
|
+
|
15
|
+
def visit_charset(node)
|
16
|
+
# @charset source range includes entire declaration, so exclude '@charset' prefix
|
17
|
+
source = source_from_range(node.source_range)[('@charset'.length)..-1]
|
18
|
+
|
19
|
+
check_quotes(node, source)
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def check_quotes(node, source)
|
25
|
+
source = source.strip
|
26
|
+
string = extract_string_without_quotes(source)
|
27
|
+
return unless string
|
28
|
+
|
29
|
+
case source[0]
|
30
|
+
when '"'
|
31
|
+
check_double_quotes(node, string)
|
32
|
+
when "'"
|
33
|
+
check_single_quotes(node, string)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
STRING_WITHOUT_QUOTES_REGEX = %r{
|
38
|
+
\A
|
39
|
+
["'](.*)["'] # Extract text between quotes
|
40
|
+
\s*\)?\s*;?\s* # Sometimes the Sass parser includes a trailing ) or ;
|
41
|
+
(//.*)? # Exclude any trailing comments that might have snuck in
|
42
|
+
\z
|
43
|
+
}x
|
44
|
+
|
45
|
+
def extract_string_without_quotes(source)
|
46
|
+
if match = STRING_WITHOUT_QUOTES_REGEX.match(source)
|
47
|
+
match[1]
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def check_double_quotes(node, string)
|
52
|
+
if config['style'] == 'single_quotes'
|
53
|
+
add_lint(node, 'Prefer single quoted strings') if string !~ /'/
|
54
|
+
else
|
55
|
+
if string =~ /(?<! \\) \\"/x && string !~ /'/
|
56
|
+
add_lint(node, 'Use single-quoted strings when writing double quotes ' +
|
57
|
+
'to avoid having to escape the double quotes')
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def check_single_quotes(node, string)
|
63
|
+
if config['style'] == 'single_quotes'
|
64
|
+
if string =~ /(?<! \\) \\'/x && string !~ /"/
|
65
|
+
add_lint(node, 'Use double-quoted strings when writing single quotes ' +
|
66
|
+
'to avoid having to escape the single quotes')
|
67
|
+
elsif string =~ /(?<! \\) \\"/x
|
68
|
+
add_lint(node, "Don't escape double quotes in single-quoted strings")
|
69
|
+
end
|
70
|
+
else
|
71
|
+
add_lint(node, 'Prefer double-quoted strings') if string !~ /"/
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module SCSSLint
|
2
|
+
# Checks for quotes in URLs.
|
3
|
+
class Linter::UrlQuotes < Linter
|
4
|
+
include LinterRegistry
|
5
|
+
|
6
|
+
def visit_prop(node)
|
7
|
+
case node.value
|
8
|
+
when Sass::Script::Tree::Literal
|
9
|
+
check(node, node.value.value.to_s)
|
10
|
+
when Sass::Script::Tree::ListLiteral
|
11
|
+
node.value.children.select { |child| child.is_a?(Sass::Script::Tree::Literal) }
|
12
|
+
.each { |child| check(node, child.value.to_s) }
|
13
|
+
end
|
14
|
+
|
15
|
+
yield
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def check(node, string)
|
21
|
+
if string =~ /^\s*url\(\s*[^"']/
|
22
|
+
add_lint(node, 'URLs should be enclosed in quotes')
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
data/lib/scss_lint/runner.rb
CHANGED
@@ -34,6 +34,7 @@ module SCSSLint
|
|
34
34
|
|
35
35
|
@linters.each do |linter|
|
36
36
|
next unless config.linter_enabled?(linter)
|
37
|
+
next if config.excluded_file_for_linter?(file, linter)
|
37
38
|
|
38
39
|
begin
|
39
40
|
linter.run(engine, config.linter_options(linter))
|
@@ -46,6 +47,8 @@ module SCSSLint
|
|
46
47
|
end
|
47
48
|
rescue Sass::SyntaxError => ex
|
48
49
|
@lints << Lint.new(ex.sass_filename, ex.sass_line, ex.to_s, :error)
|
50
|
+
rescue FileEncodingError => ex
|
51
|
+
@lints << Lint.new(file, 1, ex.to_s, :error)
|
49
52
|
end
|
50
53
|
end
|
51
54
|
end
|
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.17.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: 2014-01-
|
12
|
+
date: 2014-01-17 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: colorize
|
@@ -17,14 +17,14 @@ dependencies:
|
|
17
17
|
requirements:
|
18
18
|
- - '='
|
19
19
|
- !ruby/object:Gem::Version
|
20
|
-
version: 0.
|
20
|
+
version: 0.6.0
|
21
21
|
type: :runtime
|
22
22
|
prerelease: false
|
23
23
|
version_requirements: !ruby/object:Gem::Requirement
|
24
24
|
requirements:
|
25
25
|
- - '='
|
26
26
|
- !ruby/object:Gem::Version
|
27
|
-
version: 0.
|
27
|
+
version: 0.6.0
|
28
28
|
- !ruby/object:Gem::Dependency
|
29
29
|
name: sass
|
30
30
|
requirement: !ruby/object:Gem::Requirement
|
@@ -59,14 +59,14 @@ dependencies:
|
|
59
59
|
requirements:
|
60
60
|
- - '='
|
61
61
|
- !ruby/object:Gem::Version
|
62
|
-
version: 2.
|
62
|
+
version: 2.14.1
|
63
63
|
type: :development
|
64
64
|
prerelease: false
|
65
65
|
version_requirements: !ruby/object:Gem::Requirement
|
66
66
|
requirements:
|
67
67
|
- - '='
|
68
68
|
- !ruby/object:Gem::Version
|
69
|
-
version: 2.
|
69
|
+
version: 2.14.1
|
70
70
|
description: Opinionated tool to help write clean and consistent SCSS
|
71
71
|
email:
|
72
72
|
- eng@causes.com
|
@@ -81,6 +81,7 @@ files:
|
|
81
81
|
- lib/scss_lint/version.rb
|
82
82
|
- lib/scss_lint/constants.rb
|
83
83
|
- lib/scss_lint/utils.rb
|
84
|
+
- lib/scss_lint/reporter/files_reporter.rb
|
84
85
|
- lib/scss_lint/reporter/xml_reporter.rb
|
85
86
|
- lib/scss_lint/reporter/default_reporter.rb
|
86
87
|
- lib/scss_lint/runner.rb
|
@@ -110,6 +111,7 @@ files:
|
|
110
111
|
- lib/scss_lint/linter/space_after_property_name.rb
|
111
112
|
- lib/scss_lint/linter/property_spelling.rb
|
112
113
|
- lib/scss_lint/linter/usage_name.rb
|
114
|
+
- lib/scss_lint/linter/url_quotes.rb
|
113
115
|
- lib/scss_lint/linter/space_between_parens.rb
|
114
116
|
- lib/scss_lint/linter/border_zero.rb
|
115
117
|
- lib/scss_lint/linter/space_after_property_colon.rb
|
@@ -117,6 +119,7 @@ files:
|
|
117
119
|
- lib/scss_lint/linter/duplicate_property.rb
|
118
120
|
- lib/scss_lint/linter/hex_format.rb
|
119
121
|
- lib/scss_lint/linter/color_keyword.rb
|
122
|
+
- lib/scss_lint/linter/string_quotes.rb
|
120
123
|
- lib/scss_lint/linter/leading_zero.rb
|
121
124
|
- lib/scss_lint/linter/comment.rb
|
122
125
|
- lib/scss_lint/linter/empty_rule.rb
|