forked from sds/scss-lint
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdeclaration_order.rb
71 lines (57 loc) · 2.08 KB
/
declaration_order.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
module SCSSLint
# Checks the order of nested items within a rule set.
class Linter::DeclarationOrder < Linter
include LinterRegistry
def check_order(node)
check_node(node)
yield # Continue linting children
end
alias_method :visit_rule, :check_order
alias_method :visit_mixin, :check_order
alias_method :visit_media, :check_order
private
MESSAGE =
'Rule sets should be ordered as follows: '\
'`@extends`, `@includes` without `@content`, ' \
'properties, `@includes` with `@content`, ' \
'nested rule sets'
MIXIN_WITH_CONTENT = 'mixin_with_content'
DECLARATION_ORDER = [
Sass::Tree::ExtendNode,
Sass::Tree::MixinNode,
Sass::Tree::PropNode,
MIXIN_WITH_CONTENT,
Sass::Tree::RuleNode,
]
def important_node?(node)
DECLARATION_ORDER.include?(node.class)
end
def check_node(node)
children = node.children.each_with_index
.select { |n, _| important_node?(n) }
.map { |n, i| [n, node_declaration_type(n), i] }
sorted_children = children.sort do |(_, a_type, i), (_, b_type, j)|
[DECLARATION_ORDER.index(a_type), i] <=> [DECLARATION_ORDER.index(b_type), j]
end
check_children_order(sorted_children, children)
end
# Find the child that is out of place
def check_children_order(sorted_children, children)
sorted_children.each_with_index do |sorted_item, index|
next if sorted_item == children[index]
add_lint(sorted_item.first.line,
"Expected item on line #{sorted_item.first.line} to appear " \
"before line #{children[index].first.line}. #{MESSAGE}")
break
end
end
def node_declaration_type(node)
# If the node has no children, return the class.
return node.class unless node.has_children
# If the node is a mixin with children, indicate that;
# otherwise, just return the class.
return node.class unless node.is_a?(Sass::Tree::MixinNode)
MIXIN_WITH_CONTENT
end
end
end