lib/scss_lint/linter/shorthand.rb in scss-lint-0.37.0 vs lib/scss_lint/linter/shorthand.rb in scss-lint-0.38.0
- old
+ new
@@ -1,11 +1,13 @@
+# rubocop:disable Metrics/CyclomaticComplexity
module SCSSLint
# Checks for the use of the shortest form for properties that can be written
# in shorthand.
class Linter::Shorthand < Linter
include LinterRegistry
+ # @param node [Sass::Tree::Node]
def visit_prop(node)
property_name = node.name.join
return unless SHORTHANDABLE_PROPERTIES.include?(property_name)
case node.value
@@ -25,14 +27,18 @@
border-width
margin
padding
]
+ # @param prop [String]
+ # @param list [Sass::Script::Tree::ListLiteral]
def check_script_list(prop, list)
check_shorthand(prop, list, list.children.map(&:to_sass))
end
+ # @param prop [String]
+ # @param literal [Sass::Script::Tree::Literal]
def check_script_literal(prop, literal)
value = literal.value
# HACK: node_parent may not be initialized at this point, so we need to
# set it ourselves
@@ -47,17 +53,22 @@
(\S+\s+\S+(\s+\S+){0,2}) # Two to four values separated by spaces
(\s+!\w+)? # Ignore `!important` priority overrides
\z
/x
+ # @param prop [String]
+ # @param script_string [Sass::Script::Value::String]
def check_script_string(prop, script_string)
return unless script_string.type == :identifier
return unless values = script_string.value.strip[LIST_LITERAL_REGEX, 1]
check_shorthand(prop, script_string, values.split)
end
+ # @param prop [String]
+ # @param node [Sass::Script::Value::String]
+ # @param values [Array<String>]
def check_shorthand(prop, node, values)
return unless (2..4).member?(values.count)
shortest_form = condensed_shorthand(*values)
return if values == shortest_form
@@ -65,30 +76,64 @@
add_lint(node, "Shorthand form for property `#{prop}` should be " \
"written more concisely as `#{shortest_form.join(' ')}` " \
"instead of `#{values.join(' ')}`")
end
+ # @param top [String]
+ # @param right [String]
+ # @param bottom [String]
+ # @param left [String]
+ # @return [Array]
def condensed_shorthand(top, right, bottom = nil, left = nil)
- if can_condense_to_one_value(top, right, bottom, left)
+ if condense_to_one_value?(top, right, bottom, left)
[top]
- elsif can_condense_to_two_values(top, right, bottom, left)
+ elsif condense_to_two_values?(top, right, bottom, left)
[top, right]
- elsif right == left
+ elsif condense_to_three_values?(top, right, bottom, left)
[top, right, bottom]
else
[top, right, bottom, left].compact
end
end
- def can_condense_to_one_value(top, right, bottom, left)
+ # @param top [String]
+ # @param right [String]
+ # @param bottom [String]
+ # @param left [String]
+ # @return [Boolean]
+ def condense_to_one_value?(top, right, bottom, left)
+ return unless allowed?(1)
return unless top == right
top == bottom && (bottom == left || left.nil?) ||
bottom.nil? && left.nil?
end
- def can_condense_to_two_values(top, right, bottom, left)
+ # @param top [String]
+ # @param right [String]
+ # @param bottom [String]
+ # @param left [String]
+ # @return [Boolean]
+ def condense_to_two_values?(top, right, bottom, left)
+ return unless allowed?(2)
+
top == bottom && right == left ||
top == bottom && left.nil? && top != right
+ end
+
+ # @param right [String]
+ # @param left [String]
+ # @return [Boolean]
+ def condense_to_three_values?(_, right, __, left)
+ return unless allowed?(3)
+
+ right == left
+ end
+
+ # @param size [Number]
+ # @return [Boolean]
+ def allowed?(size)
+ return false unless config['allowed_shorthands']
+ config['allowed_shorthands'].map(&:to_i).include?(size)
end
end
end