scss-lint 0.24.1 → 0.25.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6a3663e2870c45af5654c5fea5a7289ac4fb9632
4
- data.tar.gz: 1167dbea3c255892fda1ccd621cb47b4b50f632f
3
+ metadata.gz: d8878aa5e26975ddb7c46f6bfd18f7db76e50a27
4
+ data.tar.gz: 729a1794663d878b450c6ed221ad3bd538c5f5bc
5
5
  SHA512:
6
- metadata.gz: 507b9deb0e2cbcde999f141ae35d9ebba74e80e045054334a0d448a94afadc3934b5963d88276cfee4be1f8ee98d3b1b4c0136f2ad1030b75554f9170a052c79
7
- data.tar.gz: 67c939b682e3b4f05d260ebc771a8a0c68455c4766025badf8d69ccecb91ffddabe01ef1b68af2bb69434707ea21c41bf6465645a8475d43125bbf13ffe43657
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)) && previous.line == node.line
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
- MINIMUM_SPACES_AFTER_COLON = 1
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
- if config['allow_extra_spaces']
13
- if spaces < MINIMUM_SPACES_AFTER_COLON
14
- add_lint node, 'Colon after property should be followed by ' \
15
- "at least #{pluralize(MINIMUM_SPACES_AFTER_COLON, 'space')}"
16
- end
17
- elsif spaces != MINIMUM_SPACES_AFTER_COLON
18
- add_lint node, 'Colon after property should be followed by ' \
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
@@ -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
@@ -1,4 +1,4 @@
1
1
  # Defines the gem version.
2
2
  module SCSSLint
3
- VERSION = '0.24.1'
3
+ VERSION = '0.25.0'
4
4
  end
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.24.1
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-05-21 00:00:00.000000000 Z
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.21.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.21.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