liquid_lint 1.0.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.
Files changed (61) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.md +1 -0
  3. data/bin/liquid-lint +7 -0
  4. data/config/default.yml +99 -0
  5. data/lib/liquid_lint/atom.rb +98 -0
  6. data/lib/liquid_lint/capture_map.rb +19 -0
  7. data/lib/liquid_lint/cli.rb +163 -0
  8. data/lib/liquid_lint/configuration.rb +109 -0
  9. data/lib/liquid_lint/configuration_loader.rb +86 -0
  10. data/lib/liquid_lint/constants.rb +10 -0
  11. data/lib/liquid_lint/document.rb +76 -0
  12. data/lib/liquid_lint/engine.rb +45 -0
  13. data/lib/liquid_lint/exceptions.rb +20 -0
  14. data/lib/liquid_lint/file_finder.rb +88 -0
  15. data/lib/liquid_lint/filters/attribute_processor.rb +31 -0
  16. data/lib/liquid_lint/filters/control_processor.rb +47 -0
  17. data/lib/liquid_lint/filters/inject_line_numbers.rb +43 -0
  18. data/lib/liquid_lint/filters/sexp_converter.rb +17 -0
  19. data/lib/liquid_lint/filters/splat_processor.rb +15 -0
  20. data/lib/liquid_lint/lint.rb +43 -0
  21. data/lib/liquid_lint/linter/comment_control_statement.rb +22 -0
  22. data/lib/liquid_lint/linter/consecutive_control_statements.rb +26 -0
  23. data/lib/liquid_lint/linter/control_statement_spacing.rb +24 -0
  24. data/lib/liquid_lint/linter/embedded_engines.rb +22 -0
  25. data/lib/liquid_lint/linter/empty_control_statement.rb +15 -0
  26. data/lib/liquid_lint/linter/empty_lines.rb +26 -0
  27. data/lib/liquid_lint/linter/file_length.rb +20 -0
  28. data/lib/liquid_lint/linter/line_length.rb +21 -0
  29. data/lib/liquid_lint/linter/redundant_div.rb +22 -0
  30. data/lib/liquid_lint/linter/rubocop.rb +116 -0
  31. data/lib/liquid_lint/linter/tab.rb +19 -0
  32. data/lib/liquid_lint/linter/tag_case.rb +15 -0
  33. data/lib/liquid_lint/linter/trailing_blank_lines.rb +21 -0
  34. data/lib/liquid_lint/linter/trailing_whitespace.rb +19 -0
  35. data/lib/liquid_lint/linter/zwsp.rb +18 -0
  36. data/lib/liquid_lint/linter.rb +93 -0
  37. data/lib/liquid_lint/linter_registry.rb +39 -0
  38. data/lib/liquid_lint/linter_selector.rb +79 -0
  39. data/lib/liquid_lint/logger.rb +103 -0
  40. data/lib/liquid_lint/matcher/anything.rb +11 -0
  41. data/lib/liquid_lint/matcher/base.rb +21 -0
  42. data/lib/liquid_lint/matcher/capture.rb +32 -0
  43. data/lib/liquid_lint/matcher/nothing.rb +13 -0
  44. data/lib/liquid_lint/options.rb +110 -0
  45. data/lib/liquid_lint/rake_task.rb +125 -0
  46. data/lib/liquid_lint/report.rb +25 -0
  47. data/lib/liquid_lint/reporter/checkstyle_reporter.rb +42 -0
  48. data/lib/liquid_lint/reporter/default_reporter.rb +41 -0
  49. data/lib/liquid_lint/reporter/emacs_reporter.rb +44 -0
  50. data/lib/liquid_lint/reporter/json_reporter.rb +52 -0
  51. data/lib/liquid_lint/reporter.rb +44 -0
  52. data/lib/liquid_lint/ruby_extract_engine.rb +36 -0
  53. data/lib/liquid_lint/ruby_extractor.rb +106 -0
  54. data/lib/liquid_lint/ruby_parser.rb +40 -0
  55. data/lib/liquid_lint/runner.rb +82 -0
  56. data/lib/liquid_lint/sexp.rb +106 -0
  57. data/lib/liquid_lint/sexp_visitor.rb +146 -0
  58. data/lib/liquid_lint/utils.rb +85 -0
  59. data/lib/liquid_lint/version.rb +6 -0
  60. data/lib/liquid_lint.rb +52 -0
  61. metadata +185 -0
@@ -0,0 +1,106 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LiquidLint
4
+ # Symbolic expression which represents tree-structured data.
5
+ #
6
+ # The main use of this particular implementation is to provide a single
7
+ # location for defining convenience helpers when operating on Sexps.
8
+ class Sexp < Array
9
+ # Stores the line number of the code in the original document that
10
+ # corresponds to this Sexp.
11
+ attr_accessor :line
12
+
13
+ # Creates an {Sexp} from the given {Array}-based Sexp.
14
+ #
15
+ # This provides a convenient way to convert between literal arrays of
16
+ # {Symbol}s and {Sexp}s containing {Atom}s and nested {Sexp}s. These objects
17
+ # all expose a similar API that conveniently allows the two objects to be
18
+ # treated similarly due to duck typing.
19
+ #
20
+ # @param array_sexp [Array]
21
+ def initialize(array_sexp)
22
+ array_sexp.each do |atom_or_sexp|
23
+ case atom_or_sexp
24
+ when Array
25
+ push Sexp.new(atom_or_sexp)
26
+ else
27
+ push LiquidLint::Atom.new(atom_or_sexp)
28
+ end
29
+ end
30
+ end
31
+
32
+ # Returns whether this {Sexp} matches the given Sexp pattern.
33
+ #
34
+ # A Sexp pattern is simply an incomplete Sexp prefix.
35
+ #
36
+ # @example
37
+ # The following Sexp:
38
+ #
39
+ # [:html, :doctype, "html5"]
40
+ #
41
+ # ...will match the given patterns:
42
+ #
43
+ # [:html]
44
+ # [:html, :doctype]
45
+ # [:html, :doctype, "html5"]
46
+ #
47
+ # Note that nested Sexps will also be matched, so be careful about the cost
48
+ # of matching against a complicated pattern.
49
+ #
50
+ # @param sexp_pattern [Object,Array]
51
+ # @return [Boolean]
52
+ def match?(sexp_pattern)
53
+ # Delegate matching logic if we're comparing against a matcher
54
+ if sexp_pattern.is_a?(LiquidLint::Matcher::Base)
55
+ return sexp_pattern.match?(self)
56
+ end
57
+
58
+ # If there aren't enough items to compare then this obviously won't match
59
+ return false unless sexp_pattern.is_a?(Array) && length >= sexp_pattern.length
60
+
61
+ sexp_pattern.each_with_index do |sub_pattern, index|
62
+ return false unless self[index].match?(sub_pattern)
63
+ end
64
+
65
+ true
66
+ end
67
+
68
+ # Returns pretty-printed representation of this S-expression.
69
+ #
70
+ # @return [String]
71
+ def inspect
72
+ display
73
+ end
74
+
75
+ protected
76
+
77
+ # Pretty-prints this Sexp in a form that is more readable.
78
+ #
79
+ # @param depth [Integer] indentation level to display Sexp at
80
+ # @return [String]
81
+ def display(depth = 1) # rubocop:disable Metrics/AbcSize
82
+ indentation = ' ' * 2 * depth
83
+ output = '['.dup
84
+
85
+ each_with_index do |nested_sexp, index|
86
+ output << "\n"
87
+ output += indentation
88
+
89
+ output +=
90
+ if nested_sexp.is_a?(LiquidLint::Sexp)
91
+ nested_sexp.display(depth + 1)
92
+ else
93
+ nested_sexp.inspect
94
+ end
95
+
96
+ # Add trailing comma unless this is the last item
97
+ output += ',' if index < length - 1
98
+ end
99
+
100
+ output << "\n" << ' ' * 2 * (depth - 1) unless empty?
101
+ output << ']'
102
+
103
+ output
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,146 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LiquidLint
4
+ # Provides an interface which when included allows a class to visit nodes in
5
+ # the Sexp of a Liquid document.
6
+ module SexpVisitor
7
+ # Traverse the Sexp looking for matches with registered patterns, firing
8
+ # callbacks for all matches.
9
+ #
10
+ # @param sexp [LiquidLint::Sexp]
11
+ def trigger_pattern_callbacks(sexp)
12
+ return if on_start(sexp) == :stop
13
+
14
+ traverse sexp
15
+ end
16
+
17
+ # Traverse the given Sexp, firing callbacks if they are defined.
18
+ #
19
+ # @param sexp [LiquidLint::Sexp]
20
+ def traverse(sexp)
21
+ patterns.each do |pattern|
22
+ next unless sexp.match?(pattern.sexp)
23
+
24
+ result = method(pattern.callback_method_name).call(sexp)
25
+
26
+ # Returning :stop indicates we should stop searching this Sexp
27
+ # (i.e. stop descending this branch of depth-first search).
28
+ # The `return` here is very intentional.
29
+ return if result == :stop # rubocop:disable Lint/NonLocalExitFromIterator
30
+ end
31
+
32
+ # Continue traversing children by default (match blocks can return `:stop`
33
+ # to not continue).
34
+ traverse_children(sexp)
35
+ end
36
+
37
+ # Traverse the children of this {Sexp}.
38
+ #
39
+ # @param sexp [LiquidLint::Sexp]
40
+ def traverse_children(sexp)
41
+ sexp.each do |nested_sexp|
42
+ traverse nested_sexp if nested_sexp.is_a?(Sexp)
43
+ end
44
+ end
45
+
46
+ # Returns the map of capture names to captured values.
47
+ #
48
+ # @return [Hash, CaptureMap]
49
+ def captures
50
+ self.class.captures || {}
51
+ end
52
+
53
+ # Returns the list of registered Sexp patterns.
54
+ #
55
+ # @return [Array<LiquidLint::SexpVisitor::SexpPattern>]
56
+ def patterns
57
+ self.class.patterns || []
58
+ end
59
+
60
+ # Executed before searching for any pattern matches.
61
+ #
62
+ # @param sexp [LiquidLint::Sexp] see {SexpVisitor::DSL.on_start}
63
+ # @return [Symbol] see {SexpVisitor::DSL.on_start}
64
+ def on_start(*)
65
+ # Overidden by DSL.on_start
66
+ end
67
+
68
+ # Mapping of Sexp pattern to callback method name.
69
+ #
70
+ # @attr_reader sexp [Array] S-expression pattern that when matched triggers the
71
+ # callback
72
+ # @attr_reader callback_method_name [Symbol] name of the method to call when pattern is matched
73
+ SexpPattern = Struct.new(:sexp, :callback_method_name)
74
+ private_constant :SexpPattern
75
+
76
+ # Exposes a convenient Domain-specific Language (DSL) that makes declaring
77
+ # Sexp match patterns very easy.
78
+ #
79
+ # Include them with `extend LiquidLint::SexpVisitor::DSL`
80
+ module DSL
81
+ # Registered patterns that this visitor will look for when traversing the
82
+ # {LiquidLint::Sexp}.
83
+ attr_reader :patterns
84
+
85
+ # @return [Hash] map of capture names to captured values
86
+ attr_reader :captures
87
+
88
+ # DSL helper that defines a sexp pattern and block that will be executed if
89
+ # the given pattern is found.
90
+ #
91
+ # @param sexp_pattern [Sexp]
92
+ # @yield block to execute when the specified pattern is matched
93
+ # @yieldparam sexp [LiquidLint::Sexp] Sexp that matched the pattern
94
+ # @yieldreturn [LiquidLint::Sexp,Symbol,void]
95
+ # If a Sexp is returned, indicates that traversal should jump directly
96
+ # to that Sexp.
97
+ # If `:stop` is returned, halts further traversal down this branch
98
+ # (i.e. stops recursing, but traversal at higher levels will continue).
99
+ # Otherwise traversal will continue as normal.
100
+ def on(sexp_pattern, &block)
101
+ # TODO: Index Sexps on creation so we can quickly jump to potential
102
+ # matches instead of checking array.
103
+ @patterns ||= []
104
+ @pattern_number ||= 1
105
+
106
+ # Use a monotonically increasing number to identify the method so that in
107
+ # debugging we can simply look at the nth defintion in the class.
108
+ unique_method_name = :"on_pattern_#{@pattern_number}"
109
+ define_method(unique_method_name, block)
110
+
111
+ @pattern_number += 1
112
+ @patterns << SexpPattern.new(sexp_pattern, unique_method_name)
113
+ end
114
+
115
+ # Define a block of code to run before checking for any pattern matches.
116
+ #
117
+ # @yield block to execute
118
+ # @yieldparam sexp [LiquidLint::Sexp] the root Sexp
119
+ # @yieldreturn [Symbol] if `:stop`, indicates that no further processing
120
+ # should occur
121
+ def on_start(&block)
122
+ define_method(:on_start, block)
123
+ end
124
+
125
+ # Represents a pattern that matches anything.
126
+ #
127
+ # @return [LiquidLint::Matcher::Anything]
128
+ def anything
129
+ LiquidLint::Matcher::Anything.new
130
+ end
131
+
132
+ # Represents a pattern that matches the specified matcher, storing the
133
+ # matched value in the captures list under the given name.
134
+ #
135
+ # @param capture_name [Symbol]
136
+ # @param matcher [LiquidLint::Matcher::Base]
137
+ # @return [LiquidLint::Matcher::Capture]
138
+ def capture(capture_name, matcher)
139
+ @captures ||= LiquidLint::CaptureMap.new
140
+
141
+ @captures[capture_name] =
142
+ LiquidLint::Matcher::Capture.from_matcher(matcher)
143
+ end
144
+ end
145
+ end
146
+ end
@@ -0,0 +1,85 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LiquidLint
4
+ # Miscellaneus collection of helper functions.
5
+ module Utils
6
+ module_function
7
+
8
+ # Returns whether a glob pattern (or any of a list of patterns) matches the
9
+ # specified file.
10
+ #
11
+ # This is defined here so our file globbing options are consistent
12
+ # everywhere we perform globbing.
13
+ #
14
+ # @param glob [String, Array]
15
+ # @param file [String]
16
+ # @return [Boolean]
17
+ def any_glob_matches?(globs_or_glob, file)
18
+ path = File.expand_path(file)
19
+ Array(globs_or_glob).any? do |glob|
20
+ ::File.fnmatch?(File.expand_path(glob), path,
21
+ ::File::FNM_PATHNAME | # Wildcards don't match path separators
22
+ ::File::FNM_DOTMATCH) # `*` wildcard matches dotfiles
23
+ end
24
+ end
25
+
26
+ # Find all consecutive items satisfying the given block of a minimum size,
27
+ # yielding each group of consecutive items to the provided block.
28
+ #
29
+ # @param items [Array]
30
+ # @param satisfies [Proc] function that takes an item and returns true/false
31
+ # @param min_consecutive [Fixnum] minimum number of consecutive items before
32
+ # yielding the group
33
+ # @yield Passes list of consecutive items all matching the criteria defined
34
+ # by the `satisfies` {Proc} to the provided block
35
+ # @yieldparam group [Array] List of consecutive items
36
+ # @yieldreturn [Boolean] block should return whether item matches criteria
37
+ # for inclusion
38
+ def for_consecutive_items(items, satisfies, min_consecutive = 2)
39
+ current_index = -1
40
+
41
+ while (current_index += 1) < items.count
42
+ next unless satisfies[items[current_index]]
43
+
44
+ count = count_consecutive(items, current_index, &satisfies)
45
+ next unless count >= min_consecutive
46
+
47
+ # Yield the chunk of consecutive items
48
+ yield items[current_index...(current_index + count)]
49
+
50
+ current_index += count # Skip this patch of consecutive items to find more
51
+ end
52
+ end
53
+
54
+ # Count the number of consecutive items satisfying the given {Proc}.
55
+ #
56
+ # @param items [Array]
57
+ # @param offset [Fixnum] index to start searching from
58
+ # @yield [item] Passes item to the provided block.
59
+ # @yieldparam item [Object] Item to evaluate as matching criteria for
60
+ # inclusion
61
+ # @yieldreturn [Boolean] whether to include the item
62
+ # @return [Integer]
63
+ def count_consecutive(items, offset = 0)
64
+ count = 1
65
+ count += 1 while (offset + count < items.count) && yield(items[offset + count])
66
+ count
67
+ end
68
+
69
+ # Calls a block of code with a modified set of environment variables,
70
+ # restoring them once the code has executed.
71
+ #
72
+ # @param env [Hash] environment variables to set
73
+ def with_environment(env)
74
+ old_env = {}
75
+ env.each do |var, value|
76
+ old_env[var] = ENV[var.to_s]
77
+ ENV[var.to_s] = value
78
+ end
79
+
80
+ yield
81
+ ensure
82
+ old_env.each { |var, value| ENV[var.to_s] = value }
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Defines the gem version.
4
+ module LiquidLint
5
+ VERSION = '1.0.0'
6
+ end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Load all liquid-lint modules necessary to parse and lint a file.
4
+ # Ordering here can be important depending on class references in each module.
5
+
6
+ # Need to load liquid before we can reference some classes or define filters
7
+ require 'liquid'
8
+
9
+ require 'liquid_lint/constants'
10
+ require 'liquid_lint/exceptions'
11
+ require 'liquid_lint/configuration'
12
+ require 'liquid_lint/configuration_loader'
13
+ require 'liquid_lint/utils'
14
+ require 'liquid_lint/atom'
15
+ require 'liquid_lint/sexp'
16
+ require 'liquid_lint/file_finder'
17
+ require 'liquid_lint/linter_registry'
18
+ require 'liquid_lint/logger'
19
+ require 'liquid_lint/version'
20
+
21
+ # Load all filters (required by LiquidLint::Engine)
22
+ Dir[File.expand_path('liquid_lint/filters/*.rb', File.dirname(__FILE__))].sort.each do |file|
23
+ require file
24
+ end
25
+
26
+ require 'liquid_lint/engine'
27
+ require 'liquid_lint/document'
28
+ require 'liquid_lint/capture_map'
29
+ require 'liquid_lint/sexp_visitor'
30
+ require 'liquid_lint/lint'
31
+ require 'liquid_lint/ruby_parser'
32
+ require 'liquid_lint/linter'
33
+ require 'liquid_lint/reporter'
34
+ require 'liquid_lint/report'
35
+ require 'liquid_lint/linter_selector'
36
+ require 'liquid_lint/runner'
37
+
38
+ # Load all matchers
39
+ require 'liquid_lint/matcher/base'
40
+ Dir[File.expand_path('liquid_lint/matcher/*.rb', File.dirname(__FILE__))].sort.each do |file|
41
+ require file
42
+ end
43
+
44
+ # Load all linters
45
+ Dir[File.expand_path('liquid_lint/linter/*.rb', File.dirname(__FILE__))].sort.each do |file|
46
+ require file
47
+ end
48
+
49
+ # Load all reporters
50
+ Dir[File.expand_path('liquid_lint/reporter/*.rb', File.dirname(__FILE__))].sort.each do |file|
51
+ require file
52
+ end
metadata ADDED
@@ -0,0 +1,185 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: liquid_lint
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - zeusintuivo
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2023-10-30 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rubocop
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '1.0'
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: '2.0'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: '1.0'
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '2.0'
33
+ - !ruby/object:Gem::Dependency
34
+ name: liquid
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: '3.0'
40
+ - - "<"
41
+ - !ruby/object:Gem::Version
42
+ version: '6.0'
43
+ type: :runtime
44
+ prerelease: false
45
+ version_requirements: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ version: '3.0'
50
+ - - "<"
51
+ - !ruby/object:Gem::Version
52
+ version: '6.0'
53
+ - !ruby/object:Gem::Dependency
54
+ name: pry
55
+ requirement: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - "~>"
58
+ - !ruby/object:Gem::Version
59
+ version: '0.13'
60
+ type: :development
61
+ prerelease: false
62
+ version_requirements: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - "~>"
65
+ - !ruby/object:Gem::Version
66
+ version: '0.13'
67
+ - !ruby/object:Gem::Dependency
68
+ name: rspec
69
+ requirement: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - "~>"
72
+ - !ruby/object:Gem::Version
73
+ version: '3.0'
74
+ type: :development
75
+ prerelease: false
76
+ version_requirements: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - "~>"
79
+ - !ruby/object:Gem::Version
80
+ version: '3.0'
81
+ - !ruby/object:Gem::Dependency
82
+ name: rspec-its
83
+ requirement: !ruby/object:Gem::Requirement
84
+ requirements:
85
+ - - "~>"
86
+ - !ruby/object:Gem::Version
87
+ version: '1.0'
88
+ type: :development
89
+ prerelease: false
90
+ version_requirements: !ruby/object:Gem::Requirement
91
+ requirements:
92
+ - - "~>"
93
+ - !ruby/object:Gem::Version
94
+ version: '1.0'
95
+ description: Configurable tool for writing clean and consistent Liquid templates
96
+ email:
97
+ - zeus@intuivo.com
98
+ executables:
99
+ - liquid-lint
100
+ extensions: []
101
+ extra_rdoc_files: []
102
+ files:
103
+ - LICENSE.md
104
+ - bin/liquid-lint
105
+ - config/default.yml
106
+ - lib/liquid_lint.rb
107
+ - lib/liquid_lint/atom.rb
108
+ - lib/liquid_lint/capture_map.rb
109
+ - lib/liquid_lint/cli.rb
110
+ - lib/liquid_lint/configuration.rb
111
+ - lib/liquid_lint/configuration_loader.rb
112
+ - lib/liquid_lint/constants.rb
113
+ - lib/liquid_lint/document.rb
114
+ - lib/liquid_lint/engine.rb
115
+ - lib/liquid_lint/exceptions.rb
116
+ - lib/liquid_lint/file_finder.rb
117
+ - lib/liquid_lint/filters/attribute_processor.rb
118
+ - lib/liquid_lint/filters/control_processor.rb
119
+ - lib/liquid_lint/filters/inject_line_numbers.rb
120
+ - lib/liquid_lint/filters/sexp_converter.rb
121
+ - lib/liquid_lint/filters/splat_processor.rb
122
+ - lib/liquid_lint/lint.rb
123
+ - lib/liquid_lint/linter.rb
124
+ - lib/liquid_lint/linter/comment_control_statement.rb
125
+ - lib/liquid_lint/linter/consecutive_control_statements.rb
126
+ - lib/liquid_lint/linter/control_statement_spacing.rb
127
+ - lib/liquid_lint/linter/embedded_engines.rb
128
+ - lib/liquid_lint/linter/empty_control_statement.rb
129
+ - lib/liquid_lint/linter/empty_lines.rb
130
+ - lib/liquid_lint/linter/file_length.rb
131
+ - lib/liquid_lint/linter/line_length.rb
132
+ - lib/liquid_lint/linter/redundant_div.rb
133
+ - lib/liquid_lint/linter/rubocop.rb
134
+ - lib/liquid_lint/linter/tab.rb
135
+ - lib/liquid_lint/linter/tag_case.rb
136
+ - lib/liquid_lint/linter/trailing_blank_lines.rb
137
+ - lib/liquid_lint/linter/trailing_whitespace.rb
138
+ - lib/liquid_lint/linter/zwsp.rb
139
+ - lib/liquid_lint/linter_registry.rb
140
+ - lib/liquid_lint/linter_selector.rb
141
+ - lib/liquid_lint/logger.rb
142
+ - lib/liquid_lint/matcher/anything.rb
143
+ - lib/liquid_lint/matcher/base.rb
144
+ - lib/liquid_lint/matcher/capture.rb
145
+ - lib/liquid_lint/matcher/nothing.rb
146
+ - lib/liquid_lint/options.rb
147
+ - lib/liquid_lint/rake_task.rb
148
+ - lib/liquid_lint/report.rb
149
+ - lib/liquid_lint/reporter.rb
150
+ - lib/liquid_lint/reporter/checkstyle_reporter.rb
151
+ - lib/liquid_lint/reporter/default_reporter.rb
152
+ - lib/liquid_lint/reporter/emacs_reporter.rb
153
+ - lib/liquid_lint/reporter/json_reporter.rb
154
+ - lib/liquid_lint/ruby_extract_engine.rb
155
+ - lib/liquid_lint/ruby_extractor.rb
156
+ - lib/liquid_lint/ruby_parser.rb
157
+ - lib/liquid_lint/runner.rb
158
+ - lib/liquid_lint/sexp.rb
159
+ - lib/liquid_lint/sexp_visitor.rb
160
+ - lib/liquid_lint/utils.rb
161
+ - lib/liquid_lint/version.rb
162
+ homepage: https://github.com/zeusintuivo/liquid-lint
163
+ licenses:
164
+ - MIT
165
+ metadata: {}
166
+ post_install_message:
167
+ rdoc_options: []
168
+ require_paths:
169
+ - lib
170
+ required_ruby_version: !ruby/object:Gem::Requirement
171
+ requirements:
172
+ - - ">="
173
+ - !ruby/object:Gem::Version
174
+ version: 2.4.0
175
+ required_rubygems_version: !ruby/object:Gem::Requirement
176
+ requirements:
177
+ - - ">="
178
+ - !ruby/object:Gem::Version
179
+ version: '0'
180
+ requirements: []
181
+ rubygems_version: 3.4.21
182
+ signing_key:
183
+ specification_version: 4
184
+ summary: Liquid template linting tool
185
+ test_files: []