forked from sds/scss-lint
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathstring_quotes.rb
94 lines (81 loc) · 3.21 KB
/
string_quotes.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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
module SCSSLint
# Checks the type of quotes used in string literals.
class Linter::StringQuotes < Linter
include LinterRegistry
def visit_comment(_node)
# Sass allows you to write Sass Script in non-silent comments (/* ... */).
# Unfortunately, it doesn't report correct source ranges for these script
# nodes.
# It's unlikely that a developer wanted to lint the script they wrote in a
# comment, so just ignore this case entirely and stop traversing the
# children of comment nodes.
end
def visit_script_stringinterpolation(node)
# We can't statically determine what the resultant string looks like when
# string interpolation is used, e.g. "one #{$var} three" could be a very
# different string depending on $var = `'" + "'` or $var = `two`.
#
# Thus we manually skip the substrings in the string interpolation and
# visit the expressions in the interpolation itself.
node.children.reject { |child| child.is_a?(Sass::Script::Tree::Literal) }
.each { |child| visit(child) }
end
def visit_script_string(node)
check_quotes(node, source_from_range(node.source_range))
end
def visit_import(node)
# `@import` source range conveniently includes only the quoted string
check_quotes(node, source_from_range(node.source_range))
end
def visit_charset(node)
# `@charset` source range includes entire declaration, so exclude that prefix
source = source_from_range(node.source_range)[('@charset'.length)..-1]
check_quotes(node, source)
end
private
def check_quotes(node, source)
source = source.strip
string = extract_string_without_quotes(source)
return unless string
case source[0]
when '"'
check_double_quotes(node, string)
when "'"
check_single_quotes(node, string)
end
end
STRING_WITHOUT_QUOTES_REGEX = %r{
\A
["'](.*)["'] # Extract text between quotes
\s*\)?\s*;?\s* # Sometimes the Sass parser includes a trailing ) or ;
(//.*)? # Exclude any trailing comments that might have snuck in
\z
}x
def extract_string_without_quotes(source)
return unless match = STRING_WITHOUT_QUOTES_REGEX.match(source)
match[1]
end
def check_double_quotes(node, string)
if config['style'] == 'single_quotes'
add_lint(node, 'Prefer single quoted strings') if string !~ /'/
else
if string =~ /(?<! \\) \\"/x && string !~ /'/
add_lint(node, 'Use single-quoted strings when writing double ' \
'quotes to avoid having to escape the double quotes')
end
end
end
def check_single_quotes(node, string)
if config['style'] == 'single_quotes'
if string =~ /(?<! \\) \\'/x && string !~ /"/
add_lint(node, 'Use double-quoted strings when writing single ' \
'quotes to avoid having to escape the single quotes')
elsif string =~ /(?<! \\) \\"/x
add_lint(node, "Don't escape double quotes in single-quoted strings")
end
else
add_lint(node, 'Prefer double-quoted strings') if string !~ /"/
end
end
end
end