slim_lint 0.1.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 +7 -0
- data/bin/slim-lint +7 -0
- data/config/default.yml +38 -0
- data/lib/slim_lint/cli.rb +122 -0
- data/lib/slim_lint/configuration.rb +101 -0
- data/lib/slim_lint/configuration_loader.rb +68 -0
- data/lib/slim_lint/constants.rb +8 -0
- data/lib/slim_lint/document.rb +52 -0
- data/lib/slim_lint/engine.rb +27 -0
- data/lib/slim_lint/exceptions.rb +15 -0
- data/lib/slim_lint/file_finder.rb +69 -0
- data/lib/slim_lint/filters/inject_line_numbers.rb +35 -0
- data/lib/slim_lint/filters/sexp_converter.rb +11 -0
- data/lib/slim_lint/lint.rb +25 -0
- data/lib/slim_lint/linter/line_length.rb +19 -0
- data/lib/slim_lint/linter/redundant_div.rb +17 -0
- data/lib/slim_lint/linter/rubocop.rb +73 -0
- data/lib/slim_lint/linter/trailing_whitespace.rb +17 -0
- data/lib/slim_lint/linter.rb +49 -0
- data/lib/slim_lint/linter_registry.rb +26 -0
- data/lib/slim_lint/logger.rb +107 -0
- data/lib/slim_lint/options.rb +89 -0
- data/lib/slim_lint/rake_task.rb +107 -0
- data/lib/slim_lint/report.rb +16 -0
- data/lib/slim_lint/reporter/default_reporter.rb +39 -0
- data/lib/slim_lint/reporter/json_reporter.rb +44 -0
- data/lib/slim_lint/reporter.rb +36 -0
- data/lib/slim_lint/ruby_extract_engine.rb +43 -0
- data/lib/slim_lint/ruby_extractor.rb +91 -0
- data/lib/slim_lint/ruby_parser.rb +29 -0
- data/lib/slim_lint/runner.rb +72 -0
- data/lib/slim_lint/sexp.rb +90 -0
- data/lib/slim_lint/sexp_visitor.rb +105 -0
- data/lib/slim_lint/version.rb +4 -0
- data/lib/slim_lint.rb +40 -0
- metadata +149 -0
@@ -0,0 +1,91 @@
|
|
1
|
+
module SlimLint
|
2
|
+
# Utility class for extracting Ruby script from a Slim template that can then
|
3
|
+
# be linted with a Ruby linter (i.e. is "legal" Ruby).
|
4
|
+
#
|
5
|
+
# The goal is to turn this:
|
6
|
+
#
|
7
|
+
# - if items.any?
|
8
|
+
# table#items
|
9
|
+
# - for item in items
|
10
|
+
# tr
|
11
|
+
# td.name = item.name
|
12
|
+
# td.price = item.price
|
13
|
+
# - else
|
14
|
+
# p No items found.
|
15
|
+
#
|
16
|
+
# into (something like) this:
|
17
|
+
#
|
18
|
+
# if items.any?
|
19
|
+
# for item in items
|
20
|
+
# puts item.name
|
21
|
+
# puts item.price
|
22
|
+
# else
|
23
|
+
# puts 'No items found'
|
24
|
+
# end
|
25
|
+
#
|
26
|
+
# The translation won't be perfect, and won't make any real sense, but the
|
27
|
+
# relationship between variable declarations/uses and the flow control graph
|
28
|
+
# will remain intact.
|
29
|
+
class RubyExtractor
|
30
|
+
include SexpVisitor
|
31
|
+
extend SexpVisitor::DSL
|
32
|
+
|
33
|
+
attr_reader :source_map
|
34
|
+
|
35
|
+
# Extracts Ruby code from Sexp representing a Slim document.
|
36
|
+
#
|
37
|
+
# @param sexp [SlimLint::Sexp]
|
38
|
+
def extract(sexp)
|
39
|
+
trigger_pattern_callbacks(sexp)
|
40
|
+
@source_lines.join("\n")
|
41
|
+
end
|
42
|
+
|
43
|
+
on_start do |_sexp|
|
44
|
+
@source_lines = []
|
45
|
+
@source_map = {}
|
46
|
+
@line_count = 0
|
47
|
+
end
|
48
|
+
|
49
|
+
on [:html, :doctype] do |sexp|
|
50
|
+
append('puts', sexp)
|
51
|
+
end
|
52
|
+
|
53
|
+
on [:html, :tag] do |sexp|
|
54
|
+
append('puts', sexp)
|
55
|
+
end
|
56
|
+
|
57
|
+
on [:static] do |sexp|
|
58
|
+
append('puts', sexp)
|
59
|
+
end
|
60
|
+
|
61
|
+
on [:dynamic] do |sexp|
|
62
|
+
_, ruby = sexp
|
63
|
+
append(ruby, sexp)
|
64
|
+
end
|
65
|
+
|
66
|
+
on [:code] do |sexp|
|
67
|
+
_, ruby = sexp
|
68
|
+
append(ruby, sexp)
|
69
|
+
end
|
70
|
+
|
71
|
+
private
|
72
|
+
|
73
|
+
# Append code to the buffer.
|
74
|
+
#
|
75
|
+
# @param code [String]
|
76
|
+
# @param sexp [SlimLint::Sexp]
|
77
|
+
def append(code, sexp)
|
78
|
+
return if code.empty?
|
79
|
+
|
80
|
+
@source_lines << code
|
81
|
+
original_line = sexp.line
|
82
|
+
|
83
|
+
# For code that spans multiple lines, the resulting code will span
|
84
|
+
# multiple lines, so we need to create a mapping for each line.
|
85
|
+
(code.count("\n") + 1).times do
|
86
|
+
@line_count += 1
|
87
|
+
@source_map[@line_count] = original_line
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'astrolabe/builder'
|
2
|
+
require 'parser/current'
|
3
|
+
|
4
|
+
module SlimLint
|
5
|
+
# Parser for the Ruby language.
|
6
|
+
#
|
7
|
+
# This provides a convenient wrapper around the `parser` gem and the
|
8
|
+
# `astrolabe` integration to go with it. It is intended to be used for linter
|
9
|
+
# checks that require deep inspection of Ruby code.
|
10
|
+
class RubyParser
|
11
|
+
# Creates a reusable parser.
|
12
|
+
def initialize
|
13
|
+
@builder = ::Astrolabe::Builder.new
|
14
|
+
@parser = ::Parser::CurrentRuby.new(@builder)
|
15
|
+
end
|
16
|
+
|
17
|
+
# Parse the given Ruby source into an abstract syntax tree.
|
18
|
+
#
|
19
|
+
# @param source [String] Ruby source code
|
20
|
+
# @return [Array] syntax tree in the form returned by Parser gem
|
21
|
+
def parse(source)
|
22
|
+
buffer = ::Parser::Source::Buffer.new('(string)')
|
23
|
+
buffer.source = source
|
24
|
+
|
25
|
+
@parser.reset
|
26
|
+
@parser.parse(buffer)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
module SlimLint
|
2
|
+
# Responsible for running the applicable linters against the desired files.
|
3
|
+
class Runner
|
4
|
+
# Make the list of applicable files available
|
5
|
+
attr_reader :files
|
6
|
+
|
7
|
+
# Runs the appropriate linters against the desired files given the specified
|
8
|
+
# options.
|
9
|
+
#
|
10
|
+
# @param options [Hash]
|
11
|
+
# @raise [SlimLint::Exceptions::NoLintersError] when no linters are enabled
|
12
|
+
# @return [SlimLint::Report] a summary of all lints found
|
13
|
+
def run(options = {})
|
14
|
+
config = load_applicable_config(options)
|
15
|
+
files = extract_applicable_files(options, config)
|
16
|
+
linters = extract_enabled_linters(config, options)
|
17
|
+
|
18
|
+
raise SlimLint::Exceptions::NoLintersError, 'No linters specified' if linters.empty?
|
19
|
+
|
20
|
+
@lints = []
|
21
|
+
files.each do |file|
|
22
|
+
find_lints(file, linters, config)
|
23
|
+
end
|
24
|
+
|
25
|
+
SlimLint::Report.new(@lints, files)
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def load_applicable_config(options)
|
31
|
+
if options[:config_file]
|
32
|
+
SlimLint::ConfigurationLoader.load_file(options[:config_file])
|
33
|
+
else
|
34
|
+
SlimLint::ConfigurationLoader.load_applicable_config
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def extract_enabled_linters(config, options)
|
39
|
+
included_linters = LinterRegistry
|
40
|
+
.extract_linters_from(options.fetch(:included_linters, []))
|
41
|
+
|
42
|
+
included_linters = LinterRegistry.linters if included_linters.empty?
|
43
|
+
|
44
|
+
excluded_linters = LinterRegistry
|
45
|
+
.extract_linters_from(options.fetch(:excluded_linters, []))
|
46
|
+
|
47
|
+
# After filtering out explicitly included/excluded linters, only include
|
48
|
+
# linters which are enabled in the configuration
|
49
|
+
(included_linters - excluded_linters).map do |linter_class|
|
50
|
+
linter_config = config.for_linter(linter_class)
|
51
|
+
linter_class.new(linter_config) if linter_config['enabled']
|
52
|
+
end.compact
|
53
|
+
end
|
54
|
+
|
55
|
+
def find_lints(file, linters, config)
|
56
|
+
document = SlimLint::Document.new(File.read(file), file: file, config: config)
|
57
|
+
|
58
|
+
linters.each do |linter|
|
59
|
+
@lints += linter.run(document)
|
60
|
+
end
|
61
|
+
rescue Slim::Parser::SyntaxError => ex
|
62
|
+
@lints << Lint.new(nil, file, ex.line, ex.error, :error)
|
63
|
+
end
|
64
|
+
|
65
|
+
def extract_applicable_files(options, config)
|
66
|
+
included_patterns = options[:files]
|
67
|
+
excluded_files = options.fetch(:excluded_files, [])
|
68
|
+
|
69
|
+
SlimLint::FileFinder.new(config).find(included_patterns, excluded_files)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
module SlimLint
|
2
|
+
# Symbolic expression which represents tree-structured data.
|
3
|
+
#
|
4
|
+
# The main use of this particular implementation is to provide a single
|
5
|
+
# location for defining convenience helpers when operating on Sexps.
|
6
|
+
class Sexp < Array
|
7
|
+
# Stores the line number of the code in the original document that
|
8
|
+
# corresponds to this Sexp.
|
9
|
+
attr_accessor :line
|
10
|
+
|
11
|
+
# Creates an {Sexp} from the given {Array}-based Sexp, performing a deep
|
12
|
+
# copy.
|
13
|
+
def initialize(sexp)
|
14
|
+
sexp.each do |child|
|
15
|
+
item =
|
16
|
+
case child
|
17
|
+
when Array
|
18
|
+
Sexp.new(child)
|
19
|
+
else
|
20
|
+
child
|
21
|
+
end
|
22
|
+
|
23
|
+
push(item)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# Returns whether this {Sexp} matches the given Sexp pattern.
|
28
|
+
#
|
29
|
+
# A Sexp pattern is simply an incomplete Sexp prefix.
|
30
|
+
#
|
31
|
+
# @example
|
32
|
+
# The following Sexp:
|
33
|
+
#
|
34
|
+
# [:html, :doctype, "html5"]
|
35
|
+
#
|
36
|
+
# ...will match the given patterns:
|
37
|
+
#
|
38
|
+
# [:html]
|
39
|
+
# [:html, :doctype]
|
40
|
+
# [:html, :doctype, "html5"]
|
41
|
+
#
|
42
|
+
# Note that nested Sexps will also be matched, so be careful about the cost
|
43
|
+
# of matching against a complicated pattern.
|
44
|
+
#
|
45
|
+
# @param sexp_pattern [Sexp]
|
46
|
+
# @return [Boolean]
|
47
|
+
def match?(sexp_pattern)
|
48
|
+
# If there aren't enough items to compare then this obviously won't match
|
49
|
+
return unless length >= sexp_pattern.length
|
50
|
+
|
51
|
+
sexp_pattern.each_with_index do |sub_pattern, index|
|
52
|
+
case sub_pattern
|
53
|
+
when Array
|
54
|
+
return false unless self[index].match?(sub_pattern)
|
55
|
+
else
|
56
|
+
return false unless self[index] == sub_pattern
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
true
|
61
|
+
end
|
62
|
+
|
63
|
+
def display(depth = 1) # rubocop:disable Metrics/AbcSize
|
64
|
+
indentation = ' ' * 2 * depth
|
65
|
+
output = indentation
|
66
|
+
output = '['
|
67
|
+
output << "\n"
|
68
|
+
|
69
|
+
each_with_index do |nested_sexp, index|
|
70
|
+
output += indentation
|
71
|
+
|
72
|
+
case nested_sexp
|
73
|
+
when Sexp
|
74
|
+
output += nested_sexp.display(depth + 1)
|
75
|
+
else
|
76
|
+
output += nested_sexp.inspect
|
77
|
+
end
|
78
|
+
|
79
|
+
if index < length - 1
|
80
|
+
output += ",\n"
|
81
|
+
end
|
82
|
+
end
|
83
|
+
output << "\n"
|
84
|
+
output << ' ' * 2 * (depth - 1)
|
85
|
+
output << ']'
|
86
|
+
|
87
|
+
output
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
module SlimLint
|
2
|
+
# Provides an interface which when included allows a class to visit nodes in
|
3
|
+
# the Sexp of a Slim document.
|
4
|
+
module SexpVisitor
|
5
|
+
SexpPattern = Struct.new(:sexp, :callback_method_name)
|
6
|
+
|
7
|
+
# Traverse the Sexp looking for matches with registered patterns, firing
|
8
|
+
# callbacks for all matches.
|
9
|
+
#
|
10
|
+
# @param sexp [Sexp]
|
11
|
+
def trigger_pattern_callbacks(sexp)
|
12
|
+
on_start sexp
|
13
|
+
traverse sexp
|
14
|
+
end
|
15
|
+
|
16
|
+
# Traverse the given Sexp, firing callbacks if they are defined.
|
17
|
+
#
|
18
|
+
# @param sexp [Sexp]
|
19
|
+
def traverse(sexp)
|
20
|
+
block_called = false
|
21
|
+
|
22
|
+
# Define a block within the closure of this method so that pattern matcher
|
23
|
+
# blocks can call `yield` within their block definitions to force
|
24
|
+
# traversal of their children.
|
25
|
+
block = ->(action = :descend) do
|
26
|
+
block_called = true
|
27
|
+
case action
|
28
|
+
when Sexp
|
29
|
+
# User explicitly yielded a Sexp, indicating they want to control the
|
30
|
+
# flow of traversal. Traverse the Sexp they returned.
|
31
|
+
traverse(action)
|
32
|
+
when :descend
|
33
|
+
traverse_children(sexp)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
patterns.each do |pattern|
|
38
|
+
next unless sexp.match?(pattern.sexp)
|
39
|
+
|
40
|
+
result = method(pattern.callback_method_name).call(sexp, &block)
|
41
|
+
|
42
|
+
# Returning :stop indicates we should stop searching this Sexp
|
43
|
+
# (i.e. stop descending this branch of depth-first search).
|
44
|
+
# The `return` here is very intentional.
|
45
|
+
return if result == :stop # rubocop:disable Lint/NonLocalExitFromIterator
|
46
|
+
end
|
47
|
+
|
48
|
+
# If no pattern matchers called `yield` explicitly, continue traversing
|
49
|
+
# children by default (matchers can return `:stop` to not continue).
|
50
|
+
traverse_children(sexp) unless block_called
|
51
|
+
end
|
52
|
+
|
53
|
+
def traverse_children(sexp)
|
54
|
+
sexp.each do |nested_sexp|
|
55
|
+
traverse nested_sexp if nested_sexp.is_a?(Sexp)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
# Returns the list of registered Sexp patterns.
|
60
|
+
def patterns
|
61
|
+
self.class.patterns || []
|
62
|
+
end
|
63
|
+
|
64
|
+
# Executed before searching for any pattern matches.
|
65
|
+
#
|
66
|
+
# @param sexp [SlimLint::Sexp]
|
67
|
+
def on_start(*)
|
68
|
+
# Overidden by DSL.on_start
|
69
|
+
end
|
70
|
+
|
71
|
+
# Exposes a convenient Domain-specific Language (DSL) that makes declaring
|
72
|
+
# Sexp match patterns very easy.
|
73
|
+
#
|
74
|
+
# Include them with `extend SlimLint::SexpVisitor::DSL`
|
75
|
+
module DSL
|
76
|
+
# Registered patterns that this visitor will look for when traversing the
|
77
|
+
# Sexp.
|
78
|
+
attr_reader :patterns
|
79
|
+
|
80
|
+
# DSL helper that defines a sexp pattern and block that will be executed if
|
81
|
+
# the given pattern is found.
|
82
|
+
#
|
83
|
+
# @param sexp_pattern [Sexp]
|
84
|
+
def on(sexp_pattern, &block)
|
85
|
+
# TODO: Index Sexps on creation so we can quickly jump to potential
|
86
|
+
# matches instead of checking array.
|
87
|
+
@patterns ||= []
|
88
|
+
@pattern_number ||= 1
|
89
|
+
|
90
|
+
# Use a monotonically increasing number to identify the method so that in
|
91
|
+
# debugging we can simply look at the nth defintion in the class.
|
92
|
+
unique_method_name = :"on_pattern_#{@pattern_number}"
|
93
|
+
define_method(unique_method_name, block)
|
94
|
+
|
95
|
+
@pattern_number += 1
|
96
|
+
@patterns << SexpPattern.new(sexp_pattern, unique_method_name)
|
97
|
+
end
|
98
|
+
|
99
|
+
# Define a block of code to run before checking for any pattern matches.
|
100
|
+
def on_start(&block)
|
101
|
+
define_method(:on_start, block)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
data/lib/slim_lint.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
# Load all slim-lint modules necessary to parse and lint a file.
|
2
|
+
# Ordering here can be important depending on class references in each module.
|
3
|
+
|
4
|
+
require 'slim_lint/constants'
|
5
|
+
require 'slim_lint/exceptions'
|
6
|
+
require 'slim_lint/configuration'
|
7
|
+
require 'slim_lint/configuration_loader'
|
8
|
+
require 'slim_lint/sexp'
|
9
|
+
require 'slim_lint/file_finder'
|
10
|
+
require 'slim_lint/linter_registry'
|
11
|
+
require 'slim_lint/logger'
|
12
|
+
require 'slim_lint/version'
|
13
|
+
|
14
|
+
# Need to load slim before we can
|
15
|
+
require 'slim'
|
16
|
+
|
17
|
+
# Load all filters (required by SlimLint::Engine)
|
18
|
+
Dir[File.expand_path('slim_lint/filters/*.rb', File.dirname(__FILE__))].each do |file|
|
19
|
+
require file
|
20
|
+
end
|
21
|
+
|
22
|
+
require 'slim_lint/engine'
|
23
|
+
require 'slim_lint/document'
|
24
|
+
require 'slim_lint/sexp_visitor'
|
25
|
+
require 'slim_lint/lint'
|
26
|
+
require 'slim_lint/ruby_parser'
|
27
|
+
require 'slim_lint/linter'
|
28
|
+
require 'slim_lint/reporter'
|
29
|
+
require 'slim_lint/report'
|
30
|
+
require 'slim_lint/runner'
|
31
|
+
|
32
|
+
# Load all linters
|
33
|
+
Dir[File.expand_path('slim_lint/linter/*.rb', File.dirname(__FILE__))].each do |file|
|
34
|
+
require file
|
35
|
+
end
|
36
|
+
|
37
|
+
# Load all reporters
|
38
|
+
Dir[File.expand_path('slim_lint/reporter/*.rb', File.dirname(__FILE__))].each do |file|
|
39
|
+
require file
|
40
|
+
end
|
metadata
ADDED
@@ -0,0 +1,149 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: slim_lint
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Shane da Silva
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-04-19 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: slim
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '3.0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '3.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rubocop
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.25.0
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 0.25.0
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: sysexits
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.1'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.1'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '3.0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '3.0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rspec-its
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '1.0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '1.0'
|
83
|
+
description: Configurable tool for writing clean and consistent Slim templates
|
84
|
+
email:
|
85
|
+
- shane@dasilva.io
|
86
|
+
executables:
|
87
|
+
- slim-lint
|
88
|
+
extensions: []
|
89
|
+
extra_rdoc_files: []
|
90
|
+
files:
|
91
|
+
- bin/slim-lint
|
92
|
+
- config/default.yml
|
93
|
+
- lib/slim_lint.rb
|
94
|
+
- lib/slim_lint/cli.rb
|
95
|
+
- lib/slim_lint/configuration.rb
|
96
|
+
- lib/slim_lint/configuration_loader.rb
|
97
|
+
- lib/slim_lint/constants.rb
|
98
|
+
- lib/slim_lint/document.rb
|
99
|
+
- lib/slim_lint/engine.rb
|
100
|
+
- lib/slim_lint/exceptions.rb
|
101
|
+
- lib/slim_lint/file_finder.rb
|
102
|
+
- lib/slim_lint/filters/inject_line_numbers.rb
|
103
|
+
- lib/slim_lint/filters/sexp_converter.rb
|
104
|
+
- lib/slim_lint/lint.rb
|
105
|
+
- lib/slim_lint/linter.rb
|
106
|
+
- lib/slim_lint/linter/line_length.rb
|
107
|
+
- lib/slim_lint/linter/redundant_div.rb
|
108
|
+
- lib/slim_lint/linter/rubocop.rb
|
109
|
+
- lib/slim_lint/linter/trailing_whitespace.rb
|
110
|
+
- lib/slim_lint/linter_registry.rb
|
111
|
+
- lib/slim_lint/logger.rb
|
112
|
+
- lib/slim_lint/options.rb
|
113
|
+
- lib/slim_lint/rake_task.rb
|
114
|
+
- lib/slim_lint/report.rb
|
115
|
+
- lib/slim_lint/reporter.rb
|
116
|
+
- lib/slim_lint/reporter/default_reporter.rb
|
117
|
+
- lib/slim_lint/reporter/json_reporter.rb
|
118
|
+
- lib/slim_lint/ruby_extract_engine.rb
|
119
|
+
- lib/slim_lint/ruby_extractor.rb
|
120
|
+
- lib/slim_lint/ruby_parser.rb
|
121
|
+
- lib/slim_lint/runner.rb
|
122
|
+
- lib/slim_lint/sexp.rb
|
123
|
+
- lib/slim_lint/sexp_visitor.rb
|
124
|
+
- lib/slim_lint/version.rb
|
125
|
+
homepage: https://github.com/sds/slim-lint
|
126
|
+
licenses:
|
127
|
+
- MIT
|
128
|
+
metadata: {}
|
129
|
+
post_install_message:
|
130
|
+
rdoc_options: []
|
131
|
+
require_paths:
|
132
|
+
- lib
|
133
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
134
|
+
requirements:
|
135
|
+
- - ">="
|
136
|
+
- !ruby/object:Gem::Version
|
137
|
+
version: 2.0.0
|
138
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
139
|
+
requirements:
|
140
|
+
- - ">="
|
141
|
+
- !ruby/object:Gem::Version
|
142
|
+
version: '0'
|
143
|
+
requirements: []
|
144
|
+
rubyforge_project:
|
145
|
+
rubygems_version: 2.2.2
|
146
|
+
signing_key:
|
147
|
+
specification_version: 4
|
148
|
+
summary: Slim template linting tool
|
149
|
+
test_files: []
|