slim_lint 0.36.0 → 0.37.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 +4 -4
- data/lib/slim_lint/corrector.rb +37 -15
- data/lib/slim_lint/lint.rb +4 -2
- data/lib/slim_lint/linter/comment_control_statement.rb +5 -1
- data/lib/slim_lint/linter/control_statement_spacing.rb +11 -2
- data/lib/slim_lint/linter/empty_control_statement.rb +3 -1
- data/lib/slim_lint/linter/empty_lines.rb +3 -1
- data/lib/slim_lint/linter/trailing_blank_lines.rb +5 -2
- data/lib/slim_lint/linter/zwsp.rb +3 -1
- data/lib/slim_lint/linter.rb +3 -1
- data/lib/slim_lint/options.rb +10 -3
- data/lib/slim_lint/version.rb +1 -1
- metadata +6 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 1ab51b789afce474d3a969052cf00dc0760a2d98706aa74d2d5f2daf2c58ad44
|
|
4
|
+
data.tar.gz: ad86883e7bb179a3f7f7c01c2aad5e07d57c359f790ca3541d3da78f3af17516
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7223d666bd6ae4e0c266431a5ab8edd34a89a7862ca6a7b7aca9f7171fcea57016a622ea95794372f11579ad62136e97279d54988f4c5e70f7bc3305f71c916e
|
|
7
|
+
data.tar.gz: 5de9a96b2055eeeae3f5af80053bf0af37f85d7821c874de7584da6a8a0837811dfe84aca1461c1b7c27c541bef306d08adb73d516a7efb3400790858b1b6d17
|
data/lib/slim_lint/corrector.rb
CHANGED
|
@@ -12,33 +12,55 @@ module SlimLint
|
|
|
12
12
|
# Applies every correctable lint's correction to the document's source
|
|
13
13
|
# and marks each applied lint as corrected.
|
|
14
14
|
#
|
|
15
|
+
# A correction maps the current text of its line to the corrected text:
|
|
16
|
+
# returning `nil` removes the line entirely, and returning a string
|
|
17
|
+
# containing embedded newlines replaces the line with multiple lines.
|
|
18
|
+
# Corrections are applied from the last line to the first so that a
|
|
19
|
+
# correction which adds or removes lines never invalidates the line
|
|
20
|
+
# numbers of corrections still waiting to be applied.
|
|
21
|
+
#
|
|
15
22
|
# @param lints [Array<SlimLint::Lint>]
|
|
16
23
|
# @return [String] the corrected source
|
|
17
24
|
def correct(lints)
|
|
18
|
-
|
|
25
|
+
# `-1` keeps a trailing empty element when the source ends with a
|
|
26
|
+
# newline, so the array can be joined back with "\n" to exactly
|
|
27
|
+
# reproduce the source (including its trailing newline, or lack of one).
|
|
28
|
+
lines = @document.source.split("\n", -1)
|
|
19
29
|
|
|
20
|
-
lints
|
|
30
|
+
correction_groups(lints).each do |line_number, line_lints|
|
|
21
31
|
index = line_number - 1
|
|
22
|
-
next unless lines
|
|
32
|
+
next unless index.between?(0, lines.length - 1)
|
|
23
33
|
|
|
24
|
-
|
|
25
|
-
lines[index] = lint.correction.call(lines[index])
|
|
26
|
-
lint.corrected = true
|
|
27
|
-
end
|
|
34
|
+
lines[index, 1] = apply_corrections(lines[index], line_lints)
|
|
28
35
|
end
|
|
29
36
|
|
|
30
|
-
|
|
37
|
+
@document.source_prefix + lines.join("\n")
|
|
31
38
|
end
|
|
32
39
|
|
|
33
40
|
private
|
|
34
41
|
|
|
35
|
-
#
|
|
36
|
-
#
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
+
# Groups correctable lints by line number, ordered from the last line to
|
|
43
|
+
# the first, so that a correction which adds or removes lines never
|
|
44
|
+
# invalidates the line numbers of corrections still waiting to be applied.
|
|
45
|
+
#
|
|
46
|
+
# @param lints [Array<SlimLint::Lint>]
|
|
47
|
+
# @return [Array<(Integer, Array<SlimLint::Lint>)>]
|
|
48
|
+
def correction_groups(lints)
|
|
49
|
+
lints.select(&:correctable?).group_by(&:line).sort_by { |line_number, _| -line_number }
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# @param line [String] current text of the line
|
|
53
|
+
# @param line_lints [Array<SlimLint::Lint>] lints reported on this line
|
|
54
|
+
# @return [Array<String>] replacement line(s) for this line, possibly empty
|
|
55
|
+
def apply_corrections(line, line_lints)
|
|
56
|
+
line_lints.each do |lint|
|
|
57
|
+
break if line.nil?
|
|
58
|
+
|
|
59
|
+
line = lint.correction.call(line)
|
|
60
|
+
lint.corrected = true
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
line.nil? ? [] : line.split("\n", -1)
|
|
42
64
|
end
|
|
43
65
|
end
|
|
44
66
|
end
|
data/lib/slim_lint/lint.rb
CHANGED
|
@@ -18,8 +18,10 @@ module SlimLint
|
|
|
18
18
|
# @return [Symbol] whether this lint is a warning or an error
|
|
19
19
|
attr_reader :severity
|
|
20
20
|
|
|
21
|
-
# @return [Proc, nil] maps a line of source to its corrected version
|
|
22
|
-
# `nil`
|
|
21
|
+
# @return [Proc, nil] maps a line of source to its corrected version
|
|
22
|
+
# (`nil` to remove the line, or a string with embedded newlines to
|
|
23
|
+
# replace it with multiple lines), or `nil` if this lint has no known
|
|
24
|
+
# automatic correction
|
|
23
25
|
attr_reader :correction
|
|
24
26
|
|
|
25
27
|
# @return [Boolean] whether this lint's correction has been applied
|
|
@@ -4,6 +4,7 @@ module SlimLint
|
|
|
4
4
|
# Searches for control statements with only comments.
|
|
5
5
|
class Linter::CommentControlStatement < Linter
|
|
6
6
|
include LinterRegistry
|
|
7
|
+
support_autocorrect
|
|
7
8
|
|
|
8
9
|
on [:slim, :control] do |sexp|
|
|
9
10
|
_, _, code = sexp
|
|
@@ -16,7 +17,10 @@ module SlimLint
|
|
|
16
17
|
|
|
17
18
|
report_lint(sexp,
|
|
18
19
|
"Slim code comments (`/#{comment}`) are preferred over " \
|
|
19
|
-
"control statement comments (`-##{comment}`)"
|
|
20
|
+
"control statement comments (`-##{comment}`)",
|
|
21
|
+
correction: ->(line) {
|
|
22
|
+
line.sub(/-\s*#{Regexp.escape(code.to_s)}/, "/#{comment}")
|
|
23
|
+
})
|
|
20
24
|
end
|
|
21
25
|
end
|
|
22
26
|
end
|
|
@@ -4,10 +4,17 @@ module SlimLint
|
|
|
4
4
|
# Checks for missing or superfluous spacing before and after control statements.
|
|
5
5
|
class Linter::ControlStatementSpacing < Linter
|
|
6
6
|
include LinterRegistry
|
|
7
|
+
support_autocorrect
|
|
7
8
|
|
|
8
9
|
MESSAGE_OUTPUT = 'Please add a space before and after the `=`'
|
|
9
10
|
MESSAGE_CONTROL = 'Please add a space after the `-`'
|
|
10
11
|
|
|
12
|
+
# Matches the tag/attribute-shortcut selector, the `=`-based operator
|
|
13
|
+
# (`=`, `==`, `=<`, `=>`, `=<>`, `==<`, `==>`, `==<>`), and the whitespace
|
|
14
|
+
# surrounding the operator, so it can be normalized to a single space on
|
|
15
|
+
# either side without touching the Ruby code that follows.
|
|
16
|
+
OUTPUT_SPACING = /^(\s*)(\S+?)(\s*)(=[=<>]*)(\s*)/
|
|
17
|
+
|
|
11
18
|
on [:html, :tag, anything, [],
|
|
12
19
|
[:slim, :output, anything, capture(:ruby, anything)]] do |sexp|
|
|
13
20
|
# Fetch original Slim code that contains an element with a control statement.
|
|
@@ -20,7 +27,8 @@ module SlimLint
|
|
|
20
27
|
|
|
21
28
|
next if line =~ /[^ ] ==?<?>? [^ ]/
|
|
22
29
|
|
|
23
|
-
report_lint(sexp, MESSAGE_OUTPUT
|
|
30
|
+
report_lint(sexp, MESSAGE_OUTPUT,
|
|
31
|
+
correction: ->(source_line) { source_line.sub(OUTPUT_SPACING, '\1\2 \4 ') })
|
|
24
32
|
end
|
|
25
33
|
|
|
26
34
|
on [:slim, :control] do |sexp|
|
|
@@ -30,7 +38,8 @@ module SlimLint
|
|
|
30
38
|
|
|
31
39
|
next if line =~ /^ *- [^ ]/
|
|
32
40
|
|
|
33
|
-
report_lint(sexp, MESSAGE_CONTROL
|
|
41
|
+
report_lint(sexp, MESSAGE_CONTROL,
|
|
42
|
+
correction: ->(source_line) { source_line.sub(/^(\s*)-\s*/, '\1- ') })
|
|
34
43
|
end
|
|
35
44
|
|
|
36
45
|
private
|
|
@@ -4,12 +4,14 @@ module SlimLint
|
|
|
4
4
|
# Searches for control statements with no code.
|
|
5
5
|
class Linter::EmptyControlStatement < Linter
|
|
6
6
|
include LinterRegistry
|
|
7
|
+
support_autocorrect
|
|
7
8
|
|
|
8
9
|
on [:slim, :control] do |sexp|
|
|
9
10
|
_, _, code = sexp
|
|
10
11
|
next unless code[/\A\s*\Z/]
|
|
11
12
|
|
|
12
|
-
report_lint(sexp, 'Empty control statement can be removed'
|
|
13
|
+
report_lint(sexp, 'Empty control statement can be removed',
|
|
14
|
+
correction: ->(_line) { nil })
|
|
13
15
|
end
|
|
14
16
|
end
|
|
15
17
|
end
|
|
@@ -5,6 +5,7 @@ module SlimLint
|
|
|
5
5
|
# and for the first blank line in file.
|
|
6
6
|
class Linter::EmptyLines < Linter
|
|
7
7
|
include LinterRegistry
|
|
8
|
+
support_autocorrect
|
|
8
9
|
|
|
9
10
|
on_start do |_sexp|
|
|
10
11
|
dummy_node = Struct.new(:line)
|
|
@@ -14,7 +15,8 @@ module SlimLint
|
|
|
14
15
|
if line.blank?
|
|
15
16
|
if was_empty
|
|
16
17
|
report_lint(dummy_node.new(i + 1),
|
|
17
|
-
'Extra empty line detected'
|
|
18
|
+
'Extra empty line detected',
|
|
19
|
+
correction: ->(_line) { nil })
|
|
18
20
|
end
|
|
19
21
|
was_empty = true
|
|
20
22
|
else
|
|
@@ -4,6 +4,7 @@ module SlimLint
|
|
|
4
4
|
# This linter looks for trailing blank lines and a final newline.
|
|
5
5
|
class Linter::TrailingBlankLines < Linter
|
|
6
6
|
include LinterRegistry
|
|
7
|
+
support_autocorrect
|
|
7
8
|
|
|
8
9
|
on_start do |_sexp|
|
|
9
10
|
dummy_node = Struct.new(:line)
|
|
@@ -11,10 +12,12 @@ module SlimLint
|
|
|
11
12
|
|
|
12
13
|
if !document.source.end_with?("\n")
|
|
13
14
|
report_lint(dummy_node.new(document.source_lines.size),
|
|
14
|
-
'No blank line in the end of file'
|
|
15
|
+
'No blank line in the end of file',
|
|
16
|
+
correction: ->(line) { "#{line}\n" })
|
|
15
17
|
elsif document.source.lines.last.blank?
|
|
16
18
|
report_lint(dummy_node.new(document.source.lines.size),
|
|
17
|
-
'Multiple empty lines in the end of file'
|
|
19
|
+
'Multiple empty lines in the end of file',
|
|
20
|
+
correction: ->(_line) { nil })
|
|
18
21
|
end
|
|
19
22
|
end
|
|
20
23
|
end
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
module SlimLint
|
|
4
4
|
class Linter::Zwsp < Linter
|
|
5
5
|
include LinterRegistry
|
|
6
|
+
support_autocorrect
|
|
6
7
|
|
|
7
8
|
MSG = 'Remove zero-width space'
|
|
8
9
|
|
|
@@ -11,7 +12,8 @@ module SlimLint
|
|
|
11
12
|
document.source_lines.each_with_index do |line, index|
|
|
12
13
|
next unless line.include?("\u200b")
|
|
13
14
|
|
|
14
|
-
report_lint(dummy_node.new(index + 1), MSG
|
|
15
|
+
report_lint(dummy_node.new(index + 1), MSG,
|
|
16
|
+
correction: ->(source_line) { source_line.delete("\u200b") })
|
|
15
17
|
end
|
|
16
18
|
end
|
|
17
19
|
end
|
data/lib/slim_lint/linter.rb
CHANGED
|
@@ -65,7 +65,9 @@ module SlimLint
|
|
|
65
65
|
# @param node [#line] node to extract the line number from
|
|
66
66
|
# @param message [String] error/warning to display to the user
|
|
67
67
|
# @param correction [Proc, nil] maps the offending line of source to its
|
|
68
|
-
# corrected version, for linters that declared {support_autocorrect}
|
|
68
|
+
# corrected version, for linters that declared {support_autocorrect}.
|
|
69
|
+
# Return `nil` to remove the line entirely, or a string containing
|
|
70
|
+
# embedded newlines to replace it with multiple lines.
|
|
69
71
|
def report_lint(node, message, correction: nil)
|
|
70
72
|
return if disabled_for_line?(node.line)
|
|
71
73
|
|
data/lib/slim_lint/options.rb
CHANGED
|
@@ -5,6 +5,10 @@ require 'optparse'
|
|
|
5
5
|
module SlimLint
|
|
6
6
|
# Handles option parsing for the command line application.
|
|
7
7
|
class Options
|
|
8
|
+
# Path scanned by default when no files or directories are given on the
|
|
9
|
+
# command line.
|
|
10
|
+
DEFAULT_FILES = ['.'].freeze
|
|
11
|
+
|
|
8
12
|
# Parses command line options into an options hash.
|
|
9
13
|
#
|
|
10
14
|
# @param args [Array<String>] arguments passed via the command line
|
|
@@ -13,15 +17,18 @@ module SlimLint
|
|
|
13
17
|
@options = {}
|
|
14
18
|
|
|
15
19
|
OptionParser.new do |parser|
|
|
16
|
-
parser.banner = "Usage: #{APP_NAME} [options] [file1, file2, ...]"
|
|
20
|
+
parser.banner = "Usage: #{APP_NAME} [options] [file1, file2, ...]\n\n" \
|
|
21
|
+
'If no files or directories are given, the current ' \
|
|
22
|
+
'directory is scanned by default.'
|
|
17
23
|
|
|
18
24
|
add_linter_options parser
|
|
19
25
|
add_file_options parser
|
|
20
26
|
add_info_options parser
|
|
21
27
|
end.parse!(args)
|
|
22
28
|
|
|
23
|
-
# Any remaining arguments are assumed to be files
|
|
24
|
-
|
|
29
|
+
# Any remaining arguments are assumed to be files; fall back to
|
|
30
|
+
# DEFAULT_FILES when none are given
|
|
31
|
+
@options[:files] = args.empty? ? DEFAULT_FILES : args
|
|
25
32
|
|
|
26
33
|
@options
|
|
27
34
|
rescue OptionParser::InvalidOption => e
|
data/lib/slim_lint/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: slim_lint
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.37.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Shane da Silva
|
|
@@ -168,7 +168,11 @@ files:
|
|
|
168
168
|
homepage: https://github.com/sds/slim-lint
|
|
169
169
|
licenses:
|
|
170
170
|
- MIT
|
|
171
|
-
metadata:
|
|
171
|
+
metadata:
|
|
172
|
+
bug_tracker_uri: https://github.com/sds/slim-lint/issues
|
|
173
|
+
changelog_uri: https://github.com/sds/slim-lint/blob/main/CHANGELOG.md
|
|
174
|
+
source_code_uri: https://github.com/sds/slim-lint
|
|
175
|
+
rubygems_mfa_required: 'true'
|
|
172
176
|
rdoc_options: []
|
|
173
177
|
require_paths:
|
|
174
178
|
- lib
|