eslint-rails-ee 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/.gitignore +15 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +216 -0
- data/Rakefile +1 -0
- data/app/controllers/eslint_controller.rb +23 -0
- data/app/views/eslint/show.html.erb +55 -0
- data/app/views/eslint/source.html.erb +80 -0
- data/build-plugins.sh +21 -0
- data/config/eslint.json +160 -0
- data/config/routes.rb +7 -0
- data/eslint-rails-ee.gemspec +30 -0
- data/lib/eslint-rails-ee.rb +8 -0
- data/lib/eslint-rails-ee/config.rb +29 -0
- data/lib/eslint-rails-ee/engine.rb +4 -0
- data/lib/eslint-rails-ee/runner.rb +113 -0
- data/lib/eslint-rails-ee/text_formatter.rb +43 -0
- data/lib/eslint-rails-ee/version.rb +3 -0
- data/lib/eslint-rails-ee/warning.rb +34 -0
- data/lib/tasks/eslint.rake +50 -0
- data/vendor/assets/javascripts/eslint.js +107296 -0
- data/vendor/assets/javascripts/plugins/eslint-plugin-react.js +12862 -0
- metadata +154 -0
data/config/eslint.json
ADDED
@@ -0,0 +1,160 @@
|
|
1
|
+
{
|
2
|
+
"ecmaFeatures": {},
|
3
|
+
"parser": "espree",
|
4
|
+
"env": {
|
5
|
+
"browser": false,
|
6
|
+
"node": false,
|
7
|
+
"amd": false,
|
8
|
+
"mocha": false,
|
9
|
+
"jasmine": false
|
10
|
+
},
|
11
|
+
|
12
|
+
"rules": {
|
13
|
+
"no-alert": 2,
|
14
|
+
"no-array-constructor": 2,
|
15
|
+
"no-bitwise": 0,
|
16
|
+
"no-caller": 2,
|
17
|
+
"no-catch-shadow": 2,
|
18
|
+
"no-comma-dangle": 0,
|
19
|
+
"no-cond-assign": 2,
|
20
|
+
"no-console": 2,
|
21
|
+
"no-constant-condition": 2,
|
22
|
+
"no-control-regex": 2,
|
23
|
+
"no-debugger": 2,
|
24
|
+
"no-delete-var": 2,
|
25
|
+
"no-div-regex": 0,
|
26
|
+
"no-dupe-keys": 2,
|
27
|
+
"no-dupe-args": 2,
|
28
|
+
"no-else-return": 0,
|
29
|
+
"no-empty": 2,
|
30
|
+
"no-empty-character-class": 2,
|
31
|
+
"no-eq-null": 0,
|
32
|
+
"no-eval": 2,
|
33
|
+
"no-ex-assign": 2,
|
34
|
+
"no-extend-native": 2,
|
35
|
+
"no-extra-bind": 2,
|
36
|
+
"no-extra-boolean-cast": 2,
|
37
|
+
"no-extra-parens": 0,
|
38
|
+
"no-extra-semi": 2,
|
39
|
+
"no-fallthrough": 2,
|
40
|
+
"no-floating-decimal": 0,
|
41
|
+
"no-func-assign": 2,
|
42
|
+
"no-implied-eval": 2,
|
43
|
+
"no-inline-comments": 0,
|
44
|
+
"no-inner-declarations": [2, "functions"],
|
45
|
+
"no-invalid-regexp": 2,
|
46
|
+
"no-irregular-whitespace": 2,
|
47
|
+
"no-iterator": 2,
|
48
|
+
"no-label-var": 2,
|
49
|
+
"no-labels": 2,
|
50
|
+
"no-lone-blocks": 2,
|
51
|
+
"no-lonely-if": 0,
|
52
|
+
"no-loop-func": 2,
|
53
|
+
"no-mixed-requires": [0, false],
|
54
|
+
"no-mixed-spaces-and-tabs": [2, false],
|
55
|
+
"no-multi-spaces": 2,
|
56
|
+
"no-multi-str": 2,
|
57
|
+
"no-multiple-empty-lines": [0, { "max": 2 }],
|
58
|
+
"no-native-reassign": 2,
|
59
|
+
"no-negated-in-lhs": 2,
|
60
|
+
"no-nested-ternary": 0,
|
61
|
+
"no-new": 2,
|
62
|
+
"no-new-func": 2,
|
63
|
+
"no-new-object": 2,
|
64
|
+
"no-new-require": 0,
|
65
|
+
"no-new-wrappers": 2,
|
66
|
+
"no-obj-calls": 2,
|
67
|
+
"no-octal": 2,
|
68
|
+
"no-octal-escape": 2,
|
69
|
+
"no-path-concat": 0,
|
70
|
+
"no-plusplus": 0,
|
71
|
+
"no-process-env": 0,
|
72
|
+
"no-process-exit": 2,
|
73
|
+
"no-proto": 2,
|
74
|
+
"no-redeclare": 2,
|
75
|
+
"no-regex-spaces": 2,
|
76
|
+
"no-reserved-keys": 0,
|
77
|
+
"no-restricted-modules": 0,
|
78
|
+
"no-return-assign": 2,
|
79
|
+
"no-script-url": 2,
|
80
|
+
"no-self-compare": 0,
|
81
|
+
"no-sequences": 2,
|
82
|
+
"no-shadow": 2,
|
83
|
+
"no-shadow-restricted-names": 2,
|
84
|
+
"no-space-before-semi": 0,
|
85
|
+
"no-spaced-func": 2,
|
86
|
+
"no-sparse-arrays": 2,
|
87
|
+
"no-sync": 0,
|
88
|
+
"no-ternary": 0,
|
89
|
+
"no-trailing-spaces": 2,
|
90
|
+
"no-throw-literal": 0,
|
91
|
+
"no-undef": 1,
|
92
|
+
"no-undef-init": 2,
|
93
|
+
"no-undefined": 0,
|
94
|
+
"no-underscore-dangle": 2,
|
95
|
+
"no-unreachable": 2,
|
96
|
+
"no-unused-expressions": 2,
|
97
|
+
"no-unused-vars": [2, { "vars": "all", "args": "after-used" }],
|
98
|
+
"no-use-before-define": 2,
|
99
|
+
"no-void": 0,
|
100
|
+
"no-var": 0,
|
101
|
+
"no-warning-comments": [0, { "terms": ["todo", "fixme", "xxx"], "location": "start" }],
|
102
|
+
"no-with": 2,
|
103
|
+
|
104
|
+
"block-scoped-var": 0,
|
105
|
+
"brace-style": [0, "1tbs"],
|
106
|
+
"camelcase": 2,
|
107
|
+
"comma-dangle": [2, "never"],
|
108
|
+
"comma-spacing": 2,
|
109
|
+
"comma-style": 0,
|
110
|
+
"complexity": [0, 11],
|
111
|
+
"consistent-return": 2,
|
112
|
+
"consistent-this": [0, "that"],
|
113
|
+
"curly": [2, "all"],
|
114
|
+
"default-case": 0,
|
115
|
+
"dot-notation": [2, { "allowKeywords": true }],
|
116
|
+
"eol-last": 2,
|
117
|
+
"eqeqeq": 2,
|
118
|
+
"func-names": 0,
|
119
|
+
"func-style": [0, "declaration"],
|
120
|
+
"generator-star": 0,
|
121
|
+
"guard-for-in": 0,
|
122
|
+
"handle-callback-err": 0,
|
123
|
+
"indent": 0,
|
124
|
+
"key-spacing": [2, { "beforeColon": false, "afterColon": true }],
|
125
|
+
"keyword-spacing": 2,
|
126
|
+
"max-depth": [0, 4],
|
127
|
+
"max-len": [0, 80, 4],
|
128
|
+
"max-nested-callbacks": [0, 2],
|
129
|
+
"max-params": [0, 3],
|
130
|
+
"max-statements": [0, 10],
|
131
|
+
"new-cap": 2,
|
132
|
+
"new-parens": 2,
|
133
|
+
"one-var": 0,
|
134
|
+
"operator-assignment": [0, "always"],
|
135
|
+
"padded-blocks": 0,
|
136
|
+
"quote-props": 0,
|
137
|
+
"quotes": [1, "double"],
|
138
|
+
"radix": 0,
|
139
|
+
"semi": 2,
|
140
|
+
"semi-spacing": [2, { "before": false, "after": true }],
|
141
|
+
"sort-vars": 0,
|
142
|
+
"space-after-function-name": [0, "never"],
|
143
|
+
"space-after-keywords": [0, "always"],
|
144
|
+
"space-before-blocks": [0, "always"],
|
145
|
+
"space-before-function-parentheses": [0, "always"],
|
146
|
+
"space-in-brackets": [0, "never"],
|
147
|
+
"space-in-parens": [0, "never"],
|
148
|
+
"space-infix-ops": 2,
|
149
|
+
"space-unary-ops": [2, { "words": true, "nonwords": false }],
|
150
|
+
"spaced-line-comment": [0, "always"],
|
151
|
+
"strict": 2,
|
152
|
+
"use-isnan": 2,
|
153
|
+
"valid-jsdoc": 0,
|
154
|
+
"valid-typeof": 2,
|
155
|
+
"vars-on-top": 0,
|
156
|
+
"wrap-iife": 0,
|
157
|
+
"wrap-regex": 0,
|
158
|
+
"yoda": [2, "never"]
|
159
|
+
}
|
160
|
+
}
|
data/config/routes.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'eslint-rails-ee/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'eslint-rails-ee'
|
8
|
+
spec.version = ESLintRails::VERSION
|
9
|
+
spec.authors = ['Justin Force', 'Jon Kessler', 'David Valentine']
|
10
|
+
spec.email = ['justin.force@appfolio.com', 'jon.kessler@appfolio.com', 'davidlewisrogers3@gmail.com']
|
11
|
+
spec.summary = %q{A Rails wrapper for ESLint, but ENHANCED!}
|
12
|
+
spec.description = spec.summary
|
13
|
+
spec.homepage = 'https://github.com/dlvalentine/eslint-rails-ee'
|
14
|
+
spec.license = 'MIT'
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ['lib']
|
20
|
+
|
21
|
+
spec.required_ruby_version = '>= 2.0.0'
|
22
|
+
|
23
|
+
spec.add_dependency 'railties', '>= 3.2'
|
24
|
+
spec.add_dependency 'execjs'
|
25
|
+
spec.add_dependency 'colorize'
|
26
|
+
|
27
|
+
spec.add_development_dependency 'bundler', '~> 1.7'
|
28
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
29
|
+
spec.add_development_dependency 'therubyracer'
|
30
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module ESLintRails
|
2
|
+
class Config
|
3
|
+
|
4
|
+
def self.read(force_default: false)
|
5
|
+
self.new(force_default: force_default).send(:read)
|
6
|
+
end
|
7
|
+
|
8
|
+
private
|
9
|
+
|
10
|
+
CONFIG_PATH = 'config/eslint.json'
|
11
|
+
private_constant :CONFIG_PATH
|
12
|
+
|
13
|
+
def initialize(force_default: nil)
|
14
|
+
raise(ArgumentError, 'force_default is required') if force_default.nil?
|
15
|
+
|
16
|
+
@force_default = force_default
|
17
|
+
@custom_file = Rails.root.join(CONFIG_PATH)
|
18
|
+
@default_file = ESLintRails::Engine.root.join(CONFIG_PATH)
|
19
|
+
end
|
20
|
+
|
21
|
+
def read
|
22
|
+
config_file.read
|
23
|
+
end
|
24
|
+
|
25
|
+
def config_file
|
26
|
+
(@custom_file.exist? && !@force_default) ? @custom_file : @default_file
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
require 'colorize'
|
2
|
+
|
3
|
+
module ESLintRails
|
4
|
+
class Runner
|
5
|
+
include ActionView::Helpers::JavaScriptHelper
|
6
|
+
|
7
|
+
JAVASCRIPT_EXTENSIONS = %w(.js .jsx .es6)
|
8
|
+
|
9
|
+
def initialize(file)
|
10
|
+
@file = normalize_infile(file)
|
11
|
+
end
|
12
|
+
|
13
|
+
def run(should_autocorrect=false)
|
14
|
+
warnings = assets.map do |asset|
|
15
|
+
generate_warnings(asset, should_autocorrect).tap { |warnings| output_progress(warnings) }
|
16
|
+
end
|
17
|
+
|
18
|
+
puts
|
19
|
+
|
20
|
+
warnings.flatten
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def normalize_infile(file)
|
26
|
+
file = file.to_s.gsub(/^app\/assets\/javascripts\//, '') # Remove beginning of asset path
|
27
|
+
file = Pathname.new("#{Dir.pwd}/app/assets/javascripts/#{file}") # Ensure path is absolute
|
28
|
+
file = Pathname.new("#{file}.js") if !file.directory? && file.extname.empty? # Make sure it has an extension
|
29
|
+
file
|
30
|
+
end
|
31
|
+
|
32
|
+
def assets
|
33
|
+
all_js_assets = Rails.application.assets.each_file.to_a.map { |path| Pathname.new(path) }.select do |asset|
|
34
|
+
JAVASCRIPT_EXTENSIONS.include?(asset.extname)
|
35
|
+
end
|
36
|
+
|
37
|
+
assets = all_js_assets.select{|a| is_descendant?(@file, a)}
|
38
|
+
|
39
|
+
assets.reject{|a| a.to_s =~ /eslint.js|vendor|gems|min.js|editorial/ }
|
40
|
+
end
|
41
|
+
|
42
|
+
def eslint_js
|
43
|
+
@eslint_js ||= Rails.application.assets['eslint'].to_s
|
44
|
+
end
|
45
|
+
|
46
|
+
def eslint_plugin_js
|
47
|
+
@eslint_plugin_js ||= begin
|
48
|
+
plugins.map do |plugin_name|
|
49
|
+
Rails.application.assets["plugins/eslint-plugin-#{plugin_name}"].to_s
|
50
|
+
end.join('\n')
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def plugins
|
55
|
+
JSON.parse(Config.read)['plugins'] || []
|
56
|
+
end
|
57
|
+
|
58
|
+
def warning_hashes(file_content, relative_path, should_autocorrect=false)
|
59
|
+
if !should_autocorrect
|
60
|
+
ExecJS.eval <<-JS
|
61
|
+
function () {
|
62
|
+
window = this;
|
63
|
+
#{eslint_js};
|
64
|
+
#{eslint_plugin_js};
|
65
|
+
return new eslint().verify('#{escape_javascript(file_content)}', #{Config.read});
|
66
|
+
}()
|
67
|
+
JS
|
68
|
+
else
|
69
|
+
hsh = ExecJS.eval <<-JS
|
70
|
+
function () {
|
71
|
+
window = this;
|
72
|
+
#{eslint_js};
|
73
|
+
#{eslint_plugin_js};
|
74
|
+
return new eslint().verifyAndFix('#{escape_javascript(file_content)}', #{Config.read});
|
75
|
+
}()
|
76
|
+
JS
|
77
|
+
File.write(relative_path, hsh['output']) if !hsh['output'].nil?
|
78
|
+
hsh['messages']
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def generate_warnings(asset, should_autocorrect=false)
|
83
|
+
relative_path = asset.relative_path_from(Pathname.new(Dir.pwd))
|
84
|
+
file_content = asset.read
|
85
|
+
|
86
|
+
warning_hashes(file_content, relative_path, should_autocorrect).map do |hash|
|
87
|
+
ESLintRails::Warning.new(relative_path, hash)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def output_progress(warnings)
|
92
|
+
print case file_severity(warnings)
|
93
|
+
when :high
|
94
|
+
'H'.red
|
95
|
+
when :low
|
96
|
+
'L'.yellow
|
97
|
+
else
|
98
|
+
'.'.green
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def file_severity(warnings)
|
103
|
+
warnings.map(&:severity).uniq.sort.first
|
104
|
+
end
|
105
|
+
|
106
|
+
def is_descendant?(a, b)
|
107
|
+
a_list = a.to_s.split('/')
|
108
|
+
b_list = b.to_s.split('/')
|
109
|
+
|
110
|
+
b_list[0..a_list.size-1] == a_list
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'active_support/core_ext/string/strip'
|
2
|
+
require 'colorize'
|
3
|
+
|
4
|
+
module ESLintRails
|
5
|
+
class TextFormatter
|
6
|
+
|
7
|
+
def initialize(warnings)
|
8
|
+
@warnings = warnings
|
9
|
+
end
|
10
|
+
|
11
|
+
def format(should_autocorrect=false)
|
12
|
+
max_line_column_length = max_length_of_attribute(:location)
|
13
|
+
max_rule_id_length = max_length_of_attribute(:rule_id)
|
14
|
+
max_message_length = max_length_of_attribute(:message)
|
15
|
+
@warnings.each do |warning|
|
16
|
+
message = [
|
17
|
+
warning.location.ljust(max_line_column_length + 1),
|
18
|
+
warning.severity.to_s.ljust(6),
|
19
|
+
warning.rule_id.ljust(max_rule_id_length),
|
20
|
+
warning.message.ljust(max_message_length)
|
21
|
+
].join(" ")
|
22
|
+
colorized_message =
|
23
|
+
case warning.severity
|
24
|
+
when :low
|
25
|
+
message.yellow
|
26
|
+
when :high
|
27
|
+
message.red
|
28
|
+
else
|
29
|
+
raise 'Couldn\'t figure out how to format this mess. Stahp.'
|
30
|
+
end
|
31
|
+
puts colorized_message
|
32
|
+
end
|
33
|
+
|
34
|
+
puts "#{@warnings.size} warning(s) found #{should_autocorrect ? 'after auto-correcting some issues' : ''}"
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def max_length_of_attribute(attr_key)
|
40
|
+
@warnings.map { |warning| warning.send(attr_key).size }.max
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module ESLintRails
|
2
|
+
class Warning
|
3
|
+
attr_reader :filename, :line, :column, :node_type
|
4
|
+
|
5
|
+
SEVERITY = [ :low, :high ].freeze
|
6
|
+
private_constant :SEVERITY
|
7
|
+
|
8
|
+
def initialize(filename, warning_hash)
|
9
|
+
@filename = filename
|
10
|
+
@rule_id = warning_hash['ruleId'] || "unexpected error"
|
11
|
+
@severity = warning_hash['severity']
|
12
|
+
@message = warning_hash['message']
|
13
|
+
@line = warning_hash['line']
|
14
|
+
@column = warning_hash['column']
|
15
|
+
@node_type = warning_hash['nodeType']
|
16
|
+
end
|
17
|
+
|
18
|
+
def severity
|
19
|
+
SEVERITY[@severity-1]
|
20
|
+
end
|
21
|
+
|
22
|
+
def location
|
23
|
+
"#{filename}:#{line}:#{column}"
|
24
|
+
end
|
25
|
+
|
26
|
+
def rule_id
|
27
|
+
@rule_id || 'N/A'
|
28
|
+
end
|
29
|
+
|
30
|
+
def message
|
31
|
+
@message || 'N/A'
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
ENV['EXECJS_RUNTIME'] = 'RubyRacer'
|
2
|
+
|
3
|
+
require 'eslint-rails-ee'
|
4
|
+
|
5
|
+
namespace :eslint do
|
6
|
+
def run_and_print_results(file, should_autocorrect=false)
|
7
|
+
warnings = ESLintRails::Runner.new(file).run(should_autocorrect)
|
8
|
+
raiseError = false
|
9
|
+
|
10
|
+
warnings.each do |warning|
|
11
|
+
next if warning.severity.nil?
|
12
|
+
if warning.severity.to_s.casecmp('high').zero?
|
13
|
+
raiseError = true
|
14
|
+
break
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
if warnings.empty?
|
19
|
+
puts 'All files passed! Any issues that might have existed may have been auto-corrected :)'.green
|
20
|
+
exit 0
|
21
|
+
elsif !raiseError
|
22
|
+
formatter = ESLintRails::TextFormatter.new(warnings)
|
23
|
+
puts formatter.format(should_autocorrect)
|
24
|
+
puts 'eslint reports some warnings, but they are minor enough to be passable. Might want to fix them up before release, though. :/'.yellow
|
25
|
+
exit 0
|
26
|
+
else
|
27
|
+
formatter = ESLintRails::TextFormatter.new(warnings)
|
28
|
+
puts formatter.format(should_autocorrect)
|
29
|
+
puts 'Major issues exist according to provided eslint rules. You *MUST* git gud and correct these issues before release :('.red
|
30
|
+
exit 1
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
desc %{Run ESLint against the specified JavaScript file and report warnings (default is 'application')}
|
35
|
+
task :run, [:filename, :should_autocorrect] => :environment do |_, args|
|
36
|
+
formatted_should_autocorrect = ['true'].include?(args[:should_autocorrect]) ? true : false
|
37
|
+
run_and_print_results(args[:filename] || 'application', formatted_should_autocorrect)
|
38
|
+
end
|
39
|
+
|
40
|
+
desc 'Run ESLint against all project javascript files and report warnings'
|
41
|
+
task :run_all, [:should_autocorrect] => :environment do |_, args|
|
42
|
+
formatted_should_autocorrect = ['true'].include?(args[:should_autocorrect]) ? true : false
|
43
|
+
run_and_print_results(nil, formatted_should_autocorrect) # Run all
|
44
|
+
end
|
45
|
+
|
46
|
+
desc 'Print the current configuration file (Uses local config/eslint.json if it exists; uses default config/eslint.json if it does not; optionally force default by passing a parameter)'
|
47
|
+
task :print_config, [:force_default] => :environment do |_, args|
|
48
|
+
puts ESLintRails::Config.read(force_default: args[:force_default])
|
49
|
+
end
|
50
|
+
end
|