attractor 1.0.2 → 2.0.1
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/CHANGELOG.md +20 -0
- data/README.md +200 -44
- data/Rakefile +0 -3
- data/app/assets/images/attractor_favicon.png +0 -0
- data/app/assets/javascripts/index.js.erb +4 -5
- data/app/assets/javascripts/index.pack.js +6 -6
- data/app/views/index.html.erb +6 -56
- data/attractor.gemspec +7 -1
- data/bin/test +6 -0
- data/lib/attractor.rb +29 -14
- data/lib/attractor/calculators/base_calculator.rb +5 -2
- data/lib/attractor/cli.rb +46 -28
- data/lib/attractor/detectors/base_detector.rb +7 -0
- data/lib/attractor/duration_parser.rb +27 -0
- data/lib/attractor/gem_names.rb +16 -0
- data/lib/attractor/registry_entry.rb +12 -0
- data/lib/attractor/reporters/base_reporter.rb +2 -0
- data/lib/attractor/reporters/console_reporter.rb +12 -5
- data/lib/attractor/reporters/html_reporter.rb +30 -6
- data/lib/attractor/reporters/sinatra_reporter.rb +3 -0
- data/lib/attractor/suggester.rb +1 -1
- data/lib/attractor/version.rb +1 -1
- metadata +50 -7
- data/.github/workflows/ruby.yml +0 -25
- data/.rspec +0 -3
- data/.travis.yml +0 -10
- data/lib/attractor/calculators/js_calculator.rb +0 -17
- data/lib/attractor/calculators/ruby_calculator.rb +0 -21
data/attractor.gemspec
CHANGED
@@ -28,7 +28,10 @@ Gem::Specification.new do |spec|
|
|
28
28
|
# Specify which files should be added to the gem when it is released.
|
29
29
|
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
30
30
|
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
31
|
-
`git ls-files -z`.split("\x0").reject
|
31
|
+
`git ls-files -z`.split("\x0").reject do |f|
|
32
|
+
f.match(%r{^(src|tmp|test|spec|features|\.github)/}) ||
|
33
|
+
%w[.all-contributorsrc .rspec .rspec_status .travis.yml].include?(f)
|
34
|
+
end
|
32
35
|
end
|
33
36
|
spec.bindir = 'exe'
|
34
37
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
@@ -45,6 +48,8 @@ Gem::Specification.new do |spec|
|
|
45
48
|
spec.add_dependency 'tilt'
|
46
49
|
|
47
50
|
spec.add_development_dependency 'aruba'
|
51
|
+
spec.add_development_dependency 'attractor-javascript'
|
52
|
+
spec.add_development_dependency 'attractor-ruby'
|
48
53
|
spec.add_development_dependency 'autoprefixer-rails'
|
49
54
|
spec.add_development_dependency 'bootstrap', '~> 4.3.1'
|
50
55
|
spec.add_development_dependency 'bundler', '~> 2.0'
|
@@ -55,5 +60,6 @@ Gem::Specification.new do |spec|
|
|
55
60
|
spec.add_development_dependency 'rake', '~> 10.0'
|
56
61
|
spec.add_development_dependency 'rspec', '~> 3.0'
|
57
62
|
spec.add_development_dependency 'sassc'
|
63
|
+
spec.add_development_dependency 'standard'
|
58
64
|
spec.add_development_dependency 'structured_changelog'
|
59
65
|
end
|
data/bin/test
ADDED
data/lib/attractor.rb
CHANGED
@@ -1,29 +1,44 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'attractor/version'
|
4
|
+
require 'attractor/gem_names'
|
5
|
+
require 'attractor/duration_parser'
|
4
6
|
require 'attractor/calculators/base_calculator'
|
5
|
-
require 'attractor/
|
6
|
-
require 'attractor/calculators/js_calculator'
|
7
|
+
require 'attractor/detectors/base_detector'
|
7
8
|
require 'attractor/reporters/base_reporter'
|
8
|
-
require 'attractor/reporters/console_reporter'
|
9
|
-
require 'attractor/reporters/html_reporter'
|
10
|
-
require 'attractor/reporters/sinatra_reporter'
|
11
9
|
require 'attractor/suggester'
|
12
10
|
require 'attractor/watcher'
|
13
11
|
|
12
|
+
Dir[File.join(__dir__, 'attractor', 'reporters', '*.rb')].each do |file|
|
13
|
+
next if file.start_with?('base')
|
14
|
+
|
15
|
+
require file
|
16
|
+
end
|
17
|
+
|
14
18
|
module Attractor
|
15
19
|
class Error < StandardError; end
|
16
20
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
21
|
+
@registry_entries = {}
|
22
|
+
|
23
|
+
def register(registry_entry)
|
24
|
+
@registry_entries[registry_entry.type] = registry_entry
|
25
|
+
end
|
26
|
+
|
27
|
+
def calculators_for_type(type, **options)
|
28
|
+
registry_entry_for_type = @registry_entries[type]
|
29
|
+
|
30
|
+
return { type => registry_entry_for_type.calculator_class.new(**options) } if type
|
31
|
+
|
32
|
+
|
33
|
+
Hash[@registry_entries.map do |type, entry|
|
34
|
+
[type, entry.calculator_class.new(**options)] if entry.detector_class.new.detect
|
35
|
+
end]
|
26
36
|
end
|
27
37
|
|
28
38
|
module_function :calculators_for_type
|
39
|
+
module_function :register
|
40
|
+
end
|
41
|
+
|
42
|
+
Attractor::GemNames.new.to_a.each do |gem_name|
|
43
|
+
require "attractor/#{gem_name}"
|
29
44
|
end
|
@@ -7,10 +7,13 @@ require 'attractor/value'
|
|
7
7
|
module Attractor
|
8
8
|
# calculates churn and complexity
|
9
9
|
class BaseCalculator
|
10
|
-
|
10
|
+
attr_reader :type
|
11
|
+
|
12
|
+
def initialize(file_prefix: '', file_extension: 'rb', minimum_churn_count: 3, start_ago: '5y')
|
11
13
|
@file_prefix = file_prefix
|
12
14
|
@file_extension = file_extension
|
13
15
|
@minimum_churn_count = minimum_churn_count
|
16
|
+
@start_date = Date.today - Attractor::DurationParser.new(start_ago).duration
|
14
17
|
end
|
15
18
|
|
16
19
|
def calculate
|
@@ -18,7 +21,7 @@ module Attractor
|
|
18
21
|
file_extension: @file_extension,
|
19
22
|
file_prefix: @file_prefix,
|
20
23
|
minimum_churn_count: @minimum_churn_count,
|
21
|
-
start_date:
|
24
|
+
start_date: @start_date
|
22
25
|
).report(false)
|
23
26
|
|
24
27
|
churn[:churn][:changes].map do |change|
|
data/lib/attractor/cli.rb
CHANGED
@@ -7,43 +7,56 @@ require 'attractor'
|
|
7
7
|
module Attractor
|
8
8
|
# contains methods implementing the CLI
|
9
9
|
class CLI < Thor
|
10
|
+
shared_options = [[:file_prefix, aliases: :p],
|
11
|
+
[:watch, aliases: :w, type: :boolean],
|
12
|
+
[:minimum_churn, aliases: :c, type: :numeric, default: 3],
|
13
|
+
[:start_ago, aliases: :s, type: :string, default: '5y'],
|
14
|
+
[:type, aliases: :t]]
|
15
|
+
|
16
|
+
advanced_options = [[:format, aliases: :f, default: 'html'],
|
17
|
+
[:no_open_browser, type: :boolean],
|
18
|
+
[:ci, type: :boolean]]
|
19
|
+
|
20
|
+
desc "version", "Prints Attractor's version information"
|
21
|
+
map %w(-v --version) => :version
|
22
|
+
def version
|
23
|
+
puts "Attractor version #{Attractor::VERSION}"
|
24
|
+
rescue RuntimeError => e
|
25
|
+
puts "Runtime error: #{e.message}"
|
26
|
+
end
|
27
|
+
|
10
28
|
desc 'calc', 'Calculates churn and complexity for all ruby files in current directory'
|
11
|
-
|
12
|
-
|
13
|
-
|
29
|
+
shared_options.each do |shared_option|
|
30
|
+
option(*shared_option)
|
31
|
+
end
|
14
32
|
def calc
|
15
33
|
file_prefix = options[:file_prefix]
|
16
|
-
calculators = Attractor.calculators_for_type(options[:type], file_prefix)
|
17
34
|
if options[:watch]
|
18
35
|
puts 'Listening for file changes...'
|
19
|
-
Attractor::ConsoleReporter.new(file_prefix: file_prefix, calculators: calculators).watch
|
36
|
+
Attractor::ConsoleReporter.new(file_prefix: file_prefix, calculators: calculators(options)).watch
|
20
37
|
else
|
21
|
-
Attractor::ConsoleReporter.new(file_prefix: file_prefix, calculators: calculators).report
|
38
|
+
Attractor::ConsoleReporter.new(file_prefix: file_prefix, calculators: calculators(options)).report
|
22
39
|
end
|
23
40
|
rescue RuntimeError => e
|
24
41
|
puts "Runtime error: #{e.message}"
|
25
42
|
end
|
26
43
|
|
27
44
|
desc 'report', 'Generates an HTML report'
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
option :type, aliases: :t
|
32
|
-
option :no_open_browser, type: :boolean
|
33
|
-
option :ci, type: :boolean
|
45
|
+
(shared_options + advanced_options).each do |option|
|
46
|
+
option(*option)
|
47
|
+
end
|
34
48
|
def report
|
35
49
|
file_prefix = options[:file_prefix]
|
36
|
-
|
37
|
-
open_browser = !(options[:no_open_browser] || options[:ci])
|
50
|
+
open_browser = !(options[:no_open_browser] || options[:ci])
|
38
51
|
if options[:watch]
|
39
52
|
puts 'Listening for file changes...'
|
40
|
-
Attractor::HtmlReporter.new(file_prefix: file_prefix, calculators: calculators, open_browser: open_browser).watch
|
53
|
+
Attractor::HtmlReporter.new(file_prefix: file_prefix, calculators: calculators(options), open_browser: open_browser).watch
|
41
54
|
else
|
42
55
|
case options[:format]
|
43
56
|
when 'html'
|
44
|
-
Attractor::HtmlReporter.new(file_prefix: file_prefix, calculators: calculators, open_browser: open_browser).report
|
57
|
+
Attractor::HtmlReporter.new(file_prefix: file_prefix, calculators: calculators(options), open_browser: open_browser).report
|
45
58
|
else
|
46
|
-
Attractor::HtmlReporter.new(file_prefix: file_prefix, calculators: calculators, open_browser: open_browser).report
|
59
|
+
Attractor::HtmlReporter.new(file_prefix: file_prefix, calculators: calculators(options), open_browser: open_browser).report
|
47
60
|
end
|
48
61
|
end
|
49
62
|
rescue RuntimeError => e
|
@@ -51,27 +64,32 @@ module Attractor
|
|
51
64
|
end
|
52
65
|
|
53
66
|
desc 'serve', 'Serves the report on localhost'
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
option :type, aliases: :t
|
58
|
-
option :no_open_browser, type: :boolean
|
59
|
-
option :ci, type: :boolean
|
67
|
+
(shared_options + advanced_options).each do |option|
|
68
|
+
option(*option)
|
69
|
+
end
|
60
70
|
def serve
|
61
71
|
file_prefix = options[:file_prefix]
|
62
|
-
open_browser = !(options[:no_open_browser] || options[:ci])
|
63
|
-
calculators = Attractor.calculators_for_type(options[:type], file_prefix)
|
72
|
+
open_browser = !(options[:no_open_browser] || options[:ci])
|
64
73
|
if options[:watch]
|
65
74
|
puts 'Listening for file changes...'
|
66
|
-
Attractor::SinatraReporter.new(file_prefix: file_prefix, calculators: calculators, open_browser: open_browser).watch
|
75
|
+
Attractor::SinatraReporter.new(file_prefix: file_prefix, calculators: calculators(options), open_browser: open_browser).watch
|
67
76
|
else
|
68
77
|
case options[:format]
|
69
78
|
when 'html'
|
70
|
-
Attractor::SinatraReporter.new(file_prefix: file_prefix, calculators: calculators, open_browser: open_browser).report
|
79
|
+
Attractor::SinatraReporter.new(file_prefix: file_prefix, calculators: calculators(options), open_browser: open_browser).report
|
71
80
|
else
|
72
|
-
Attractor::SinatraReporter.new(file_prefix: file_prefix, calculators: calculators, open_browser: open_browser).report
|
81
|
+
Attractor::SinatraReporter.new(file_prefix: file_prefix, calculators: calculators(options), open_browser: open_browser).report
|
73
82
|
end
|
74
83
|
end
|
75
84
|
end
|
85
|
+
|
86
|
+
private
|
87
|
+
|
88
|
+
def calculators(options)
|
89
|
+
Attractor.calculators_for_type(options[:type],
|
90
|
+
file_prefix: options[:file_prefix],
|
91
|
+
minimum_churn_count: options[:minimum_churn],
|
92
|
+
start_ago: options[:start_ago])
|
93
|
+
end
|
76
94
|
end
|
77
95
|
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Attractor
|
4
|
+
# converts a duration string into an amount of days
|
5
|
+
class DurationParser
|
6
|
+
TOKENS = {
|
7
|
+
'd' => 1,
|
8
|
+
'w' => 7,
|
9
|
+
'm' => 30,
|
10
|
+
'y' => 365
|
11
|
+
}.freeze
|
12
|
+
|
13
|
+
attr_reader :duration
|
14
|
+
|
15
|
+
def initialize(input)
|
16
|
+
@input = input
|
17
|
+
@duration = 0
|
18
|
+
parse
|
19
|
+
end
|
20
|
+
|
21
|
+
def parse
|
22
|
+
@input.scan(/(\d+)(\w)/).each do |amount, measure|
|
23
|
+
@duration += amount.to_i * TOKENS[measure]
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Attractor
|
2
|
+
# from https://github.com/prontolabs/pronto/blob/master/lib/pronto/gem_names.rb
|
3
|
+
class GemNames
|
4
|
+
def to_a
|
5
|
+
gems.map { |gem| gem.name.sub(/^attractor-/, '') }.uniq.sort
|
6
|
+
end
|
7
|
+
|
8
|
+
private
|
9
|
+
|
10
|
+
def gems
|
11
|
+
Gem::Specification.find_all.select do |gem|
|
12
|
+
gem.name =~ /^attractor-/
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module Attractor
|
2
|
+
class RegistryEntry
|
3
|
+
attr_reader :type, :detector_class, :calculator_class
|
4
|
+
|
5
|
+
def initialize(type:, detector_class:, calculator_class:)
|
6
|
+
@type = type
|
7
|
+
@detector_class = detector_class
|
8
|
+
@calculator_class = calculator_class
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
@@ -10,6 +10,7 @@ module Attractor
|
|
10
10
|
class BaseReporter
|
11
11
|
extend Forwardable
|
12
12
|
attr_accessor :values, :file_prefix
|
13
|
+
attr_reader :types
|
13
14
|
def_delegator :@watcher, :watch
|
14
15
|
|
15
16
|
def initialize(file_prefix: '', calculators:, open_browser: true)
|
@@ -33,6 +34,7 @@ module Attractor
|
|
33
34
|
|
34
35
|
def report
|
35
36
|
@suggestions = @suggester.suggest
|
37
|
+
@types = Hash[@calculators.map { |calc| [calc.first, calc.last.type] }]
|
36
38
|
end
|
37
39
|
|
38
40
|
def render
|
@@ -10,12 +10,19 @@ module Attractor
|
|
10
10
|
puts "file_path#{' ' * 53}complexity churn"
|
11
11
|
puts '-' * 80
|
12
12
|
|
13
|
-
|
13
|
+
@calculators.each do |calc|
|
14
|
+
# e.g. ['js', JsCalculator']
|
15
|
+
puts calc.last.type
|
14
16
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
17
|
+
values = calc.last.calculate
|
18
|
+
suggester = Suggester.new(values)
|
19
|
+
|
20
|
+
puts values&.map(&:to_s)
|
21
|
+
puts
|
22
|
+
puts 'Suggestions for refactorings:'
|
23
|
+
suggester.suggest&.each { |sug| puts sug.file_path }
|
24
|
+
puts
|
25
|
+
end
|
19
26
|
end
|
20
27
|
end
|
21
28
|
end
|
@@ -15,23 +15,47 @@ module Attractor
|
|
15
15
|
FileUtils.mkdir_p './attractor_output/javascripts'
|
16
16
|
|
17
17
|
File.open('./attractor_output/images/attractor_logo.svg', 'w') { |file| file.write(logo) }
|
18
|
+
File.open('./attractor_output/images/attractor_favicon.png', 'w') { |file| file.write(favicon) }
|
18
19
|
File.open('./attractor_output/stylesheets/main.css', 'w') { |file| file.write(css) }
|
19
|
-
File.open('./attractor_output/javascripts/index.js', 'w') { |file| file.write(javascript) }
|
20
20
|
File.open('./attractor_output/javascripts/index.pack.js', 'w') { |file| file.write(javascript_pack) }
|
21
21
|
|
22
|
-
|
23
|
-
|
22
|
+
if @calculators.size > 1
|
23
|
+
@calculators.each do |calc|
|
24
|
+
@short_type = calc.first
|
25
|
+
@values = calc.last.calculate
|
26
|
+
suggester = Suggester.new(values)
|
27
|
+
@suggestions = suggester.suggest
|
24
28
|
|
25
|
-
|
26
|
-
|
27
|
-
|
29
|
+
File.open("./attractor_output/javascripts/index.#{@short_type}.js", 'w') { |file| file.write(javascript) }
|
30
|
+
File.open("./attractor_output/index.#{@short_type}.html", 'w') { |file| file.write(render) }
|
31
|
+
puts "Generated HTML report at #{File.expand_path './attractor_output/'}/index.#{@short_type}.html"
|
32
|
+
end
|
33
|
+
|
34
|
+
if @open_browser
|
35
|
+
Launchy.open(File.expand_path("./attractor_output/index.#{@calculators.first.first}.html"))
|
36
|
+
puts "Opening browser window..."
|
37
|
+
end
|
38
|
+
else
|
39
|
+
File.open('./attractor_output/javascripts/index.js', 'w') { |file| file.write(javascript) }
|
40
|
+
File.open('./attractor_output/index.html', 'w') { |file| file.write(render) }
|
41
|
+
puts "Generated HTML report at #{File.expand_path './attractor_output/index.html'}"
|
42
|
+
|
43
|
+
if @open_browser
|
44
|
+
Launchy.open(File.expand_path('./attractor_output/index.html'))
|
45
|
+
puts "Opening browser window..."
|
46
|
+
end
|
28
47
|
end
|
48
|
+
|
29
49
|
end
|
30
50
|
|
31
51
|
def logo
|
32
52
|
File.read(File.expand_path('../../../app/assets/images/attractor_logo.svg', __dir__))
|
33
53
|
end
|
34
54
|
|
55
|
+
def favicon
|
56
|
+
File.read(File.expand_path('../../../app/assets/images/attractor_favicon.png', __dir__))
|
57
|
+
end
|
58
|
+
|
35
59
|
def css
|
36
60
|
File.read(File.expand_path('../../../app/assets/stylesheets/main.css', __dir__))
|
37
61
|
end
|
@@ -17,6 +17,7 @@ module Attractor
|
|
17
17
|
set :show_exceptions, :after_handler
|
18
18
|
|
19
19
|
get '/' do
|
20
|
+
@types = @reporter.types
|
20
21
|
erb File.read(File.expand_path('../../../app/views/index.html.erb', __dir__))
|
21
22
|
end
|
22
23
|
|
@@ -73,6 +74,8 @@ module Attractor
|
|
73
74
|
def values(type: 'rb')
|
74
75
|
@values = @calculators[type].calculate
|
75
76
|
@values
|
77
|
+
rescue NoMethodError => e
|
78
|
+
puts "No calculator for type #{type}"
|
76
79
|
end
|
77
80
|
end
|
78
81
|
end
|
data/lib/attractor/suggester.rb
CHANGED
data/lib/attractor/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: attractor
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Julian Rubisch
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-02-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: churn
|
@@ -150,6 +150,34 @@ dependencies:
|
|
150
150
|
- - ">="
|
151
151
|
- !ruby/object:Gem::Version
|
152
152
|
version: '0'
|
153
|
+
- !ruby/object:Gem::Dependency
|
154
|
+
name: attractor-javascript
|
155
|
+
requirement: !ruby/object:Gem::Requirement
|
156
|
+
requirements:
|
157
|
+
- - ">="
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: '0'
|
160
|
+
type: :development
|
161
|
+
prerelease: false
|
162
|
+
version_requirements: !ruby/object:Gem::Requirement
|
163
|
+
requirements:
|
164
|
+
- - ">="
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: '0'
|
167
|
+
- !ruby/object:Gem::Dependency
|
168
|
+
name: attractor-ruby
|
169
|
+
requirement: !ruby/object:Gem::Requirement
|
170
|
+
requirements:
|
171
|
+
- - ">="
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: '0'
|
174
|
+
type: :development
|
175
|
+
prerelease: false
|
176
|
+
version_requirements: !ruby/object:Gem::Requirement
|
177
|
+
requirements:
|
178
|
+
- - ">="
|
179
|
+
- !ruby/object:Gem::Version
|
180
|
+
version: '0'
|
153
181
|
- !ruby/object:Gem::Dependency
|
154
182
|
name: autoprefixer-rails
|
155
183
|
requirement: !ruby/object:Gem::Requirement
|
@@ -290,6 +318,20 @@ dependencies:
|
|
290
318
|
- - ">="
|
291
319
|
- !ruby/object:Gem::Version
|
292
320
|
version: '0'
|
321
|
+
- !ruby/object:Gem::Dependency
|
322
|
+
name: standard
|
323
|
+
requirement: !ruby/object:Gem::Requirement
|
324
|
+
requirements:
|
325
|
+
- - ">="
|
326
|
+
- !ruby/object:Gem::Version
|
327
|
+
version: '0'
|
328
|
+
type: :development
|
329
|
+
prerelease: false
|
330
|
+
version_requirements: !ruby/object:Gem::Requirement
|
331
|
+
requirements:
|
332
|
+
- - ">="
|
333
|
+
- !ruby/object:Gem::Version
|
334
|
+
version: '0'
|
293
335
|
- !ruby/object:Gem::Dependency
|
294
336
|
name: structured_changelog
|
295
337
|
requirement: !ruby/object:Gem::Requirement
|
@@ -318,17 +360,15 @@ extra_rdoc_files: []
|
|
318
360
|
files:
|
319
361
|
- ".babelrc"
|
320
362
|
- ".eslintrc.json"
|
321
|
-
- ".github/workflows/ruby.yml"
|
322
363
|
- ".gitignore"
|
323
|
-
- ".rspec"
|
324
364
|
- ".rubocop.yml"
|
325
|
-
- ".travis.yml"
|
326
365
|
- CHANGELOG.md
|
327
366
|
- Gemfile
|
328
367
|
- Guardfile
|
329
368
|
- LICENSE
|
330
369
|
- README.md
|
331
370
|
- Rakefile
|
371
|
+
- app/assets/images/attractor_favicon.png
|
332
372
|
- app/assets/images/attractor_logo.png
|
333
373
|
- app/assets/images/attractor_logo.svg
|
334
374
|
- app/assets/images/attractor_logo@2x.png
|
@@ -339,13 +379,16 @@ files:
|
|
339
379
|
- attractor.gemspec
|
340
380
|
- bin/console
|
341
381
|
- bin/setup
|
382
|
+
- bin/test
|
342
383
|
- dist/calculator.bundle.js
|
343
384
|
- exe/attractor
|
344
385
|
- lib/attractor.rb
|
345
386
|
- lib/attractor/calculators/base_calculator.rb
|
346
|
-
- lib/attractor/calculators/js_calculator.rb
|
347
|
-
- lib/attractor/calculators/ruby_calculator.rb
|
348
387
|
- lib/attractor/cli.rb
|
388
|
+
- lib/attractor/detectors/base_detector.rb
|
389
|
+
- lib/attractor/duration_parser.rb
|
390
|
+
- lib/attractor/gem_names.rb
|
391
|
+
- lib/attractor/registry_entry.rb
|
349
392
|
- lib/attractor/reporters/.keep
|
350
393
|
- lib/attractor/reporters/base_reporter.rb
|
351
394
|
- lib/attractor/reporters/console_reporter.rb
|