guard-eslint 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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 13b6d5684ff42abb480cfebdefb8b9a2fb3c0ad7734f2f1e953d2e9aa2fd5d8f
4
+ data.tar.gz: a72c609367b38177a97af4e2635083fee57f0cd02f6e865fc95e429f8c0ed80d
5
+ SHA512:
6
+ metadata.gz: 0eba44793949312b50b27c1fb1b4c151d9b5c3e10b0b907e80603741544a0bd56c8ee1091b3ed1ac4e30f64dc933512ec4b485f3d65e760abcf3ec12466d4f26
7
+ data.tar.gz: ec966b2a42890b48a643242223e9bc0aa01f1f61b3f39ed4af579c5858bb1538831b91dc736a3051353111f99bbe0110241ba38c69d9e633872f71371e6acbe8
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.rubocop.yml ADDED
@@ -0,0 +1,27 @@
1
+ require: rubocop-rspec
2
+ AllCops:
3
+ DisplayCopNames: true
4
+ DisplayStyleGuide: true
5
+ Exclude:
6
+ - bin/**/*
7
+ - db/**/*
8
+ - vendor/**/*
9
+ - Guardfile
10
+ Rails:
11
+ Enabled: true
12
+ Metrics/LineLength:
13
+ Max: 100
14
+ Style/Documentation:
15
+ Enabled: false
16
+ Style/NumericLiterals:
17
+ Enabled: false
18
+ Style/ClassAndModuleChildren:
19
+ Enabled: false
20
+ MethodLength:
21
+ Max: 15
22
+ Enabled: false
23
+ Enabled: false
24
+ RegexpLiteral:
25
+ Exclude:
26
+ - '**/*.gemspec'
27
+ - '**/Guardfile'
data/.travis.yml ADDED
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.3.1
4
+ before_install: gem install bundler -v 1.11.2
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in guard-eslint.gemspec
4
+ gemspec
data/README.md ADDED
@@ -0,0 +1,59 @@
1
+ # Guard::Eslint
2
+
3
+ Guard::Eslint allows you to automatically run eslint when you change a Javascript/ES6 file.
4
+ This is best when run after your Javascript tests pass.
5
+
6
+ ## Installation
7
+
8
+ Add this line to your application's Gemfile:
9
+
10
+ ```ruby
11
+ gem 'guard-eslint'
12
+ ```
13
+
14
+ And then execute:
15
+
16
+ $ bundle
17
+
18
+ Or install it yourself as:
19
+
20
+ $ gem install guard-eslint
21
+
22
+ ## Usage
23
+
24
+ Please read [Guard usage doc](https://github.com/guard/guard#readme).
25
+
26
+ ## Guardfile
27
+
28
+ For a typical Rails app with webpack:
29
+
30
+ ``` ruby
31
+ guard :eslint, formatter: 'codeframe' do
32
+ watch(%r{^app/javascript/.+\.(js|es6)$})
33
+ watch(%r{^spec/javascript/.+\.(js|es6)$})
34
+ end
35
+ ```
36
+
37
+ ### List of available options:
38
+
39
+ ``` ruby
40
+ all_on_start: true # Run all specs after changed specs pass.
41
+ keep_failed: false # Keep failed files until they pass (add them to new ones)
42
+ notification: :failed # Display notification when eslint reports an issue.
43
+ # If you want to always notify, set to true.
44
+ cli: nil # Additional command-line options to pass to eslint.
45
+ # Don't use the '-f' or '--format' option here.
46
+ formatter: nil # Formatter to use for output to the console.
47
+ command: 'eslint' # Specify a custom path to the eslint command.
48
+ default_paths: ['**/*.js', '**/*.es6'] # The default paths that will be used for "all_on_start".
49
+ ```
50
+
51
+ ## Contributing
52
+
53
+ Bug reports and pull requests are welcome on GitHub at https://github.com/RobinDaugherty/guard-eslint.
54
+
55
+ * Please create a topic branch for every separate change you make.
56
+ * Make sure your patches are well-tested.
57
+ * Update the README to reflect your changes.
58
+ * Please **do not change** the version number.
59
+ * Open a pull request.
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "guard/eslint"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,35 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'guard/eslint/version'
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = "guard-eslint"
8
+ s.version = Guard::EslintVersion.to_s
9
+ s.authors = %w[tadiou RobinDaugherty]
10
+ s.email = %w[therearedemonsinsideofus@gmail.com robin@robindaugherty.net]
11
+
12
+ s.description = %q{Allows you to add eslint to your Guard toolchain, so that eslint is run.}
13
+ s.summary = %q{Guard to run eslint.}
14
+ s.homepage = "https://github.com/RobinDaugherty/guard-eslint"
15
+ s.license = "MIT"
16
+
17
+ if s.respond_to?(:metadata)
18
+ s.metadata['changelog_uri'] = 'https://github.com/RobinDaugherty/guard-eslint/releases'
19
+ s.metadata['source_code_uri'] = 'https://github.com/RobinDaugherty/guard-eslint'
20
+ s.metadata['bug_tracker_uri'] = 'https://github.com/RobinDaugherty/guard-eslint/issues'
21
+ else
22
+ puts "Your RubyGems does not support metadata. Update if you'd like to make a release."
23
+ end
24
+
25
+ s.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
26
+ s.require_paths = ["lib"]
27
+
28
+ s.required_ruby_version = ">= 2.0.0"
29
+
30
+ s.add_dependency 'guard', "~> 2.1"
31
+ s.add_dependency 'guard-compat', "~> 1.1"
32
+
33
+ s.add_development_dependency "rake", "~> 10.0"
34
+ s.add_development_dependency "rspec", "~> 3.0"
35
+ end
@@ -0,0 +1,135 @@
1
+ require 'guard/compat/plugin'
2
+
3
+ module Guard
4
+ class Eslint < Plugin
5
+ autoload :Runner, 'guard/eslint/runner'
6
+
7
+ # Initializes a Guard plugin.
8
+ # Don't do any work here, especially as Guard plugins get initialized
9
+ # even if they are not in an active group!
10
+ #
11
+ # @param [Hash] options the custom Guard plugin options
12
+ # @option options [Array<Guard::Watcher>] watchers the Guard plugin file watchers
13
+ # @option options [Symbol] group the group this Guard plugin belongs to
14
+ # @option options [Boolean] any_return allow any object to be returned from a watcher
15
+ #
16
+ def initialize(options = {})
17
+ super
18
+
19
+ @options = {
20
+ all_on_start: false,
21
+ keep_failed: false,
22
+ notification: :failed,
23
+ cli: nil,
24
+ formatter: nil,
25
+ command: 'eslint',
26
+ default_paths: ['**/*.js', '**/*.es6'],
27
+ }.merge(options)
28
+
29
+ @failed_paths = []
30
+ end
31
+
32
+ # Called once when Guard starts. Please override initialize method to init stuff.
33
+ #
34
+ # @raise [:task_has_failed] when start has failed
35
+ # @return [Object] the task result
36
+ #
37
+ def start
38
+ Compat::UI.info 'Guard::ESLint is running'
39
+ run_all if options[:all_on_start]
40
+ end
41
+
42
+ # Called when `reload|r|z + enter` is pressed.
43
+ # This method should be mainly used for "reload" (really!) actions like reloading
44
+ # passenger/spork/bundler/...
45
+ #
46
+ # @raise [:task_has_failed] when reload has failed
47
+ # @return [Object] the task result
48
+ #
49
+ def reload
50
+ runner.reload
51
+ end
52
+
53
+ # Called when just `enter` is pressed
54
+ # This method should be principally used for long action like running all specs/tests/...
55
+ #
56
+ # @raise [:task_has_failed] when run_all has failed
57
+ # @return [Object] the task result
58
+ #
59
+ def run_all
60
+ Compat::UI.info 'Inspecting all Javascript files'
61
+ inspect_with_eslint
62
+ end
63
+
64
+ # Called on file(s) additions that the Guard plugin watches.
65
+ #
66
+ # @param [Array<String>] paths the changes files or paths
67
+ # @raise [:task_has_failed] when run_on_additions has failed
68
+ # @return [Object] the task result
69
+ #
70
+ def run_on_additions(paths)
71
+ run_partially(paths)
72
+ end
73
+
74
+ # Called on file(s) modifications that the Guard plugin watches.
75
+ #
76
+ # @param [Array<String>] paths the changes files or paths
77
+ # @raise [:task_has_failed] when run_on_modifications has failed
78
+ # @return [Object] the task result
79
+ #
80
+ def run_on_modifications(paths)
81
+ run_partially(paths)
82
+ end
83
+
84
+ private
85
+
86
+ def inspect_with_eslint(paths = [])
87
+ runner = Runner.new(@options)
88
+ passed = runner.run(paths)
89
+ @failed_paths = runner.failed_paths
90
+ throw :task_has_failed unless passed
91
+ rescue => error
92
+ Compat::UI.error 'The following exception occurred while running guard-eslint: ' \
93
+ "#{error.backtrace.first} #{error.message} (#{error.class.name})"
94
+ end
95
+
96
+ def run_partially(paths)
97
+ paths += @failed_paths if @options[:keep_failed]
98
+ paths = clean_paths(paths)
99
+
100
+ return if paths.empty?
101
+
102
+ displayed_paths = paths.map { |path| smart_path(path) }
103
+ Compat::UI.info "Inspecting JS code style: #{displayed_paths.join(' ')}"
104
+
105
+ inspect_with_eslint(paths)
106
+ end
107
+
108
+ def clean_paths(paths)
109
+ paths = paths.dup
110
+ paths.map! { |path| File.expand_path(path) }
111
+ paths.uniq!
112
+ paths.reject! do |path|
113
+ next true unless File.exist?(path)
114
+ included_in_other_path?(path, paths)
115
+ end
116
+ paths
117
+ end
118
+
119
+ def included_in_other_path?(target_path, other_paths)
120
+ dir_paths = other_paths.select { |path| File.directory?(path) }
121
+ dir_paths.delete(target_path)
122
+ dir_paths.any? do |dir_path|
123
+ target_path.start_with?(dir_path)
124
+ end
125
+ end
126
+
127
+ def smart_path(path)
128
+ if path.start_with?(Dir.pwd)
129
+ Pathname.new(path).relative_path_from(Pathname.getwd).to_s
130
+ else
131
+ path
132
+ end
133
+ end
134
+ end
135
+ end
@@ -0,0 +1,131 @@
1
+ # coding: utf-8
2
+
3
+ require 'json'
4
+
5
+ module Guard
6
+ class Eslint
7
+ # This class runs `eslint` command, retrieves result and notifies.
8
+ # An instance of this class is intended to invoke `eslint` only once in its lifetime.
9
+ class Runner
10
+ def initialize(options)
11
+ @options = options
12
+ end
13
+
14
+ attr_reader :options
15
+
16
+ def run(paths)
17
+ paths = options[:default_paths] unless paths
18
+
19
+ command = command_for_check(paths)
20
+ passed = system(*command)
21
+ case options[:notification]
22
+ when :failed
23
+ notify(passed) unless passed
24
+ when true
25
+ notify(passed)
26
+ end
27
+
28
+ run_for_output(paths)
29
+
30
+ passed
31
+ end
32
+
33
+ ##
34
+ # Once eslint reports a failure, we have to run it again to show the results using the
35
+ # formatter that it uses for output.
36
+ # This because eslint doesn't support multiple formatters during the same run.
37
+ def run_for_output(paths)
38
+ command = [options[:command]]
39
+
40
+ command.concat(args_specified_by_user)
41
+ command.concat(['-f', options[:formatter]]) if options[:formatter]
42
+ command.concat(paths)
43
+ system(*command)
44
+ end
45
+
46
+ def command_for_check(paths)
47
+ command = [options[:command]]
48
+
49
+ command.concat(args_specified_by_user)
50
+ command.concat(['-f', 'json', '-o', json_file_path])
51
+ command.concat(paths)
52
+ end
53
+
54
+ def args_specified_by_user
55
+ @args_specified_by_user ||= begin
56
+ args = options[:cli]
57
+ case args
58
+ when Array then args
59
+ when String then args.shellsplit
60
+ when NilClass then []
61
+ else fail ':cli option must be either an array or string'
62
+ end
63
+ end
64
+ end
65
+
66
+ def json_file_path
67
+ @json_file_path ||= begin
68
+ # Just generate random tempfile path.
69
+ basename = self.class.name.downcase.gsub('::', '_')
70
+ tempfile = Tempfile.new(basename)
71
+ tempfile.close
72
+ tempfile.path
73
+ end
74
+ end
75
+
76
+ def result
77
+ @result ||= begin
78
+ File.open(json_file_path) do |file|
79
+ # Rubinius 2.0.0.rc1 does not support `JSON.load` with 3 args.
80
+ JSON.parse(file.read, symbolize_names: true)
81
+ end
82
+ end
83
+ end
84
+
85
+ def notify(passed)
86
+ image = passed ? :success : :failed
87
+ Notifier.notify(summary_text, title: 'ESLint results', image: image)
88
+ end
89
+
90
+ # rubocop:disable Metric/AbcSize
91
+ def summary_text
92
+ summary = {
93
+ files_inspected: result.count,
94
+ errors: result.map { |x| x[:errorCount] }.reduce(:+),
95
+ warnings: result.map { |x| x[:warningCount] }.reduce(:+)
96
+ }
97
+
98
+ text = pluralize(summary[:files_inspected], 'file')
99
+ text << ' inspected, '
100
+
101
+ errors_count = summary[:errors]
102
+ text << pluralize(errors_count, 'error', no_for_zero: true)
103
+ text << ' detected, '
104
+
105
+ warning_count = summary[:warnings]
106
+ text << pluralize(warning_count, 'warning', no_for_zero: true)
107
+ text << ' detected'
108
+ end
109
+ # rubocop:enable Metric/AbcSize
110
+
111
+ def failed_paths
112
+ result.reject { |f| f[:messages].empty? }.map { |f| f[:filePath] }
113
+ end
114
+
115
+ def pluralize(number, thing, options = {})
116
+ text = ''
117
+
118
+ if number == 0 && options[:no_for_zero]
119
+ text = 'no'
120
+ else
121
+ text << number.to_s
122
+ end
123
+
124
+ text << " #{thing}"
125
+ text << 's' unless number == 1
126
+
127
+ text
128
+ end
129
+ end
130
+ end
131
+ end
@@ -0,0 +1,14 @@
1
+ module Guard
2
+ # A workaround for some superclass BS
3
+ # where Eslint < Guard has to exist?
4
+ module EslintVersion
5
+ # http://semver.org/
6
+ MAJOR = 1
7
+ MINOR = 0
8
+ PATCH = 0
9
+
10
+ def self.to_s
11
+ [MAJOR, MINOR, PATCH].join('.')
12
+ end
13
+ end
14
+ end
metadata ADDED
@@ -0,0 +1,118 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: guard-eslint
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - tadiou
8
+ - RobinDaugherty
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2018-11-16 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: guard
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - "~>"
19
+ - !ruby/object:Gem::Version
20
+ version: '2.1'
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - "~>"
26
+ - !ruby/object:Gem::Version
27
+ version: '2.1'
28
+ - !ruby/object:Gem::Dependency
29
+ name: guard-compat
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - "~>"
33
+ - !ruby/object:Gem::Version
34
+ version: '1.1'
35
+ type: :runtime
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - "~>"
40
+ - !ruby/object:Gem::Version
41
+ version: '1.1'
42
+ - !ruby/object:Gem::Dependency
43
+ name: rake
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - "~>"
47
+ - !ruby/object:Gem::Version
48
+ version: '10.0'
49
+ type: :development
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - "~>"
54
+ - !ruby/object:Gem::Version
55
+ version: '10.0'
56
+ - !ruby/object:Gem::Dependency
57
+ name: rspec
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - "~>"
61
+ - !ruby/object:Gem::Version
62
+ version: '3.0'
63
+ type: :development
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - "~>"
68
+ - !ruby/object:Gem::Version
69
+ version: '3.0'
70
+ description: Allows you to add eslint to your Guard toolchain, so that eslint is run.
71
+ email:
72
+ - therearedemonsinsideofus@gmail.com
73
+ - robin@robindaugherty.net
74
+ executables: []
75
+ extensions: []
76
+ extra_rdoc_files: []
77
+ files:
78
+ - ".gitignore"
79
+ - ".rspec"
80
+ - ".rubocop.yml"
81
+ - ".travis.yml"
82
+ - Gemfile
83
+ - README.md
84
+ - Rakefile
85
+ - bin/console
86
+ - bin/setup
87
+ - guard-eslint.gemspec
88
+ - lib/guard/eslint.rb
89
+ - lib/guard/eslint/runner.rb
90
+ - lib/guard/eslint/version.rb
91
+ homepage: https://github.com/RobinDaugherty/guard-eslint
92
+ licenses:
93
+ - MIT
94
+ metadata:
95
+ changelog_uri: https://github.com/RobinDaugherty/guard-eslint/releases
96
+ source_code_uri: https://github.com/RobinDaugherty/guard-eslint
97
+ bug_tracker_uri: https://github.com/RobinDaugherty/guard-eslint/issues
98
+ post_install_message:
99
+ rdoc_options: []
100
+ require_paths:
101
+ - lib
102
+ required_ruby_version: !ruby/object:Gem::Requirement
103
+ requirements:
104
+ - - ">="
105
+ - !ruby/object:Gem::Version
106
+ version: 2.0.0
107
+ required_rubygems_version: !ruby/object:Gem::Requirement
108
+ requirements:
109
+ - - ">="
110
+ - !ruby/object:Gem::Version
111
+ version: '0'
112
+ requirements: []
113
+ rubyforge_project:
114
+ rubygems_version: 2.7.6
115
+ signing_key:
116
+ specification_version: 4
117
+ summary: Guard to run eslint.
118
+ test_files: []