scss-lint 0.24.1 → 0.25.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 +5 -0
- data/lib/scss_lint/linter/else_placement.rb +48 -0
- data/lib/scss_lint/linter/empty_line_between_blocks.rb +0 -7
- data/lib/scss_lint/linter/indentation.rb +38 -2
- data/lib/scss_lint/linter/placeholder_in_extend.rb +6 -0
- data/lib/scss_lint/linter/space_after_property_colon.rb +48 -10
- data/lib/scss_lint/utils.rb +14 -0
- data/lib/scss_lint/version.rb +1 -1
- metadata +5 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d8878aa5e26975ddb7c46f6bfd18f7db76e50a27
|
4
|
+
data.tar.gz: 729a1794663d878b450c6ed221ad3bd538c5f5bc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 329e54beb7daf2457817fb6e9be9c69f603b3b058d11f1dc241fc36f25f7038b524f80e2e7a332b6bfe2f53d4f5e80b80cac202641489ff6a643faca0849d6ea
|
7
|
+
data.tar.gz: ee4adc133055f837029d44500a0ae360829985922fb96a1dbc6fe76da64d5d318b6d94b1c223855448b69fca2e602f143eb6e6c8b2f0c6f1bb685f9d6bd95782
|
data/config/default.yml
CHANGED
@@ -21,6 +21,10 @@ linters:
|
|
21
21
|
DuplicateProperty:
|
22
22
|
enabled: true
|
23
23
|
|
24
|
+
ElsePlacement:
|
25
|
+
enabled: true
|
26
|
+
style: same_line # or 'new_line'
|
27
|
+
|
24
28
|
EmptyLineBetweenBlocks:
|
25
29
|
enabled: true
|
26
30
|
ignore_single_line_blocks: true
|
@@ -87,6 +91,7 @@ linters:
|
|
87
91
|
|
88
92
|
SpaceAfterPropertyColon:
|
89
93
|
enabled: true
|
94
|
+
style: one_space # or 'no_space', or 'at_least_one_space', or 'aligned'
|
90
95
|
|
91
96
|
SpaceAfterPropertyName:
|
92
97
|
enabled: true
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module SCSSLint
|
2
|
+
# Checks where `@else` and `@else if` directives are placed with respect to
|
3
|
+
# the previous curly brace.
|
4
|
+
class Linter::ElsePlacement < Linter
|
5
|
+
include LinterRegistry
|
6
|
+
|
7
|
+
def visit_if(node)
|
8
|
+
visit_else(node, node.else) if node.else
|
9
|
+
end
|
10
|
+
|
11
|
+
def visit_else(if_node, else_node)
|
12
|
+
# Check each @else branch if there are multiple `@else if`s
|
13
|
+
visit_else(else_node, else_node.else) if else_node.else
|
14
|
+
|
15
|
+
# Skip @else statements on the same line as the previous @if, since we
|
16
|
+
# don't care about placement in that case
|
17
|
+
return if if_node.line == else_node.line
|
18
|
+
|
19
|
+
spaces = 0
|
20
|
+
while (char = character_at(else_node.source_range.start_pos, - (spaces + 1)))
|
21
|
+
if char == '}'
|
22
|
+
curly_on_same_line = true
|
23
|
+
break
|
24
|
+
end
|
25
|
+
spaces += 1
|
26
|
+
end
|
27
|
+
|
28
|
+
check_placement(else_node, curly_on_same_line)
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def check_placement(else_node, curly_on_same_line)
|
34
|
+
if same_line_preferred?
|
35
|
+
unless curly_on_same_line
|
36
|
+
add_lint(else_node,
|
37
|
+
'@else should be placed on same line as previous curly brace')
|
38
|
+
end
|
39
|
+
elsif curly_on_same_line
|
40
|
+
add_lint(else_node, '@else should be placed on its own line')
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def same_line_preferred?
|
45
|
+
config['style'] == 'same_line'
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -72,12 +72,5 @@ module SCSSLint
|
|
72
72
|
index = siblings.index(node)
|
73
73
|
siblings[index - 1] if index > 0 && siblings.count > 1
|
74
74
|
end
|
75
|
-
|
76
|
-
def node_siblings(node)
|
77
|
-
return unless node && node.node_parent
|
78
|
-
node.node_parent
|
79
|
-
.children
|
80
|
-
.select { |child| child.is_a?(Sass::Tree::Node) }
|
81
|
-
end
|
82
75
|
end
|
83
76
|
end
|
@@ -25,7 +25,9 @@ module SCSSLint
|
|
25
25
|
|
26
26
|
# Ignore the case where the node is on the same line as its previous
|
27
27
|
# sibling or its parent, as indentation isn't possible
|
28
|
-
return if (previous = previous_node(node)) &&
|
28
|
+
return if (previous = previous_node(node)) &&
|
29
|
+
(previous.line == node.line ||
|
30
|
+
previous.source_range.end_pos.line == node.line)
|
29
31
|
|
30
32
|
actual_indent = engine.lines[node.line - 1][/^(\s*)/, 1]
|
31
33
|
|
@@ -43,8 +45,34 @@ module SCSSLint
|
|
43
45
|
visit(node.else) if node.else
|
44
46
|
end
|
45
47
|
|
48
|
+
# Need to define this explicitly since @at-root directives can contain
|
49
|
+
# inline selectors which produces the same parse tree as if the selector was
|
50
|
+
# nested within it. For example:
|
51
|
+
#
|
52
|
+
# @at-root {
|
53
|
+
# .something {
|
54
|
+
# ...
|
55
|
+
# }
|
56
|
+
# }
|
57
|
+
#
|
58
|
+
# ...and...
|
59
|
+
#
|
60
|
+
# @at-root .something {
|
61
|
+
# ...
|
62
|
+
# }
|
63
|
+
#
|
64
|
+
# ...produce the same parse tree, but result in different indentation
|
65
|
+
# levels.
|
66
|
+
def visit_atroot(node, &block)
|
67
|
+
if at_root_contains_inline_selector?(node)
|
68
|
+
return if check_indentation(node)
|
69
|
+
yield
|
70
|
+
else
|
71
|
+
check_and_visit_children(node, &block)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
46
75
|
# Define node types that increase indentation level
|
47
|
-
alias_method :visit_atroot, :check_and_visit_children
|
48
76
|
alias_method :visit_directive, :check_and_visit_children
|
49
77
|
alias_method :visit_each, :check_and_visit_children
|
50
78
|
alias_method :visit_for, :check_and_visit_children
|
@@ -66,5 +94,13 @@ module SCSSLint
|
|
66
94
|
alias_method :visit_return, :check_indentation
|
67
95
|
alias_method :visit_variable, :check_indentation
|
68
96
|
alias_method :visit_warn, :check_indentation
|
97
|
+
|
98
|
+
private
|
99
|
+
|
100
|
+
def at_root_contains_inline_selector?(node)
|
101
|
+
return unless node.children.any?
|
102
|
+
|
103
|
+
same_position?(node.source_range.end_pos, node.children.first.source_range.start_pos)
|
104
|
+
end
|
69
105
|
end
|
70
106
|
end
|
@@ -4,9 +4,15 @@ module SCSSLint
|
|
4
4
|
include LinterRegistry
|
5
5
|
|
6
6
|
def visit_extend(node)
|
7
|
+
# Ignore if it cannot be statically determined that this selector is a
|
8
|
+
# placeholder since its prefix is dynamically generated
|
9
|
+
return if node.selector.first.is_a?(Sass::Script::Tree::Node)
|
10
|
+
|
7
11
|
# The array returned by the parser is a bit awkward in that it splits on
|
8
12
|
# every word boundary (so %placeholder becomes ['%', 'placeholder']).
|
9
13
|
selector = node.selector.join
|
14
|
+
|
15
|
+
# Ignore if this is a placeholder
|
10
16
|
return if selector.start_with?('%')
|
11
17
|
|
12
18
|
add_lint(node, 'Prefer using placeholder selectors (e.g. ' \
|
@@ -4,25 +4,63 @@ module SCSSLint
|
|
4
4
|
class Linter::SpaceAfterPropertyColon < Linter
|
5
5
|
include LinterRegistry
|
6
6
|
|
7
|
-
|
7
|
+
def visit_rule(node)
|
8
|
+
if config['style'] == 'aligned'
|
9
|
+
check_properties_alignment(node)
|
10
|
+
end
|
11
|
+
|
12
|
+
yield # Continue linting children
|
13
|
+
end
|
8
14
|
|
9
15
|
def visit_prop(node)
|
10
16
|
spaces = spaces_after_colon(node)
|
11
17
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
"#{pluralize(MINIMUM_SPACES_AFTER_COLON, 'space')} " \
|
20
|
-
"instead of #{pluralize(spaces, 'space')}"
|
18
|
+
case config['style']
|
19
|
+
when 'no_space'
|
20
|
+
check_for_no_spaces(node, spaces)
|
21
|
+
when 'one_space'
|
22
|
+
check_for_one_space(node, spaces)
|
23
|
+
when 'at_least_one_space'
|
24
|
+
check_for_at_least_one_space(node, spaces)
|
21
25
|
end
|
22
26
|
end
|
23
27
|
|
24
28
|
private
|
25
29
|
|
30
|
+
def check_for_no_spaces(node, spaces)
|
31
|
+
return if spaces == 0
|
32
|
+
add_lint(node, 'Colon after property should not be followed by any spaces')
|
33
|
+
end
|
34
|
+
|
35
|
+
def check_for_one_space(node, spaces)
|
36
|
+
return if spaces == 1
|
37
|
+
add_lint(node, 'Colon after property should be followed by one space')
|
38
|
+
end
|
39
|
+
|
40
|
+
def check_for_at_least_one_space(node, spaces)
|
41
|
+
return if spaces >= 1
|
42
|
+
add_lint(node, 'Colon after property should be followed by at least one space')
|
43
|
+
end
|
44
|
+
|
45
|
+
def check_properties_alignment(rule_node)
|
46
|
+
properties = rule_node.children.select { |node| node.is_a?(Sass::Tree::PropNode) }
|
47
|
+
|
48
|
+
properties.each_slice(2) do |prop1, prop2|
|
49
|
+
next unless prop2
|
50
|
+
next unless value_offset(prop1) != value_offset(prop2)
|
51
|
+
add_lint(prop1, 'Property values should be aligned')
|
52
|
+
break
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# Offset of value for property
|
57
|
+
def value_offset(prop)
|
58
|
+
src_range = prop.name_source_range
|
59
|
+
src_range.start_pos.offset +
|
60
|
+
(src_range.end_pos.offset - src_range.start_pos.offset) +
|
61
|
+
spaces_after_colon(prop)
|
62
|
+
end
|
63
|
+
|
26
64
|
def spaces_after_colon(node)
|
27
65
|
spaces = 0
|
28
66
|
offset = 1
|
data/lib/scss_lint/utils.rb
CHANGED
@@ -41,8 +41,22 @@ module SCSSLint
|
|
41
41
|
end
|
42
42
|
end
|
43
43
|
|
44
|
+
def node_siblings(node)
|
45
|
+
return unless node && node.node_parent
|
46
|
+
node.node_parent
|
47
|
+
.children
|
48
|
+
.select { |child| child.is_a?(Sass::Tree::Node) }
|
49
|
+
end
|
50
|
+
|
44
51
|
def pluralize(value, word)
|
45
52
|
value == 1 ? "#{value} #{word}" : "#{value} #{word}s"
|
46
53
|
end
|
54
|
+
|
55
|
+
# Sass doesn't define an equality operator for Sass::Source::Position
|
56
|
+
# objects, so we define a helper for our own use.
|
57
|
+
def same_position?(pos1, pos2)
|
58
|
+
return unless pos1 && pos2
|
59
|
+
pos1.line == pos2.line && pos1.offset == pos2.offset
|
60
|
+
end
|
47
61
|
end
|
48
62
|
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.25.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-
|
12
|
+
date: 2014-06-23 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rainbow
|
@@ -73,14 +73,14 @@ dependencies:
|
|
73
73
|
requirements:
|
74
74
|
- - '='
|
75
75
|
- !ruby/object:Gem::Version
|
76
|
-
version: 0.
|
76
|
+
version: 0.23.0
|
77
77
|
type: :development
|
78
78
|
prerelease: false
|
79
79
|
version_requirements: !ruby/object:Gem::Requirement
|
80
80
|
requirements:
|
81
81
|
- - '='
|
82
82
|
- !ruby/object:Gem::Version
|
83
|
-
version: 0.
|
83
|
+
version: 0.23.0
|
84
84
|
description: Configurable tool for writing clean and consistent SCSS
|
85
85
|
email:
|
86
86
|
- eng@causes.com
|
@@ -125,6 +125,7 @@ files:
|
|
125
125
|
- lib/scss_lint/linter/zero_unit.rb
|
126
126
|
- lib/scss_lint/linter/placeholder_in_extend.rb
|
127
127
|
- lib/scss_lint/linter/selector_depth.rb
|
128
|
+
- lib/scss_lint/linter/else_placement.rb
|
128
129
|
- lib/scss_lint/linter/hex_validation.rb
|
129
130
|
- lib/scss_lint/linter/compass/property_with_mixin.rb
|
130
131
|
- lib/scss_lint/linter/space_after_property_name.rb
|