jshint_on_rails 1.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.
- data/Changelog.markdown +8 -0
- data/Gemfile +5 -0
- data/Gemfile.lock +22 -0
- data/MIT-LICENSE +20 -0
- data/README.markdown +70 -0
- data/Rakefile +10 -0
- data/lib/jshint.rb +7 -0
- data/lib/jshint/config/jshint.yml +91 -0
- data/lib/jshint/errors.rb +9 -0
- data/lib/jshint/lint.rb +80 -0
- data/lib/jshint/rails.rb +4 -0
- data/lib/jshint/railtie.rb +21 -0
- data/lib/jshint/tasks.rb +27 -0
- data/lib/jshint/utils.rb +80 -0
- data/lib/jshint/vendor/jshint.js +6011 -0
- data/lib/jshint/vendor/rhino.jar +0 -0
- data/lib/jshint/vendor/test.jar +0 -0
- data/lib/jshint_on_rails.rb +1 -0
- data/spec/lint_spec.rb +179 -0
- data/spec/railtie_spec.rb +31 -0
- data/spec/spec_helper.rb +21 -0
- data/spec/utils_spec.rb +148 -0
- metadata +88 -0
Binary file
|
Binary file
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'jshint'
|
data/spec/lint_spec.rb
ADDED
@@ -0,0 +1,179 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe JSHint::Lint do
|
4
|
+
|
5
|
+
JSHint::Lint.class_eval do
|
6
|
+
attr_reader :config, :file_list
|
7
|
+
end
|
8
|
+
|
9
|
+
before :all do
|
10
|
+
File.open(JSHint::DEFAULT_CONFIG_FILE, "w") { |f| f.write "color: red\nsize: 5\nshape: circle\n" }
|
11
|
+
File.open("custom_config.yml", "w") { |f| f.write "color: blue\nsize: 7\nborder: 2\n" }
|
12
|
+
File.open("other_config.yml", "w") { |f| f.write "color: green\nborder: 0\nshape: square" }
|
13
|
+
JSHint.config_path = "custom_config.yml"
|
14
|
+
end
|
15
|
+
|
16
|
+
def setup_java(lint)
|
17
|
+
lint.should_receive(:call_java_with_output).once.and_return("OK")
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should merge default config with custom config from JSHint.config_path" do
|
21
|
+
lint = JSHint::Lint.new
|
22
|
+
lint.config.should == { 'color' => 'blue', 'size' => 7, 'border' => 2, 'shape' => 'circle' }
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should merge default config with custom config given in argument, if available" do
|
26
|
+
lint = JSHint::Lint.new :config_path => 'other_config.yml'
|
27
|
+
lint.config.should == { 'color' => 'green', 'border' => 0, 'shape' => 'square', 'size' => 5 }
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should convert predef to string if it's an array" do
|
31
|
+
File.open("predef.yml", "w") { |f| f.write "predef:\n - a\n - b\n - c" }
|
32
|
+
|
33
|
+
lint = JSHint::Lint.new :config_path => 'predef.yml'
|
34
|
+
lint.config['predef'].should == "a,b,c"
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should accept predef as string" do
|
38
|
+
File.open("predef.yml", "w") { |f| f.write "predef: d,e,f" }
|
39
|
+
|
40
|
+
lint = JSHint::Lint.new :config_path => 'predef.yml'
|
41
|
+
lint.config['predef'].should == "d,e,f"
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should not pass paths and exclude_paths options to real JSHint" do
|
45
|
+
File.open("test.yml", "w") do |f|
|
46
|
+
f.write(YAML.dump({ 'paths' => ['a', 'b'], 'exclude_paths' => ['c'], 'debug' => 'true' }))
|
47
|
+
end
|
48
|
+
lint = JSHint::Lint.new :config_path => 'test.yml'
|
49
|
+
lint.config['debug'].should == 'true'
|
50
|
+
lint.config['paths'].should be_nil
|
51
|
+
lint.config['exclude_paths'].should be_nil
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should fail if Java isn't available" do
|
55
|
+
lint = JSHint::Lint.new
|
56
|
+
lint.should_receive(:call_java_with_output).once.and_return("java: command not found")
|
57
|
+
lambda { lint.run }.should raise_error(JSHint::NoJavaException)
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should fail if JSHint check fails" do
|
61
|
+
lint = JSHint::Lint.new
|
62
|
+
setup_java(lint)
|
63
|
+
lint.should_receive(:call_java_with_status).once.and_return(false)
|
64
|
+
lambda { lint.run }.should raise_error(JSHint::LintCheckFailure)
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should not fail if JSHint check passes" do
|
68
|
+
lint = JSHint::Lint.new
|
69
|
+
setup_java(lint)
|
70
|
+
lint.should_receive(:call_java_with_status).once.and_return(true)
|
71
|
+
lambda { lint.run }.should_not raise_error
|
72
|
+
end
|
73
|
+
|
74
|
+
it "should only do Java check once" do
|
75
|
+
lint = JSHint::Lint.new
|
76
|
+
setup_java(lint)
|
77
|
+
lint.should_receive(:call_java_with_status).twice.and_return(true)
|
78
|
+
lambda do
|
79
|
+
lint.run
|
80
|
+
lint.run
|
81
|
+
end.should_not raise_error(JSHint::NoJavaException)
|
82
|
+
end
|
83
|
+
|
84
|
+
it "should pass an ampersand-separated option string to JSHint" do
|
85
|
+
lint = JSHint::Lint.new
|
86
|
+
lint.instance_variable_set("@config", { 'debug' => true, 'semicolons' => false, 'linelength' => 120 })
|
87
|
+
setup_java(lint)
|
88
|
+
param_string = ""
|
89
|
+
lint.
|
90
|
+
should_receive(:call_java_with_status).
|
91
|
+
once.
|
92
|
+
with(an_instance_of(String), an_instance_of(String), an_instance_of(String)).
|
93
|
+
and_return { |a, b, c| param_string = c; true }
|
94
|
+
lint.run
|
95
|
+
|
96
|
+
option_string = param_string.split(/\s+/).detect { |p| p =~ /linelength/ }
|
97
|
+
eval(option_string).split('&').sort.should == ['debug=true', 'linelength=120', 'semicolons=false']
|
98
|
+
end
|
99
|
+
|
100
|
+
it "should escape $ in option string when passing it to Java/JSHint" do
|
101
|
+
lint = JSHint::Lint.new
|
102
|
+
lint.instance_variable_set("@config", { 'predef' => 'window,$,Ajax,$app,Request' })
|
103
|
+
setup_java(lint)
|
104
|
+
param_string = ""
|
105
|
+
lint.
|
106
|
+
should_receive(:call_java_with_status).
|
107
|
+
once.
|
108
|
+
with(an_instance_of(String), an_instance_of(String), /window,\\\$,Ajax,\\\$app,Request/).
|
109
|
+
and_return(true)
|
110
|
+
lint.run
|
111
|
+
end
|
112
|
+
|
113
|
+
it "should pass space-separated list of files to JSHint" do
|
114
|
+
lint = JSHint::Lint.new
|
115
|
+
lint.instance_variable_set("@file_list", ['app.js', 'test.js', 'jquery.js'])
|
116
|
+
setup_java(lint)
|
117
|
+
lint.
|
118
|
+
should_receive(:call_java_with_status).
|
119
|
+
once.
|
120
|
+
with(an_instance_of(String), an_instance_of(String), /app\.js test\.js jquery\.js$/).
|
121
|
+
and_return(true)
|
122
|
+
lint.run
|
123
|
+
end
|
124
|
+
|
125
|
+
describe "file lists" do
|
126
|
+
before :each do
|
127
|
+
JSHint::Utils.stub!(:exclude_files).and_return { |inc, exc| inc - exc }
|
128
|
+
JSHint::Utils.stub!(:unique_files).and_return { |files| files.uniq }
|
129
|
+
end
|
130
|
+
|
131
|
+
before :all do
|
132
|
+
@files = ['test/app.js', 'test/lib.js', 'test/utils.js', 'test/vendor/jquery.js', 'test/vendor/proto.js']
|
133
|
+
@files.each { |fn| File.open(fn, "w") { |f| f.write("alert()") }}
|
134
|
+
@files = @files.map { |fn| File.expand_path(fn) }
|
135
|
+
end
|
136
|
+
|
137
|
+
it "should calculate a list of files to test" do
|
138
|
+
lint = JSHint::Lint.new :paths => ['test/**/*.js']
|
139
|
+
lint.file_list.should == @files
|
140
|
+
|
141
|
+
lint = JSHint::Lint.new :paths => ['test/a*.js', 'test/**/*r*.js']
|
142
|
+
lint.file_list.should == [@files[0], @files[3], @files[4]]
|
143
|
+
|
144
|
+
lint = JSHint::Lint.new :paths => ['test/a*.js', 'test/**/*r*.js'], :exclude_paths => ['**/*q*.js']
|
145
|
+
lint.file_list.should == [@files[0], @files[4]]
|
146
|
+
|
147
|
+
lint = JSHint::Lint.new :paths => ['test/**/*.js'], :exclude_paths => ['**/*.js']
|
148
|
+
lint.file_list.should == []
|
149
|
+
|
150
|
+
lint = JSHint::Lint.new :paths => ['test/**/*.js', 'test/**/a*.js', 'test/**/p*.js']
|
151
|
+
lint.file_list.should == @files
|
152
|
+
|
153
|
+
File.open("new.yml", "w") { |f| f.write(YAML.dump({ 'paths' => ['test/vendor/*.js'] })) }
|
154
|
+
|
155
|
+
lint = JSHint::Lint.new :config_path => 'new.yml', :exclude_paths => ['**/proto.js']
|
156
|
+
lint.file_list.should == [@files[3]]
|
157
|
+
|
158
|
+
lint = JSHint::Lint.new :config_path => 'new.yml', :paths => ['test/l*.js']
|
159
|
+
lint.file_list.should == [@files[1]]
|
160
|
+
end
|
161
|
+
|
162
|
+
it "should accept :paths and :exclude_paths as string instead of one-element array" do
|
163
|
+
lambda do
|
164
|
+
lint = JSHint::Lint.new :paths => 'test/*.js', :exclude_paths => 'test/lib.js'
|
165
|
+
lint.file_list.should == [@files[0], @files[2]]
|
166
|
+
end.should_not raise_error
|
167
|
+
end
|
168
|
+
|
169
|
+
it "should ignore empty files" do
|
170
|
+
File.open("test/empty.js", "w") { |f| f.write("") }
|
171
|
+
File.open("test/full.js", "w") { |f| f.write("qqq") }
|
172
|
+
|
173
|
+
lint = JSHint::Lint.new :paths => ['test/*.js']
|
174
|
+
lint.file_list.should_not include(File.expand_path("test/empty.js"))
|
175
|
+
lint.file_list.should include(File.expand_path("test/full.js"))
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'jshint/railtie'
|
3
|
+
|
4
|
+
describe JSHint::Railtie do
|
5
|
+
before :all do
|
6
|
+
File.open(JSHint::DEFAULT_CONFIG_FILE, "w") { |f| f.write "foo" }
|
7
|
+
JSHint.config_path = "custom_config.yml"
|
8
|
+
end
|
9
|
+
|
10
|
+
before :each do
|
11
|
+
File.delete(JSHint.config_path) if File.exist?(JSHint.config_path)
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "create_example_config" do
|
15
|
+
it "should create a config file if it doesn't exist" do
|
16
|
+
JSHint::Railtie.create_example_config
|
17
|
+
|
18
|
+
File.exist?(JSHint.config_path).should be_true
|
19
|
+
File.read(JSHint.config_path).should == "foo"
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should not do anything if config already exists" do
|
23
|
+
File.open(JSHint.config_path, "w") { |f| f.write "bar" }
|
24
|
+
|
25
|
+
JSHint::Railtie.create_example_config
|
26
|
+
|
27
|
+
File.exist?(JSHint.config_path).should be_true
|
28
|
+
File.read(JSHint.config_path).should == "bar"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'jshint'
|
2
|
+
require 'fakefs'
|
3
|
+
|
4
|
+
module JSHint::Utils
|
5
|
+
# disable logging to stdout
|
6
|
+
def self.xprint(x) ; end
|
7
|
+
def self.xputs(x) ; end
|
8
|
+
end
|
9
|
+
|
10
|
+
module Rails
|
11
|
+
class Railtie
|
12
|
+
def self.rake_tasks
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
module FileUtils
|
18
|
+
def copy(*args)
|
19
|
+
cp(*args)
|
20
|
+
end
|
21
|
+
end
|
data/spec/utils_spec.rb
ADDED
@@ -0,0 +1,148 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe JSHint::Utils do
|
4
|
+
|
5
|
+
JSU = JSHint::Utils
|
6
|
+
|
7
|
+
before :all do
|
8
|
+
File.open(JSHint::DEFAULT_CONFIG_FILE, "w") { |f| f.puts "default config file" }
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should have a config_path setting" do
|
12
|
+
JSHint.config_path = 'some/path'
|
13
|
+
JSHint.config_path.should == 'some/path'
|
14
|
+
end
|
15
|
+
|
16
|
+
describe "paths_from_command_line" do
|
17
|
+
it "should extract an array of paths from command line argument" do
|
18
|
+
ENV['test_arg'] = 'one,two,three'
|
19
|
+
JSU.paths_from_command_line('test_arg').should == ['one', 'two', 'three']
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should also work if the argument name is given in uppercase" do
|
23
|
+
ENV['TEST_ARG'] = 'ruby,python,js'
|
24
|
+
JSU.paths_from_command_line('test_arg').should == ['ruby', 'python', 'js']
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should return nil if the argument isn't set" do
|
28
|
+
JSU.paths_from_command_line('crash').should be_nil
|
29
|
+
end
|
30
|
+
|
31
|
+
after :each do
|
32
|
+
ENV['test_arg'] = nil
|
33
|
+
ENV['TEST_ARG'] = nil
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe "load_config_file" do
|
38
|
+
|
39
|
+
before :all do
|
40
|
+
File.open("sample.yml", "w") { |f| f.puts("framework: rails") }
|
41
|
+
Dir.mkdir("tmp")
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should load a YAML file if it can be read" do
|
45
|
+
JSU.load_config_file("sample.yml").should == { 'framework' => 'rails' }
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should return an empty hash if file name is nil" do
|
49
|
+
JSU.load_config_file(nil).should == {}
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should return an empty hash if file doesn't exist" do
|
53
|
+
JSU.load_config_file("crack.exe").should == {}
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should return an empty hash if file is not a file" do
|
57
|
+
JSU.load_config_file("tmp").should == {}
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should return an empty hash if file is not readable" do
|
61
|
+
File.should_receive(:readable?).once.with("sample.yml").and_return(false)
|
62
|
+
JSU.load_config_file("sample.yml").should == {}
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
describe "unique and exclude" do
|
67
|
+
def set_identical(file1, file2, value)
|
68
|
+
File.should_receive(:identical?).with(file1, file2).once.and_return(value)
|
69
|
+
end
|
70
|
+
|
71
|
+
it "should remove duplicate files from a list" do
|
72
|
+
set_identical('config.yml', 'lib/../config.yml', true)
|
73
|
+
set_identical('config.yml', 'Rakefile', false)
|
74
|
+
set_identical('config.yml', 'Config.yml', true)
|
75
|
+
unique = JSU.unique_files(['config.yml', 'lib/../config.yml', 'Rakefile', 'Config.yml'])
|
76
|
+
unique.should == ['config.yml', 'Rakefile']
|
77
|
+
end
|
78
|
+
|
79
|
+
it "should subtract files on the second list from the first list" do
|
80
|
+
set_identical('RaKeFiLe', 'config.yml', false)
|
81
|
+
set_identical('wtf', 'config.yml', false)
|
82
|
+
set_identical('Config.yml', 'config.yml', true)
|
83
|
+
set_identical('RaKeFiLe', 'Rakefile', true)
|
84
|
+
set_identical('RaKeFiLe', 'Gemfile', false)
|
85
|
+
set_identical('wtf', 'Gemfile', false)
|
86
|
+
set_identical('Config.yml', 'Gemfile', false)
|
87
|
+
included = JSU.exclude_files(['config.yml', 'Rakefile', 'Gemfile'], ['RaKeFiLe', 'wtf', 'Config.yml'])
|
88
|
+
included.should == ['Gemfile']
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
describe "copy_config_file" do
|
93
|
+
it "throw an error if config path isn't set" do
|
94
|
+
JSHint.config_path = nil
|
95
|
+
lambda { JSHint::Utils.copy_config_file }.should raise_error(ArgumentError)
|
96
|
+
end
|
97
|
+
|
98
|
+
it "should copy default config to config_path" do
|
99
|
+
JSHint.config_path = "newfile.yml"
|
100
|
+
FileUtils.should_receive(:copy).with(JSHint::DEFAULT_CONFIG_FILE, "newfile.yml")
|
101
|
+
JSHint::Utils.copy_config_file
|
102
|
+
end
|
103
|
+
|
104
|
+
it "should not overwrite the file if it exists" do
|
105
|
+
JSHint.config_path = "newfile2.yml"
|
106
|
+
File.open("newfile2.yml", "w") { |f| f.write("qwe") }
|
107
|
+
FileUtils.should_not_receive(:copy)
|
108
|
+
JSHint::Utils.copy_config_file
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
describe "remove_config_file" do
|
113
|
+
it "throw an error if config path isn't set" do
|
114
|
+
JSHint.config_path = nil
|
115
|
+
lambda { JSHint::Utils.remove_config_file }.should raise_error(ArgumentError)
|
116
|
+
end
|
117
|
+
|
118
|
+
it "should remove the file if it's identical to default one" do
|
119
|
+
JSHint.config_path = "newfile3.yml"
|
120
|
+
File.open("newfile3.yml", "w") { |f| f.puts("default config file") }
|
121
|
+
File.exists?("newfile3.yml").should be_true
|
122
|
+
JSHint::Utils.remove_config_file
|
123
|
+
File.exists?("newfile3.yml").should be_false
|
124
|
+
end
|
125
|
+
|
126
|
+
it "should not remove the file if it's not identical to default one" do
|
127
|
+
JSHint.config_path = "newfile4.yml"
|
128
|
+
File.open("newfile4.yml", "w") { |f| f.puts("something's changed") }
|
129
|
+
File.exists?("newfile4.yml").should be_true
|
130
|
+
JSHint::Utils.remove_config_file
|
131
|
+
File.exists?("newfile4.yml").should be_true
|
132
|
+
end
|
133
|
+
|
134
|
+
it "should not remove the file if it doesn't exist" do
|
135
|
+
JSHint.config_path = "this_doesnt_exist.yml"
|
136
|
+
lambda { JSHint::Utils.remove_config_file }.should_not raise_error
|
137
|
+
end
|
138
|
+
|
139
|
+
it "should not remove the file if it's not a file" do
|
140
|
+
Dir.mkdir("public")
|
141
|
+
JSHint.config_path = "public"
|
142
|
+
lambda { JSHint::Utils.remove_config_file }.should_not raise_error
|
143
|
+
File.exist?("public").should be_true
|
144
|
+
File.directory?("public").should be_true
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
end
|
metadata
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: jshint_on_rails
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 21
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 1
|
8
|
+
- 0
|
9
|
+
- 1
|
10
|
+
version: 1.0.1
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Bruno Gouveia
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2011-05-13 00:00:00 -03:00
|
19
|
+
default_executable:
|
20
|
+
dependencies: []
|
21
|
+
|
22
|
+
description:
|
23
|
+
email: brunogouveia@buzungo.com.br
|
24
|
+
executables: []
|
25
|
+
|
26
|
+
extensions: []
|
27
|
+
|
28
|
+
extra_rdoc_files: []
|
29
|
+
|
30
|
+
files:
|
31
|
+
- MIT-LICENSE
|
32
|
+
- README.markdown
|
33
|
+
- Changelog.markdown
|
34
|
+
- Gemfile
|
35
|
+
- Gemfile.lock
|
36
|
+
- Rakefile
|
37
|
+
- lib/jshint/config/jshint.yml
|
38
|
+
- lib/jshint/errors.rb
|
39
|
+
- lib/jshint/lint.rb
|
40
|
+
- lib/jshint/rails.rb
|
41
|
+
- lib/jshint/railtie.rb
|
42
|
+
- lib/jshint/tasks.rb
|
43
|
+
- lib/jshint/utils.rb
|
44
|
+
- lib/jshint/vendor/jshint.js
|
45
|
+
- lib/jshint/vendor/rhino.jar
|
46
|
+
- lib/jshint/vendor/test.jar
|
47
|
+
- lib/jshint.rb
|
48
|
+
- lib/jshint_on_rails.rb
|
49
|
+
- spec/lint_spec.rb
|
50
|
+
- spec/railtie_spec.rb
|
51
|
+
- spec/spec_helper.rb
|
52
|
+
- spec/utils_spec.rb
|
53
|
+
has_rdoc: true
|
54
|
+
homepage: http://github.com/bgouveia/jshint_on_rails
|
55
|
+
licenses: []
|
56
|
+
|
57
|
+
post_install_message:
|
58
|
+
rdoc_options: []
|
59
|
+
|
60
|
+
require_paths:
|
61
|
+
- lib
|
62
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
63
|
+
none: false
|
64
|
+
requirements:
|
65
|
+
- - ">="
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
hash: 3
|
68
|
+
segments:
|
69
|
+
- 0
|
70
|
+
version: "0"
|
71
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
72
|
+
none: false
|
73
|
+
requirements:
|
74
|
+
- - ">="
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
hash: 3
|
77
|
+
segments:
|
78
|
+
- 0
|
79
|
+
version: "0"
|
80
|
+
requirements:
|
81
|
+
- Java JRE (5.0 or later)
|
82
|
+
rubyforge_project:
|
83
|
+
rubygems_version: 1.5.0
|
84
|
+
signing_key:
|
85
|
+
specification_version: 3
|
86
|
+
summary: JSHint is a little more flexible JavaScript checker, wrapped in a Ruby gem for easier use
|
87
|
+
test_files: []
|
88
|
+
|