slimembedcop 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: e085bf2820cb1e136a62f6584721898d1177eb3cebda9e4735cd2f6ea5ab6ea8
4
+ data.tar.gz: e21faefb596375c8a30919fad86d5585037a41e8f9a84cbeca222d382ea0e586
5
+ SHA512:
6
+ metadata.gz: 99f0354e919a707327ead19fa82335631d7b9b44fb938928ee425435c5816999577c79992ed35c08ba7b1accff42f9417ccd75bc5ae1158f8955258aa5a4741d
7
+ data.tar.gz: 2c54f363d17d4a101fbef514505d9315a3eb1c38988506172876c8d820b42df37892ac40143c502009c1534a00da820e9d6fbf305f1261007c8256596f57cf54
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
data/.rubocop.yml ADDED
@@ -0,0 +1,36 @@
1
+ require:
2
+ - rubocop-performance
3
+ - rubocop-rake
4
+ - rubocop-rspec
5
+
6
+ AllCops:
7
+ NewCops: enable
8
+ SuggestExtensions: false
9
+ TargetRubyVersion: 2.7
10
+
11
+ Layout/LineLength:
12
+ Enabled: false
13
+
14
+ Metrics:
15
+ Enabled: false
16
+
17
+ RSpec/AnyInstance:
18
+ Enabled: false
19
+
20
+ RSpec/ExampleLength:
21
+ Enabled: false
22
+
23
+ RSpec/ImplicitSubject:
24
+ Enabled: false
25
+
26
+ RSpec/MultipleExpectations:
27
+ Enabled: false
28
+
29
+ RSpec/NamedSubject:
30
+ Enabled: false
31
+
32
+ Style/Documentation:
33
+ Enabled: false
34
+
35
+ Style/StringLiterals:
36
+ EnforcedStyle: double_quotes
data/CHANGELOG.md ADDED
@@ -0,0 +1,5 @@
1
+ ## Unreleased
2
+
3
+ ## 0.1.0 - 2023-09-07
4
+
5
+ - Initial release
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2023 Yudai Takada
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,7 @@
1
+ # Slimembedcop
2
+
3
+ RuboCop runner for Ruby code embedded in Slim.
4
+
5
+ ## License
6
+
7
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rspec/core/rake_task"
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ task default: %i[spec]
data/exe/slimembedcop ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ $LOAD_PATH.unshift File.expand_path("../lib", __dir__)
5
+ require "slimembedcop"
6
+
7
+ exit Slimembedcop::Cli.run(ARGV)
data/lib/default.yml ADDED
@@ -0,0 +1,8 @@
1
+ Style/FrozenStringLiteralComment:
2
+ Enabled: false
3
+ Layout/TrailingEmptyLines:
4
+ Enabled: false
5
+ Layout/InitialIndentation:
6
+ Enabled: false
7
+ Lint/CircularArgumentReference:
8
+ Enabled: true
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "optparse"
4
+ require "rubocop"
5
+
6
+ module Slimembedcop
7
+ # Command line interface for Slimembedcop.
8
+ class Cli
9
+ class << self
10
+ DEFAULT_CONFIG_PATH = File.expand_path("../default.yml", __dir__)
11
+ DEFAULT_PATH_PATTERNS = %w[**/*.slim].freeze
12
+
13
+ def run(argv)
14
+ options = parse_options!(argv)
15
+ formatter = ::RuboCop::Formatter::ProgressFormatter.new($stdout, color: options[:color])
16
+ config = ConfigGenerator.run(DEFAULT_CONFIG_PATH, options[:forced_config_path])
17
+ paths = PathFinder.run(DEFAULT_PATH_PATTERNS, config.for_all_cops["Exclude"], argv)
18
+ offenses = Runner.run(paths, formatter, config, options[:autocorrect])
19
+ exit(offenses.empty? ? 0 : 1)
20
+ end
21
+
22
+ private
23
+
24
+ def parse_options!(argv)
25
+ options = {}
26
+ parser = ::OptionParser.new
27
+ parser.banner = "Usage: slimembedcop [options] [file1, file2, ...]"
28
+ parser.version = VERSION
29
+ parser.on("-a", "--autocorrect", "Autocorrect offenses.") do
30
+ p "autocorrect"
31
+ options[:autocorrect] = true
32
+ end
33
+ parser.on("-c", "--config=", "Specify configuration file. (default: #{DEFAULT_CONFIG_PATH} or .rubocop.yml)") do |file_path|
34
+ options[:forced_config_path] = file_path
35
+ end
36
+ parser.on("--[no-]color", "Force color output on or off.") do |value|
37
+ options[:color] = value
38
+ end
39
+ parser.parse!(argv)
40
+ options
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rubocop"
4
+
5
+ module Slimembedcop
6
+ # Generates a configuration for RuboCop.
7
+ class ConfigGenerator
8
+ class << self
9
+ def run(default_config_path, forced_config_path)
10
+ @default_config_path = default_config_path
11
+ @forced_config_path = forced_config_path
12
+ ::RuboCop::ConfigLoader.merge_with_default(merged_config, loaded_path)
13
+ end
14
+
15
+ private
16
+
17
+ def loaded_path
18
+ @forced_config_path || implicit_config_path || @default_config_path
19
+ end
20
+
21
+ def merged_config
22
+ ::RuboCop::Config.create(merged_config_hash, loaded_path)
23
+ end
24
+
25
+ def merged_config_hash
26
+ result = default_config
27
+ result = ::RuboCop::ConfigLoader.merge(result, user_config) if user_config
28
+ result
29
+ end
30
+
31
+ def user_config
32
+ if instance_variable_defined?(:@user_config)
33
+ @user_config
34
+ else
35
+ @user_config =
36
+ if @forced_config_path
37
+ ::RuboCop::ConfigLoader.load_file(@forced_config_path)
38
+ elsif (path = implicit_config_path)
39
+ ::RuboCop::ConfigLoader.load_file(path)
40
+ end
41
+ end
42
+ end
43
+
44
+ def default_config
45
+ ::RuboCop::ConfigLoader.load_file(@default_config_path)
46
+ end
47
+
48
+ def implicit_config_path
49
+ if instance_variable_defined?(:@implicit_config_path)
50
+ @implicit_config_path
51
+ else
52
+ @implicit_config_path = %w[.slimembedcop.yml .rubocop.yml].find do |path|
53
+ ::File.exist?(path)
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "slimi"
4
+
5
+ module Slimembedcop
6
+ # Extract Ruby codes from Slim embedded code.
7
+ class Extractor
8
+ class << self
9
+ def run(path, source)
10
+ @path = path
11
+ @source = source
12
+
13
+ ranges.map do |(begin_, end_)|
14
+ { code: source[begin_...end_], offset: begin_ }
15
+ end
16
+ end
17
+
18
+ private
19
+
20
+ def ranges
21
+ result = []
22
+ index = 0
23
+ begin_pos = 0
24
+ leading_spaces = 0
25
+ inside_ruby = false
26
+ @source.each_line do |line|
27
+ if block_start?(line)
28
+ leading_spaces = line.match(/^\s*/)[0].length
29
+ inside_ruby = true
30
+ begin_pos = index += line.length
31
+ next
32
+ end
33
+
34
+ if inside_ruby && block_end?(line, leading_spaces)
35
+ result << [begin_pos, index - 1]
36
+ inside_ruby = false
37
+ end
38
+
39
+ index += line.length
40
+ end
41
+
42
+ result << [begin_pos, index - 1] if inside_ruby
43
+
44
+ result
45
+ end
46
+
47
+ def block_start?(line)
48
+ line.strip.start_with?("ruby:")
49
+ end
50
+
51
+ def block_end?(line, leading_spaces)
52
+ line.match(/^\s{#{leading_spaces}}\S/) ||
53
+ (leading_spaces.zero? && line.match(/^\S/))
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,87 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "forwardable"
4
+
5
+ require "parser"
6
+ require "rubocop"
7
+
8
+ module Slimembedcop
9
+ # Wraps a RuboCop offense.
10
+ class Offense
11
+ extend ::Forwardable
12
+
13
+ attr_reader :path, :offset
14
+
15
+ delegate(
16
+ %i[column column_length cop_name correctable? corrected_with_todo?
17
+ corrected? corrector eql? hash highlighted_area line
18
+ message real_column severity] => :offense_with_real_location
19
+ )
20
+
21
+ def initialize(path, offset, offense, source)
22
+ @path = path
23
+ @offset = offset
24
+ @offense = offense
25
+ @source = source
26
+ end
27
+
28
+ def location
29
+ @location ||= ::Parser::Source::Range.new(
30
+ buffer,
31
+ @offense.location.begin_pos + @offset,
32
+ @offense.location.end_pos + @offset
33
+ )
34
+ end
35
+
36
+ def marshal_dump
37
+ {
38
+ begin_pos: @offense.location.begin_pos,
39
+ cop_name: @offense.cop_name,
40
+ end_pos: @offense.location.end_pos,
41
+ path: @path,
42
+ message: @offense.message.dup.force_encoding(::Encoding::UTF_8).scrub,
43
+ offset: @offset,
44
+ severity: @offense.severity.to_s,
45
+ source: @source,
46
+ status: @offense.status
47
+ }
48
+ end
49
+
50
+ def marshal_load(hash)
51
+ @path = hash[:path]
52
+ @offset = hash[:offset]
53
+ @offense = ::RuboCop::Cop::Offense.new(
54
+ hash[:severity],
55
+ ::Parser::Source::Range.new(
56
+ ::Parser::Source::Buffer.new(
57
+ @path,
58
+ source: @source
59
+ ),
60
+ hash[:begin_pos],
61
+ hash[:end_pos]
62
+ ),
63
+ hash[:message],
64
+ hash[:cop_name],
65
+ hash[:status].to_sym
66
+ )
67
+ @source = hash[:source]
68
+ end
69
+
70
+ private
71
+
72
+ def buffer
73
+ ::Parser::Source::Buffer.new(path, source: @source)
74
+ end
75
+
76
+ def offense_with_real_location
77
+ ::RuboCop::Cop::Offense.new(
78
+ @offense.severity.name,
79
+ location,
80
+ @offense.message,
81
+ @offense.cop_name,
82
+ @offense.status,
83
+ @offense.corrector
84
+ )
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Slimembedcop
4
+ # Collect RuboCop offenses from Template code.
5
+ class OffenseCollector
6
+ class << self
7
+ def run(path, config, source, autocorrect)
8
+ snippets(path, source).flat_map do |snippet|
9
+ RubyOffenseCollector.run(path, config, snippet[:code], autocorrect).map do |offense|
10
+ Offense.new(path, snippet[:offset], offense, source)
11
+ end
12
+ end
13
+ end
14
+
15
+ private
16
+
17
+ def snippets(path, source)
18
+ Extractor.run(path, source)
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "pathname"
4
+ require "set"
5
+
6
+ module Slimembedcop
7
+ # Collect file paths from given path patterns.
8
+ class PathFinder
9
+ class << self
10
+ def run(default_patterns, exclude_patterns, path_patterns)
11
+ @default_patterns = default_patterns
12
+ @exclude_patterns = exclude_patterns || []
13
+ @path_patterns = path_patterns
14
+ matching_paths(patterns) do |path|
15
+ !excluded?(path)
16
+ end.sort
17
+ end
18
+
19
+ private
20
+
21
+ def matching_paths(patterns, &block)
22
+ patterns.each_with_object(Set.new) do |pattern, set|
23
+ ::Pathname.glob(pattern) do |pathname|
24
+ next unless pathname.file?
25
+
26
+ path = pathname.expand_path.to_s
27
+ set.add(path) if block.nil? || yield(path)
28
+ end
29
+ end
30
+ end
31
+
32
+ def excluded?(path)
33
+ excluded.include?(path)
34
+ end
35
+
36
+ def excluded
37
+ @excluded ||= matching_paths(@exclude_patterns)
38
+ end
39
+
40
+ def patterns
41
+ return @default_patterns if @path_patterns.empty?
42
+
43
+ @path_patterns.map do |pattern|
44
+ next pattern unless File.directory?(pattern)
45
+
46
+ @default_patterns.map do |default|
47
+ File.join(pattern, default)
48
+ end.flatten
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rubocop"
4
+
5
+ module Slimembedcop
6
+ # Collect RuboCop offenses from Ruby code.
7
+ class RubyOffenseCollector
8
+ class << self
9
+ def run(path, config, source, autocorrect)
10
+ return [] unless rubocop_processed_source(path, config, source).valid_syntax?
11
+
12
+ rubocop_team(config, autocorrect).investigate(rubocop_processed_source(path, config, source)).offenses.reject(&:disabled?)
13
+ end
14
+
15
+ private
16
+
17
+ def registry
18
+ @registry ||= begin
19
+ all_cops = if ::RuboCop::Cop::Registry.respond_to?(:all)
20
+ ::RuboCop::Cop::Registry.all
21
+ else
22
+ ::RuboCop::Cop::Cop.all
23
+ end
24
+
25
+ ::RuboCop::Cop::Registry.new(all_cops)
26
+ end
27
+ end
28
+
29
+ def rubocop_processed_source(path, config, source)
30
+ ::RuboCop::ProcessedSource.new(source, config.target_ruby_version, path).tap do |processed_source|
31
+ processed_source.config = config if processed_source.respond_to?(:config)
32
+ processed_source.registry = registry if processed_source.respond_to?(:registry)
33
+ end
34
+ end
35
+
36
+ def rubocop_team(config, autocorrect)
37
+ ::RuboCop::Cop::Team.new(
38
+ registry,
39
+ config,
40
+ autocorrect: autocorrect,
41
+ display_cop_names: true,
42
+ extra_details: true,
43
+ stdin: ""
44
+ )
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,83 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "parallel"
4
+ require "stringio"
5
+
6
+ module Slimembedcop
7
+ # Run investigation and auto-correction.
8
+ class Runner
9
+ class << self
10
+ def run(paths, formatter, config, autocorrect)
11
+ @autocorrect = autocorrect
12
+
13
+ on_started(formatter, paths)
14
+ result = run_in_parallel(paths, formatter, config)
15
+ on_finished(paths, formatter, result)
16
+ result.flat_map { |(_, offenses)| offenses }
17
+ end
18
+
19
+ private
20
+
21
+ def on_started(formatter, paths)
22
+ formatter.started(paths)
23
+ end
24
+
25
+ def run_in_parallel(paths, formatter, config)
26
+ ::Parallel.map(paths) do |path|
27
+ offenses_per_file = []
28
+ max_trials_count.times do
29
+ on_file_started(formatter, path)
30
+ source = ::File.read(path)
31
+ offenses = investigate(path, config, source)
32
+ offenses_per_file |= offenses
33
+ break if offenses.none?(&:correctable?)
34
+
35
+ next unless @autocorrect
36
+
37
+ correct(path, offenses, source)
38
+ end
39
+
40
+ on_file_finished(path, formatter, offenses_per_file)
41
+ [path, offenses_per_file]
42
+ end
43
+ end
44
+
45
+ def max_trials_count
46
+ if @autocorrect
47
+ 7
48
+ else
49
+ 1
50
+ end
51
+ end
52
+
53
+ def investigate(path, config, source)
54
+ OffenseCollector.run(path, config, source, @autocorrect)
55
+ end
56
+
57
+ def correct(path, offenses, source)
58
+ rewritten_source = TemplateCorrector.new(path, offenses, source).run
59
+ ::File.write(path, rewritten_source)
60
+ end
61
+
62
+ def on_file_started(formatter, path)
63
+ formatter.file_started(path, {})
64
+ end
65
+
66
+ def on_file_finished(path, formatter, offenses)
67
+ formatter.file_finished(path, offenses)
68
+ end
69
+
70
+ def on_finished(paths, formatter, result)
71
+ original = formatter.output
72
+ formatter.instance_variable_set(:@output, ::StringIO.new)
73
+ result.each do |(path, offenses)|
74
+ on_file_started(formatter, path)
75
+ on_file_finished(path, formatter, offenses)
76
+ end
77
+ formatter.instance_variable_set(:@output, original)
78
+
79
+ formatter.finished(paths)
80
+ end
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "parser"
4
+ require "rubocop/cop/legacy/corrector"
5
+
6
+ module Slimembedcop
7
+ # Apply auto-corrections to Template file.
8
+ class TemplateCorrector
9
+ def initialize(path, offenses, source)
10
+ @path = path
11
+ @offenses = offenses
12
+ @source = source
13
+ end
14
+
15
+ def run
16
+ ::RuboCop::Cop::Legacy::Corrector.new(source_buffer, corrections).rewrite
17
+ end
18
+
19
+ private
20
+
21
+ def corrections
22
+ @offenses.select(&:corrector).map do |offense|
23
+ lambda do |corrector|
24
+ corrector.import!(offense.corrector, offset: offense.offset)
25
+ end
26
+ end
27
+ end
28
+
29
+ def source_buffer
30
+ ::Parser::Source::Buffer.new(@path, source: @source)
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Slimembedcop
4
+ VERSION = "0.1.0"
5
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "slimembedcop/version"
4
+
5
+ module Slimembedcop
6
+ autoload :Cli, "slimembedcop/cli"
7
+ autoload :ConfigGenerator, "slimembedcop/config_generator"
8
+ autoload :Extractor, "slimembedcop/extractor"
9
+ autoload :Offense, "slimembedcop/offense"
10
+ autoload :OffenseCollector, "slimembedcop/offense_collector"
11
+ autoload :PathFinder, "slimembedcop/path_finder"
12
+ autoload :RubyOffenseCollector, "slimembedcop/ruby_offense_collector"
13
+ autoload :Runner, "slimembedcop/runner"
14
+ autoload :TemplateCorrector, "slimembedcop/template_corrector"
15
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "lib/slimembedcop/version"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "slimembedcop"
7
+ spec.version = Slimembedcop::VERSION
8
+ spec.authors = ["Yudai Takada"]
9
+ spec.email = ["t.yudai92@gmail.com"]
10
+
11
+ spec.summary = "RuboCop runner for Ruby code embedded in Slim."
12
+ spec.homepage = "https://github.com/ydah/slimembedcop"
13
+ spec.license = "MIT"
14
+ spec.required_ruby_version = ">= 2.7.0"
15
+
16
+ spec.metadata["homepage_uri"] = spec.homepage
17
+ spec.metadata["source_code_uri"] = spec.homepage
18
+ spec.metadata["changelog_uri"] = "#{spec.homepage}/releases"
19
+ spec.metadata["rubygems_mfa_required"] = "true"
20
+
21
+ spec.files = Dir.chdir(__dir__) do
22
+ `git ls-files -z`.split("\x0").reject do |f|
23
+ (File.expand_path(f) == __FILE__) ||
24
+ f.start_with?(*%w[bin/ test/ spec/ features/ .git .circleci appveyor Gemfile])
25
+ end
26
+ end
27
+ spec.bindir = "exe"
28
+ spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
29
+ spec.require_paths = ["lib"]
30
+
31
+ spec.add_dependency "rubocop", "~> 1.0"
32
+ end
metadata ADDED
@@ -0,0 +1,82 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: slimembedcop
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Yudai Takada
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2023-09-06 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
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.0'
27
+ description:
28
+ email:
29
+ - t.yudai92@gmail.com
30
+ executables:
31
+ - slimembedcop
32
+ extensions: []
33
+ extra_rdoc_files: []
34
+ files:
35
+ - ".rspec"
36
+ - ".rubocop.yml"
37
+ - CHANGELOG.md
38
+ - LICENSE.txt
39
+ - README.md
40
+ - Rakefile
41
+ - exe/slimembedcop
42
+ - lib/default.yml
43
+ - lib/slimembedcop.rb
44
+ - lib/slimembedcop/cli.rb
45
+ - lib/slimembedcop/config_generator.rb
46
+ - lib/slimembedcop/extractor.rb
47
+ - lib/slimembedcop/offense.rb
48
+ - lib/slimembedcop/offense_collector.rb
49
+ - lib/slimembedcop/path_finder.rb
50
+ - lib/slimembedcop/ruby_offense_collector.rb
51
+ - lib/slimembedcop/runner.rb
52
+ - lib/slimembedcop/template_corrector.rb
53
+ - lib/slimembedcop/version.rb
54
+ - slimembedcop.gemspec
55
+ homepage: https://github.com/ydah/slimembedcop
56
+ licenses:
57
+ - MIT
58
+ metadata:
59
+ homepage_uri: https://github.com/ydah/slimembedcop
60
+ source_code_uri: https://github.com/ydah/slimembedcop
61
+ changelog_uri: https://github.com/ydah/slimembedcop/releases
62
+ rubygems_mfa_required: 'true'
63
+ post_install_message:
64
+ rdoc_options: []
65
+ require_paths:
66
+ - lib
67
+ required_ruby_version: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ version: 2.7.0
72
+ required_rubygems_version: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ requirements: []
78
+ rubygems_version: 3.3.7
79
+ signing_key:
80
+ specification_version: 4
81
+ summary: RuboCop runner for Ruby code embedded in Slim.
82
+ test_files: []