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 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