lib/scss_lint/linter/name_format.rb in scss-lint-0.19.0 vs lib/scss_lint/linter/name_format.rb in scss-lint-0.20.0
- old
+ new
@@ -3,40 +3,38 @@
# lowercase and use hyphens instead of underscores.
class Linter::NameFormat < Linter
include LinterRegistry
def visit_extend(node)
- if selector_has_bad_placeholder?(node.selector)
- add_name_lint(node, node.selector.join, 'placeholder')
- end
+ check_placeholder(node)
end
def visit_function(node)
- check_declared_name(node, 'function')
+ check_name(node, 'function')
yield # Continue into content block of this function definition
end
def visit_mixin(node)
- check_name_use(node, 'mixin')
+ check_name(node, 'mixin')
yield # Continue into content block of this mixin's block
end
def visit_mixindef(node)
- check_declared_name(node, 'mixin')
+ check_name(node, 'mixin')
yield # Continue into content block of this mixin definition
end
def visit_script_funcall(node)
- check_name_use(node, 'function') unless FUNCTION_WHITELIST.include?(node.name)
+ check_name(node, 'function') unless FUNCTION_WHITELIST.include?(node.name)
end
def visit_script_variable(node)
- check_name_use(node, 'variable')
+ check_name(node, 'variable')
end
def visit_variable(node)
- check_declared_name(node, 'variable')
+ check_name(node, 'variable')
yield # Continue into expression tree for this variable definition
end
private
@@ -45,34 +43,42 @@
scaleX scaleY scaleZ
skewX skewY
translateX translateY translateZ
].to_set
- def check_declared_name(node, node_type)
- if node_has_bad_name?(node)
- fixed_name = node.name.downcase.gsub(/_/, '-')
-
- add_lint(node, "Name of #{node_type} `#{node.name}` should " <<
- "be written in lowercase as `#{fixed_name}`")
+ def check_name(node, node_type, node_text = node.name)
+ if convention = violated_convention(node_text)
+ add_lint(node, "Name of #{node_type} `#{node_text}` should be " <<
+ "written #{convention[:explanation]}")
end
end
- def check_name_use(node, node_type)
- add_name_lint(node, node.name, node_type) if node_has_bad_name?(node)
+ def check_placeholder(node)
+ extract_string_selectors(node.selector).any? do |selector_str|
+ check_name(node, 'placeholder', selector_str.gsub('%', ''))
+ end
end
- def add_name_lint(node, name, node_type)
- fixed_name = name.downcase.gsub(/_/, '-')
+ CONVENTIONS = {
+ 'hyphenated_lowercase' => {
+ explanation: 'in lowercase with hyphens instead of underscores',
+ validator: ->(name) { name !~ /[_A-Z]/ },
+ },
+ 'BEM' => {
+ explanation: 'in BEM (Block Element Modifier) format',
+ validator: ->(name) { name !~ /[A-Z]|-{3}|_{3}|[^_]_[^_]/ },
+ },
+ }
- add_lint(node, "All uses of #{node_type} `#{name}` should be written " <<
- "in lowercase as `#{fixed_name}`")
- end
+ # Checks the given name and returns the violated convention if it failed.
+ def violated_convention(name_string)
+ convention_name = config['convention'] || 'hyphenated_lowercase'
- # Given a selector array, returns whether it contains any placeholder
- # selectors with invalid names.
- def selector_has_bad_placeholder?(selector_array)
- extract_string_selectors(selector_array).any? do |selector_str|
- selector_str =~ /%\w*#{INVALID_NAME_CHARS}/
- end
+ convention = CONVENTIONS[convention_name] || {
+ explanation: "must match regex /#{convention_name}/",
+ validator: ->(name) { name =~ /#{convention_name}/ }
+ }
+
+ convention unless convention[:validator].call(name_string)
end
end
end