jsc 0.1.2 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,14 @@
1
+ == 0.1.3 / 2009-12-14
2
+
3
+ BUG fix: now show every error in a file, not just the first
4
+ Exception handling for:
5
+ * file to check not found
6
+ * Name or service not known (SocketError)
7
+
8
+ == 0.1.2 / 2009-12-12
9
+
10
+ fix in --help option for jsc command when installed as gem
11
+
1
12
  == 0.1.0 / 2009-12-12
2
13
 
3
14
  * First gem release
@@ -47,9 +47,7 @@ Compile a piece of code, check for errors:
47
47
 
48
48
  ruby bin/jsc -e "function("
49
49
 
50
- <b>NOTE</b>: the library is a single file, so you can include it and just call the JSCompiler.compile(file_name, operations, compilation_level) function everywhere in your code. Check the plugins dir for samples or snippets.
51
-
52
- <b>UPDATE 20091212</b>: bin file plugins/bin/google_closure_compiler not working at the moment due to changes in project name and structure
50
+ <b>NOTE</b>: the library is a single file, so you can include it and just call one of the JSCompiler.compile* functions everywhere in your code.
53
51
 
54
52
  == EMACS SNIPPETS
55
53
 
@@ -67,7 +65,7 @@ Now, select the code to compile and run:
67
65
 
68
66
  == REQUIREMENTS:
69
67
 
70
- jsc require the {bones}[http://gemcutter.org/gems/bones] gem.
68
+ jsc requires the {bones}[http://gemcutter.org/gems/bones] gem.
71
69
 
72
70
  == INSTALL:
73
71
 
data/Rakefile CHANGED
@@ -31,7 +31,7 @@ Bones {
31
31
  authors 'sub'
32
32
  email 'fitzkarraldo@gmail.com'
33
33
  url 'http://github.com/sub/jsc'
34
- version '0.1.2'
34
+ version '0.1.3'
35
35
  summary 'Simple Ruby API to Google Closure Compiler Web service'
36
36
  }
37
37
 
data/bin/jsc CHANGED
@@ -82,10 +82,5 @@ unless ARGV.length > 0 or file
82
82
  exit 0
83
83
  end
84
84
 
85
- code = ARGV.shift
86
-
87
- if file
88
- puts JSCompiler.compile_file(file_path, output_info, level)
89
- else
90
- puts JSCompiler.compile(code, output_info, level)
91
- end
85
+ arg = file_path.blank? ? ARGV.shift : file_path
86
+ puts JSCompiler.compile(arg, file, output_info, level)
@@ -0,0 +1 @@
1
+ function hello(a){return; alert(\"Hello, \"+a)}hello(\"New user\")
@@ -0,0 +1,169 @@
1
+ require 'rubygems' # include RubyGems
2
+ gem 'activesupport' # load ActiveSupport
3
+ require 'activesupport' # include ActiveSupport
4
+ require 'active_support/core_ext/integer/inflections'
5
+
6
+ require 'json'
7
+ require 'net/http'
8
+
9
+ module JSCompiler
10
+
11
+ # CONFIGURE this with the relative path to your javascript
12
+ # folder (typically public/javascripts in a RAILS APP)
13
+ # NO MORE NEEDED
14
+ #JAVASCRIPTS_DIR = "js/"
15
+
16
+ # Link to Google Closure Compiler service
17
+ GOOGLE_SERVICE_ADDRESS = "http://closure-compiler.appspot.com/compile"
18
+ # Default output_info parameter
19
+ DEFAULT_SERVICE = "compiled_code"
20
+ # Default compilation_level parameter
21
+ DEFAULT_LEVEL = "SIMPLE_OPTIMIZATIONS"
22
+
23
+ class << self
24
+
25
+ # Creates the <em>JSON</em> hash for the request and returns the hash to send along with the request
26
+ #
27
+ # Accepted parameters:
28
+ # * <b>code</b>: json_code parameter
29
+ # * <b>level</b>: compilation_level parameter
30
+ def create_json_request(code)
31
+ parameters = {
32
+ "code" => code,
33
+ "level" => @level,
34
+ "format" => "json",
35
+ "info" => @op
36
+ }
37
+ end
38
+
39
+ # Sends the JSON request <em>data</em> hash to Google service and returns its response
40
+ #
41
+ def post_to_cc(data)
42
+ post_args = {
43
+ 'js_code' => data["code"],
44
+ 'compilation_level' => data["level"],
45
+ 'output_format' => data["format"],
46
+ 'output_info' => data["info"]
47
+ }
48
+ # send the request
49
+ resp, data = Net::HTTP.post_form(URI.parse(GOOGLE_SERVICE_ADDRESS), post_args)
50
+ end
51
+
52
+ # Reads the <em>file_name</em> file and calls compile method on it
53
+ #
54
+ # Accepted parameters:
55
+ # * <b>file_name</b>: absolute path to file
56
+ # * <b>op</b>: output_info parameter
57
+ # * <b>level</b>: compilation_level parameter
58
+ def compile_file(file_name, op, level)
59
+ # javascript_code = read_file(JAVASCRIPTS_DIR + file_name)
60
+ # resp, data = post_to_cc(create_json_request(javascript_code, op, level))
61
+ # parse_json_output(data, op)
62
+
63
+ javascript_code = read_file(file_name)
64
+ compile(javascript_code, op, level)
65
+ end
66
+
67
+ # Compiles <em>javascript_code</em> code and returns parsed output
68
+ #
69
+ # Accepted parameters:
70
+ # * <b>req</b>: the code to compile
71
+ # * <b>op</b>: output_info parameter
72
+ # * <b>level</b>: compilation_level parameter
73
+ def compile(req, is_file, op, level)
74
+ @op = op.blank? ? DEFAULT_SERVICE : op
75
+ @level = level.blank? ? DEFAULT_LEVEL : level
76
+
77
+ js_code = is_file ? read_file(qualcosa) : qualcosa
78
+ resp, data = post_to_cc(create_json_request(js_code))
79
+ parse_json_output(data)
80
+ end
81
+
82
+ # Calls compile method for every file in <em>dir</em> directory
83
+ #
84
+ # Accepted parameters:
85
+ # * <b>dir</b>: the directory
86
+ # * <b>op</b>: output_info parameter
87
+ # * <b>level</b>: compilation_level parameter
88
+ def compile_dir(dir, op, level)
89
+ out = String.new
90
+ Dir.entries(dir).each do |file|
91
+ if File.extname(file) == ".js"
92
+ out << "Statistics for file #{file}...\n"
93
+ out << compile_file(file, op, level) + "\n***************\n"
94
+ end
95
+ end
96
+ return out
97
+ end
98
+
99
+ # Parses and returns JSON server <em>response</em>
100
+ #
101
+ # Accepted parameters:
102
+ # * <b>response</b>: the server response
103
+ def parse_json_output(response)
104
+ out = String.new
105
+ parsed_response = JSON.parse(response, :max_nesting => false)
106
+ #p response
107
+
108
+ if parsed_response.has_key?("serverErrors")
109
+ result = parsed_response['serverErrors']
110
+ return "Server Error: #{result[0]['error']} - Error Code: #{result[0]['code']}"
111
+ end
112
+
113
+ case @op
114
+ when "compiled_code"
115
+ out = parsed_response['compiledCode']
116
+ when "statistics"
117
+ result = parsed_response['statistics']
118
+ out = create_statistics_output(result)
119
+ else "errors"
120
+ #case for errors or warnings
121
+ begin
122
+ result = parsed_response[@op]
123
+ unless result.nil?
124
+ result.each do |message|
125
+ out = "#{message['type']}: " + message[@op.singularize] + " at line #{message['lineno']} character #{message['charno']}\n"
126
+ out << message['line'] unless message['line'].nil?
127
+ return out
128
+ end
129
+ else
130
+ return "No #{@op}"
131
+ end
132
+ rescue
133
+ out = "Error parsing JSON output...Check your output"
134
+ end
135
+ end
136
+ end
137
+
138
+ # Reads file and returns its content
139
+ #
140
+ # Accepted parameters:
141
+ # * <b>file_name</b>: the absolute path to the file
142
+ def read_file(file_name)
143
+ begin
144
+ # content = File.open(JAVASCRIPTS_DIR + file_name).read
145
+ content = File.open(file_name).read
146
+ return content, true
147
+ rescue
148
+ out = "ERROR reading #{file_name} file"
149
+ return out, false
150
+ end
151
+ end
152
+
153
+ # Parses and returns the <em>result</em> JSON server response
154
+ #
155
+ # Accepted parameters:
156
+ # * <b>result</b>: the already parsed JSON server response
157
+ def create_statistics_output(result)
158
+ size_improvement = result['originalSize'] - result['compressedSize']
159
+ size_gzip_improvement = result['originalGzipSize'] - result['compressedGzipSize']
160
+ rate_improvement = (size_improvement * 100)/result['originalSize']
161
+ rate_gzip_improvement = (size_gzip_improvement * 100)/result['originalGzipSize']
162
+ out = "Original Size: #{result['originalSize']} bytes (#{result['originalGzipSize']} bytes gzipped) \n"
163
+ out << "Compiled Size: #{result['compressedSize']} bytes (#{result['compressedGzipSize']} bytes gzipped) \n"
164
+ out << "\t Saved #{rate_improvement}% off the original size (#{rate_gzip_improvement}% off the gzipped size)"
165
+ end
166
+
167
+ end
168
+
169
+ end
@@ -6,13 +6,6 @@ require 'active_support/core_ext/integer/inflections'
6
6
  require 'json'
7
7
  require 'net/http'
8
8
 
9
- module JSCompiler
10
-
11
- # CONFIGURE this with the relative path to your javascript
12
- # folder (typically public/javascripts in a RAILS APP)
13
- # NO MORE NEEDED
14
- #JAVASCRIPTS_DIR = "js/"
15
-
16
9
  # Link to Google Closure Compiler service
17
10
  GOOGLE_SERVICE_ADDRESS = "http://closure-compiler.appspot.com/compile"
18
11
  # Default output_info parameter
@@ -20,6 +13,8 @@ DEFAULT_SERVICE = "compiled_code"
20
13
  # Default compilation_level parameter
21
14
  DEFAULT_LEVEL = "SIMPLE_OPTIMIZATIONS"
22
15
 
16
+ module JSCompiler
17
+
23
18
  class << self
24
19
 
25
20
  # Creates the <em>JSON</em> hash for the request and returns the hash to send along with the request
@@ -49,32 +44,36 @@ DEFAULT_LEVEL = "SIMPLE_OPTIMIZATIONS"
49
44
  resp, data = Net::HTTP.post_form(URI.parse(GOOGLE_SERVICE_ADDRESS), post_args)
50
45
  end
51
46
 
52
- # Reads the <em>file_name</em> file and calls compile method on it
47
+ # Compiles a file or a piece of code and returns parsed output
53
48
  #
54
49
  # Accepted parameters:
55
- # * <b>file_name</b>: absolute path to file
50
+ # * <b>arg</b>: the code or the file path to compile
51
+ # * <b>is_file</b>: 0 => arg is code
52
+ # 1 => arg is a file path
56
53
  # * <b>op</b>: output_info parameter
57
54
  # * <b>level</b>: compilation_level parameter
58
- def compile_file(file_name, op, level)
59
- # javascript_code = read_file(JAVASCRIPTS_DIR + file_name)
60
- # resp, data = post_to_cc(create_json_request(javascript_code, op, level))
61
- # parse_json_output(data, op)
62
-
63
- javascript_code = read_file(file_name)
64
- compile(javascript_code, op, level)
65
- end
66
-
67
- # Compiles <em>javascript_code</em> code and returns parsed output
68
- #
69
- # Accepted parameters:
70
- # * <b>javascript_code</b>: the code to compile
71
- # * <b>op</b>: output_info parameter
72
- # * <b>level</b>: compilation_level parameter
73
- def compile(javascript_code, op, level)
55
+ def compile(arg, is_file, op, level)
74
56
  @op = op.blank? ? DEFAULT_SERVICE : op
75
57
  @level = level.blank? ? DEFAULT_LEVEL : level
58
+ value = true
59
+
60
+ if is_file
61
+ js_code, value = read_file(arg)
62
+ else
63
+ js_code = arg
64
+ end
65
+ # js_code = is_file ? read_file(arg) : arg
66
+
67
+ unless value
68
+ return "Error reading file #{arg}"
69
+ end
70
+
71
+ begin
72
+ resp, data = post_to_cc(create_json_request(js_code))
73
+ rescue
74
+ return "Error calling the service...try again later"
75
+ end
76
76
 
77
- resp, data = post_to_cc(create_json_request(javascript_code))
78
77
  parse_json_output(data)
79
78
  end
80
79
 
@@ -89,7 +88,7 @@ DEFAULT_LEVEL = "SIMPLE_OPTIMIZATIONS"
89
88
  Dir.entries(dir).each do |file|
90
89
  if File.extname(file) == ".js"
91
90
  out << "Statistics for file #{file}...\n"
92
- out << compile_file(file, op, level) + "\n***************\n"
91
+ out << compile(file, true, op, level) + "\n***************\n"
93
92
  end
94
93
  end
95
94
  return out
@@ -102,7 +101,6 @@ DEFAULT_LEVEL = "SIMPLE_OPTIMIZATIONS"
102
101
  def parse_json_output(response)
103
102
  out = String.new
104
103
  parsed_response = JSON.parse(response, :max_nesting => false)
105
- #p response
106
104
 
107
105
  if parsed_response.has_key?("serverErrors")
108
106
  result = parsed_response['serverErrors']
@@ -121,10 +119,10 @@ DEFAULT_LEVEL = "SIMPLE_OPTIMIZATIONS"
121
119
  result = parsed_response[@op]
122
120
  unless result.nil?
123
121
  result.each do |message|
124
- out = "#{message['type']}: " + message[@op.singularize] + " at line #{message['lineno']} character #{message['charno']}\n"
125
- out << message['line'] unless message['line'].nil?
126
- return out
122
+ out << "#{message['type']}: " + message[@op.singularize] + " at line #{message['lineno']} character #{message['charno']}\n"
123
+ out << message['line'] + "\n" unless message['line'].nil?
127
124
  end
125
+ return out
128
126
  else
129
127
  return "No #{@op}"
130
128
  end
@@ -140,7 +138,6 @@ DEFAULT_LEVEL = "SIMPLE_OPTIMIZATIONS"
140
138
  # * <b>file_name</b>: the absolute path to the file
141
139
  def read_file(file_name)
142
140
  begin
143
- # content = File.open(JAVASCRIPTS_DIR + file_name).read
144
141
  content = File.open(file_name).read
145
142
  return content, true
146
143
  rescue
@@ -1,15 +1,36 @@
1
1
 
2
2
  require File.join(File.dirname(__FILE__), %w[spec_helper])
3
3
 
4
+ COMPILE_CODE = <<-EOU
5
+ function hello(name) {
6
+ alert('Hello, ' + name)
7
+ }
8
+ hello('New user');
9
+ EOU
10
+
11
+ ERROR_CODE = <<-EOU
12
+ functiont hello(name) {
13
+ alert('Hello, ' + name)
14
+ }
15
+ hello('New user');
16
+ EOU
17
+
18
+ WARNING_CODE = <<-EOU
19
+ function hello(name) {
20
+ return;
21
+ alert('Hello, ' + name)
22
+ }
23
+ hello('New user');
24
+ EOU
25
+
4
26
  describe JSCompiler do
5
27
 
6
28
  describe 'Use the web service through API' do
7
-
29
+
8
30
  describe 'Put all keys in the request' do
9
31
 
10
32
  before do
11
- code = "function hello(a){alert(\"Hello, \"+a)}hello(\"New user\");"
12
- @request = JSCompiler.create_json_request(code)
33
+ @request = JSCompiler.create_json_request(COMPILE_CODE)
13
34
  @request['level'] = "SIMPLE_OPTIMIZATIONS"
14
35
  @request['info'] = "compiled_code"
15
36
  end
@@ -37,8 +58,7 @@ describe JSCompiler do
37
58
 
38
59
  describe 'create a JSON compile-code request (default request)' do
39
60
  before do
40
- code = "function hello(a){alert(\"Hello, \"+a)}hello(\"New user\");"
41
- @request = JSCompiler.create_json_request(code)
61
+ @request = JSCompiler.create_json_request(COMPILE_CODE)
42
62
  @request['level'] = "SIMPLE_OPTIMIZATIONS"
43
63
  @request['info'] = "compiled_code"
44
64
  end
@@ -62,8 +82,7 @@ describe JSCompiler do
62
82
 
63
83
  describe 'compile code and get compiled code' do
64
84
  before do
65
- code = "function hello(a){alert(\"Hello, \"+a)}hello(\"New user\");"
66
- @resp = JSCompiler.compile(code, "compiled_code", "SIMPLE_OPTIMIZATIONS")
85
+ @resp = JSCompiler.compile(COMPILE_CODE, false, "compiled_code", "SIMPLE_OPTIMIZATIONS")
67
86
  end
68
87
 
69
88
  it 'should receive the compiled code' do
@@ -73,30 +92,28 @@ describe JSCompiler do
73
92
 
74
93
  describe 'compile code and find errors' do
75
94
  before do
76
- code = "functiont hello(a){alert(\"Hello, \"+a)}hello(\"New user\");"
77
- @resp = JSCompiler.compile(code, "errors", "SIMPLE_OPTIMIZATIONS")
95
+ @resp = JSCompiler.compile(ERROR_CODE, false, "errors", "SIMPLE_OPTIMIZATIONS")
78
96
  end
79
97
 
80
98
  it 'should return the result string' do
81
99
  @resp.should match(/at line/)
82
100
  end
83
101
  end
84
-
102
+
85
103
  describe 'compile code and find warnings' do
86
104
  before do
87
- code = "function hello(a){return; alert(\"Hello, \"+a)}hello(\"New user\");"
88
- @resp = JSCompiler.compile(code, "warnings", "SIMPLE_OPTIMIZATIONS")
105
+ @resp = JSCompiler.compile(WARNING_CODE, false, "warnings", "SIMPLE_OPTIMIZATIONS")
106
+ puts @resp
89
107
  end
90
108
 
91
109
  it 'should return the result string' do
92
110
  @resp.should match(/at line/)
93
111
  end
94
112
  end
95
-
113
+
96
114
  describe 'compile code and obtain statistics' do
97
115
  before do
98
- code = "function hello(a){alert(\"Hello, \"+a)}hello(\"New user\");"
99
- @resp = JSCompiler.compile(code, "statistics", "SIMPLE_OPTIMIZATIONS")
116
+ @resp = JSCompiler.compile(COMPILE_CODE, false, "statistics", "SIMPLE_OPTIMIZATIONS")
100
117
  end
101
118
 
102
119
  it 'should return the result string' do
@@ -109,12 +126,18 @@ describe JSCompiler do
109
126
  before do
110
127
  #test file
111
128
  @file_name = 'js/compiled_code.js'
129
+ @file_not_found = 'js/not_found.js'
112
130
  end
113
131
 
114
132
  it 'should return the code without errors' do
115
133
  result, value = JSCompiler.read_file(@file_name)
116
134
  value.should be_true
117
135
  end
136
+
137
+ it 'should return error if file not found' do
138
+ result, value = JSCompiler.read_file(@file_not_found)
139
+ result.should match(/ERROR reading /)
140
+ end
118
141
  end
119
142
 
120
143
  describe 'compile a whole directory' do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jsc
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - sub
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-12-12 00:00:00 +01:00
12
+ date: 2009-12-14 00:00:00 +01:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -25,28 +25,31 @@ dependencies:
25
25
  description: Simple Ruby API to Google Closure Compiler Web service.
26
26
  email: fitzkarraldo@gmail.com
27
27
  executables:
28
+ - "#jsc#"
28
29
  - jsc
29
30
  extensions: []
30
31
 
31
32
  extra_rdoc_files:
32
33
  - History.txt
33
34
  - README.rdoc
35
+ - bin/#jsc#
34
36
  - bin/jsc
35
37
  files:
36
- - .bnsignore
37
38
  - .gitignore
38
39
  - History.txt
39
40
  - README.rdoc
40
41
  - Rakefile
42
+ - bin/#jsc#
41
43
  - bin/jsc
42
44
  - js/compiled_code.js
43
45
  - js/errors.js
46
+ - js/temp.js
44
47
  - js/warnings.js
45
48
  - lib/jsc.rb
49
+ - lib/jsc/clo2.rb
46
50
  - lib/jsc/closure_compiler.rb
47
- - plugins/bin/google_closure_compiler
48
51
  - plugins/jsc.el
49
- - spec/jsc.rb
52
+ - spec/jsc_spec.rb
50
53
  - spec/spec_helper.rb
51
54
  - spec/wip_spec.rb
52
55
  - tasks/jsc.rake
data/.bnsignore DELETED
@@ -1,18 +0,0 @@
1
- # The list of files that should be ignored by Mr Bones.
2
- # Lines that start with '#' are comments.
3
- #
4
- # A .gitignore file can be used instead by setting it as the ignore
5
- # file in your Rakefile:
6
- #
7
- # Bones {
8
- # ignore_file '.gitignore'
9
- # }
10
- #
11
- # For a project with a C extension, the following would be a good set of
12
- # exclude patterns (uncomment them if you want to use them):
13
- # *.[oa]
14
- # *~
15
- announcement.txt
16
- coverage
17
- doc
18
- pkg
@@ -1,42 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require File.expand_path(
4
- File.join(File.dirname(__FILE__), %w[.. .. lib google_closure_compiler]))
5
-
6
- # Give me errors!
7
- puts ClosureCompiler.compile_file("test_errors.js", "errors")
8
- puts "**************\n"
9
-
10
- # Read file and compile it!
11
-
12
- # function passing it the relative path of the file
13
- code_to_compile, result = ClosureCompiler.read_file('test.js')
14
- if result
15
- compiled_code = ClosureCompiler.compile(code_to_compile, "compiled_code")
16
- unless compiled_code.nil?
17
- puts compiled_code
18
- end
19
- else
20
- puts "ERROR reading file\n"
21
- end
22
- puts "**************\n"
23
-
24
- # Give me statistics!
25
- code_to_compile = "function hello(a){alert(\"Hello, \"+a)}hello(\"New user\");"
26
- puts ClosureCompiler.compile(code_to_compile, "statistics")
27
- puts "**************\n"
28
-
29
- # Compile a whole directory
30
- js_dir = "js" # relative path to js directory
31
- puts "Compiling a WHOLE directory...\n"
32
- puts ClosureCompiler.compile_dir(js_dir, "statistics")
33
- puts "**************\n"
34
-
35
- # Execute every check on the file
36
- puts ClosureCompiler.compile_file("js/compiled_code.js", "compiled_code")
37
- puts "*******************"
38
- puts ClosureCompiler.compile_file("js/compiled_code.js", "warnings")
39
- puts "*******************"
40
- puts ClosureCompiler.compile_file("js/compiled_code.js", "errors")
41
- puts "*******************"
42
- puts ClosureCompiler.compile_file("js/compiled_code.js", "statistics")