jsus 0.3.4 → 0.3.5

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG CHANGED
@@ -1,4 +1,11 @@
1
1
  = Jsus Changelog
2
+ == Version 0.3.5
3
+ Other changes:
4
+ * Faster cycle search; fails fast and makes --no-cycle-search option obsolete
5
+ * Fixed error reporting routine when package.json / .yml was missing.
6
+ * New compression methods: frontcompiler, closure, uglifier
7
+ (besides the default yui) [Thanks to Pavel Evstigneev]
8
+
2
9
  == Version 0.3.4
3
10
  Middleware changes:
4
11
  * support for /compressed/ path component, which acts like /require/, but
data/Gemfile CHANGED
@@ -8,13 +8,26 @@ gem "rgl"
8
8
  group :development do
9
9
  gem "rake"
10
10
  gem "rspec"
11
- gem "cucumber"
11
+
12
+ # FIXME: change to the latest cucumber version when cucumber bug gets fixed
13
+ # https://github.com/cucumber/cucumber/issues/136
14
+ gem "cucumber", "1.0.3"
15
+
12
16
  gem "jeweler"
13
17
  gem "murdoc", "~> 0.1.11"
14
18
  gem "ruby-debug19", :platforms => :ruby_19
19
+
20
+ # FIXME: linecache being ruby1.9+only
21
+ gem "linecache", "= 0.45", :platforms => :ruby_18
22
+
15
23
  gem "ruby-debug", :platforms => :ruby_18
16
24
  gem 'fssm'
17
- gem 'yui-compressor'
25
+
26
+ gem 'yuicompressor', :require => false
27
+ gem 'uglifier', :require => false
28
+ gem 'front-compiler', :require => false
29
+ gem 'closure-compiler', :require => false
30
+
18
31
  gem 'sinatra'
19
32
  gem 'rack-test'
20
33
  gem 'yard'
data/Rakefile CHANGED
@@ -13,7 +13,7 @@ require 'jeweler'
13
13
  Jeweler::Tasks.new do |gem|
14
14
  # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
15
15
  gem.name = "jsus"
16
- gem.homepage = "http://github.com/markiz/jsus"
16
+ gem.homepage = "http://github.com/jsus/jsus"
17
17
  gem.license = "Public Domain"
18
18
  gem.summary = "Javascript packager and dependency resolver"
19
19
  gem.description = "Javascript packager and dependency resolver"
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.3.4
1
+ 0.3.5
@@ -1,2 +1,2 @@
1
1
  Autotest.add_discovery { "rspec2" }
2
- Autotest.add_discovery { "cucumber" }
2
+ Autotest.add_discovery { "cucumber" }
data/bin/jsus CHANGED
@@ -1,380 +1,126 @@
1
1
  #!/usr/bin/env ruby
2
2
  require 'rubygems'
3
-
4
3
  require 'pathname'
4
+
5
5
  begin
6
6
  gem_home = Pathname.new(ENV["GEM_HOME"]).realpath.to_s
7
- current_dir = File.dirname(Pathname.new(__FILE__).realpath.to_s)
8
- if current_dir.index(gem_home) != 0 && File.exists?(current_dir + '/../lib/jsus.rb')
7
+ current_dir = Pathname.new(__FILE__).realpath.dirname
8
+ if current_dir.to_s.index(gem_home) != 0 && current_dir.join('../lib/jsus.rb').exist?
9
9
  # If we are outside gem home,
10
10
  # override whatever they got there
11
11
  # with local version of jsus
12
- $:.unshift File.expand_path(current_dir + "/../lib")
12
+ $:.unshift((current_dir + "../lib").expand_path.to_s)
13
13
  end
14
14
  rescue Exception => e
15
+ raise e
15
16
  # Something weird happened during our checks,
16
17
  # but it's probably nothing.
17
18
  end
18
- require 'jsus'
19
19
 
20
- require "fileutils"
20
+ require 'jsus'
21
21
  require "optparse"
22
22
 
23
- module Jsus
24
- class CLI
25
- class <<self
26
- attr_accessor :cli_options
27
-
28
- def parse_command_line!
29
- options = {}
30
- cli = OptionParser.new do |opts|
31
- opts.banner = "jsus #{Jsus.version}. Usage: jsus [options] <input_dir> <output_dir>"
32
-
33
- opts.on('-i', '--input-directory [DIR]', '[DEPRECATED] path to input directory ') do |dir|
34
- $stderr.puts "DEPRECATION NOTICE: please do not use -i command-line argument"
35
- options[:input_dir] = dir
36
- end
37
-
38
- opts.on('-o', '--output-directory [DIR]', '[DEPRECATED] path to output directory ') do |dir|
39
- $stderr.puts "DEPRECATION NOTICE: please do not use -o command-line argument"
40
- options[:output_dir] = dir
41
- end
42
-
43
- opts.on('-d', '--with-dependencies [DEPS]', 'path to directory containing dependency packages') do |dir|
44
- options[:deps_dir] = dir
45
- end
46
-
47
- opts.on('-g', '--generate-includes [ROOT]', 'generates includes.js file that you may use for ad-hoc requiring of dependencies, defaults to output directory') do |dir|
48
- options[:generate_includes] = true
49
- options[:includes_root] = dir
50
- end
51
-
52
- opts.on('--generate-docs [*CLASSES]', Array, "generate docs for some of the sources. When given empty array, defaults to /**/*") do |docs|
53
- if !docs
54
- options[:documented_classes] = ["/**/*"]
55
- else
56
- options[:documented_classes] = docs
57
- end
58
- end
59
-
60
- opts.on('--no-syntax-highlight', 'if you turned on docs generation, it will use syntax highlighting by default. This option prevents it') do
61
- options[:no_syntax_highlight] = true
62
- end
63
-
64
- opts.on('--validate-with [*VALIDATORS]', Array, 'performs a check against some of the validators. Available validators: mooforge') do |validators|
65
- options[:validators] = (validators || []).map {|v| v.downcase }
66
- end
67
-
68
- opts.on('--postproc [*PROCESSORS]', Array, 'performs postprocessing. Available postprocs:\n* moocompat12 -- removes mootools 1.2compat tags and their contents\n* mooltIE8 -- removes mootools ltIE8 compat tags and their contents') do |postprocs|
69
- options[:postproc] = postprocs
70
- end
71
-
72
- opts.on('--compress', 'compresses resulting file with YUI compressor') do
73
- options[:compress] = true
74
- end
75
-
76
- opts.on('--no-cycle-search', 'disables search for circular dependencies which may take quite some time during compilation') do
77
- Jsus.look_for_cycles = false
78
- end
79
-
80
- opts.on_tail('-v', '--verbose', 'verbose mode, shows various debug messages') do
81
- Jsus.verbose = true
82
- end
83
-
84
- opts.on_tail('--very-verbose', 'very verbose mode, shows pool stats beside usual verbose stuff') do
85
- Jsus.verbose = true
86
- options[:display_pool_stats] = true
87
- end
88
-
89
- opts.on_tail('-b', '--benchmark', 'shows time spent on various stages') do
90
- options[:benchmark] = true
91
- end
92
-
93
- opts.on_tail('--without-scripts-info', 'do not generate scripts.json') do
94
- options[:without_scripts_info] = true
95
- end
96
-
97
- opts.on_tail('--without-tree-info', 'do not generate tree.json') do
98
- options[:without_tree_info] = true
99
- end
100
-
101
- opts.on_tail('--watch', 'watch file system events for *.js files in subdirectories and rerun jsus with the same parameters') do
102
- options[:watch] = true
103
- end
104
-
105
- opts.on_tail('-h', '--help', 'Show this message') do
106
- puts opts
107
- exit
108
- end
109
- end
110
- cli.parse!
111
-
112
- options[:input_dir] ||= ARGV[0]
113
- options[:output_dir] ||= ARGV[1]
114
-
115
- if !(options[:input_dir] && options[:output_dir])
116
- puts cli
117
- exit
118
- end
119
- options[:input_dir] = File.expand_path(options[:input_dir])
120
- options[:output_dir] = File.expand_path(options[:output_dir])
121
- self.cli_options = options
122
- end
123
-
124
- def watch?
125
- cli_options[:watch]
126
- end
127
-
128
- def launch!
129
- new.launch
130
- end
131
-
132
- def run!
133
- parse_command_line!
134
- launch!
135
- if watch?
136
- watch do |base, match|
137
- full_path = File.join(base, match)
138
- unless full_path.include?(cli_options[:output_dir])
139
- puts "#{match} has changed, relaunching jsus..."
140
- begin
141
- launch!
142
- puts "... done"
143
- rescue Exception => e
144
- puts "Exception happened: #{e}, #{e.inspect}"
145
- puts "\t#{e.backtrace.join("\n\t")}" if Jsus.verbose?
146
- puts "Compilation FAILED."
147
- end
148
- puts ""
149
- end
150
- end
151
- end
152
- end
153
-
154
- def watch
155
- require 'fssm'
156
- puts "Jsus enters watch mode, it will watch your files for changes and relaunch itself"
157
- puts ""
158
- start_directory = Dir.pwd
159
- watched_dirs = [cli_options[:input_dir], cli_options[:deps_dir]].compact.map {|path| File.expand_path(path)}
160
-
161
- watched_dirs.reject! do |dir|
162
- # This is a work around for rb-fsevent quirk
163
- # Apparently, when your dependency dir is a child directory for your input dir,
164
- # You get problems.
165
- result = false
166
- pathname_traversal = Pathname.new(dir).descend do |parent|
167
- parent = parent.to_s
168
- result ||= watched_dirs.include?(parent) && parent != dir
169
- end
170
- result
171
- end
172
-
173
- puts "Watching directories: " + watched_dirs.inspect if Jsus.verbose?
174
- FSSM.monitor do
175
- watched_dirs.each do |dir|
176
- path dir do
177
- glob ["**/*.js", "**/package.yml", "**/package.json"]
178
- update {|base, relative| yield base, relative }
179
- delete {|base, relative| yield base, relative }
180
- create {|base, relative| yield base, relative }
181
- end
182
- end
183
- end
184
-
185
- rescue LoadError => e
186
- puts "You need to install fssm gem for --watch option."
187
- puts "You may also want to install rb-fsevent for OS X"
188
- raise e
189
- end
190
-
191
- end
23
+ Jsus.logger = Jsus::Util::Logger.new(STDOUT)
24
+ Jsus.logger.formatter = lambda {|severity, time, progname, msg|
25
+ prefix = case severity
26
+ when /error/i, /fatal/i, /warn/i then "[#{severity}]: "
27
+ else ""
28
+ end
29
+ "#{prefix}#{msg}\n"
30
+ }
192
31
 
193
- attr_accessor :options
32
+ options = {}
33
+ cli = OptionParser.new do |opts|
34
+ opts.banner = "jsus #{Jsus.version}. Usage: jsus [options] <input_dir> <output_dir>"
194
35
 
195
- def initialize(options = Jsus::CLI.cli_options)
196
- @options = options
197
- end
36
+ opts.on('-i', '--input-directory [DIR]', '[DEPRECATED] path to input directory ') do |dir|
37
+ Jsus.logger.warn "DEPRECATION NOTICE: please do not use -i command-line argument"
38
+ options[:input_dir] = dir
39
+ end
198
40
 
199
- def launch
200
- checkpoint(:start)
201
- setup_output_directory
202
- preload_pool
203
- load_package
204
- display_pool_stats if options[:display_pool_stats]
205
- compile_package
206
- post_process if options[:postproc]
207
- compress_package if options[:compress]
208
- package_filename = File.join(@output_dir, @package.filename)
209
- File.open(package_filename, 'w') {|f| f << @package_content }
210
- generate_supplemental_files
211
- validate_sources
212
- generate_includes if options[:generate_includes]
213
- generate_docs if options[:documented_classes] && !options[:documented_classes].empty?
214
- output_benchmarks
215
- end
41
+ opts.on('-o', '--output-directory [DIR]', '[DEPRECATED] path to output directory ') do |dir|
42
+ Jsus.logger.warn "DEPRECATION NOTICE: please do not use -o command-line argument"
43
+ options[:output_dir] = dir
44
+ end
216
45
 
217
- def setup_output_directory
218
- @output_dir = options[:output_dir]
219
- FileUtils.mkdir_p(@output_dir)
220
- end
46
+ opts.on('-d', '--with-dependencies [DEPS]', 'path to directory containing dependency packages') do |dir|
47
+ options[:deps_dir] = dir
48
+ end
221
49
 
222
- def preload_pool
223
- @pool = if options[:deps_dir]
224
- Jsus::Pool.new(options[:deps_dir])
225
- else
226
- Jsus::Pool.new
227
- end
228
- checkpoint(:pool)
229
- end
50
+ opts.on('-g', '--generate-includes [ROOT]', 'generates includes.js file that you may use for ad-hoc requiring of dependencies, defaults to output directory') do |dir|
51
+ options[:generate_includes] = true
52
+ options[:includes_root] = dir
53
+ end
230
54
 
231
- def load_package
232
- @package = Jsus::Package.new(options[:input_dir], :pool => @pool)
233
- @package.include_dependencies!
234
- checkpoint(:dependencies)
55
+ opts.on('--generate-docs [*CLASSES]', Array, "generate docs for some of the sources. When given empty array, defaults to /**/*") do |docs|
56
+ if !docs
57
+ options[:documented_classes] = ["/**/*"]
58
+ else
59
+ options[:documented_classes] = docs
235
60
  end
61
+ end
236
62
 
237
- def display_pool_stats
238
- checkpoint(:pool_stats)
239
- puts ""
240
- puts "Pool stats:"
241
- puts ""
242
- puts "Main package:"
243
- display_package @package
244
- puts "Supplementary packages:"
245
- @pool.packages.each do |package|
246
- display_package package
247
- end
248
- puts ""
249
- end
63
+ opts.on('--no-syntax-highlight', 'if you turned on docs generation, it will use syntax highlighting by default. This option prevents it') do
64
+ options[:no_syntax_highlight] = true
65
+ end
250
66
 
251
- def display_package(package)
252
- puts "Package: #{package.name}"
253
- package.source_files.to_a.sort_by {|sf| sf.filename}.each do |sf|
254
- puts " [#{sf.relative_filename}]"
255
- puts " Provides: [#{sf.provides_names.join(", ")}]"
256
- puts " Requires: [#{sf.requires_names.join(", ")}]"
257
- end
258
- puts ""
259
- end
67
+ opts.on('--validate-with [*VALIDATORS]', Array, 'performs a check against some of the validators. Available validators: mooforge') do |validators|
68
+ options[:validators] = (validators || []).map {|v| v.downcase }
69
+ end
260
70
 
261
- def compile_package
262
- @package_content = @package.compile(nil)
263
- checkpoint(:compilation)
264
- end
71
+ opts.on('--postproc [*PROCESSORS]', Array, 'performs postprocessing. Available postprocs:\n* moocompat12 -- removes mootools 1.2compat tags and their contents\n* mooltIE8 -- removes mootools ltIE8 compat tags and their contents') do |postprocs|
72
+ options[:postproc] = postprocs
73
+ end
265
74
 
266
- def post_process
267
- options[:postproc].each do |processor|
268
- case processor.strip
269
- when /^moocompat12$/i
270
- @package_content.gsub!(/\/\/<1.2compat>.*?\/\/<\/1.2compat>/m, '')
271
- @package_content.gsub!(/\/\*<1.2compat>\*\/.*?\/\*<\/1.2compat>\*\//m, '')
272
- when /^mooltie8$/i
273
- @package_content.gsub!(/\/\/<ltIE8>.*?\/\/<\/ltIE8>/m, '')
274
- @package_content.gsub!(/\/\*<ltIE8>\*\/.*?\/\*<\/ltIE8>\*\//m, '')
275
- else
276
- $stderr.puts "Unknown post-processor: #{processor}"
277
- end
278
- end
279
- checkpoint(:postproc)
280
- end
75
+ opts.on('--compress', 'compresses resulting file') do
76
+ options[:compress] = true
77
+ end
281
78
 
282
- def compress_package
283
- compressed_content = Jsus::Util::Compressor.new(@package_content).result
284
- if compressed_content != ""
285
- @compression_ratio = compressed_content.size.to_f / @package_content.size.to_f
286
- compressed_file_name = @package.filename.sub(/.js$/, ".min.js")
287
- File.open(File.join(@output_dir, compressed_file_name), "w") {|f| f.write(compressed_content) }
288
- else
289
- @compression_ratio = 1.00
290
- puts "ERROR: YUI compressor could not parse input. "
291
- puts "Compressor command used: #{compressor.command.join(' ')}"
292
- end
293
- checkpoint(:compress)
294
- end
79
+ opts.on('--compression-method [METHOD]', 'compression method: yui, closure, frontcompiler or uglifier') do |method|
80
+ options[:compression_method] = method
81
+ end
295
82
 
296
- def generate_supplemental_files
297
- @package.generate_scripts_info(@output_dir) unless options[:without_scripts_info]
298
- @package.generate_tree(@output_dir) unless options[:without_tree_info]
299
- checkpoint(:supplemental_files)
300
- end
83
+ opts.on_tail('-v', '--verbose', 'verbose mode, shows various debug messages') do
84
+ Jsus.verbose = true
85
+ end
301
86
 
302
- def generate_includes
303
- includes_root = options[:includes_root] || @output_dir
304
- File.open(File.join(@output_dir, "includes.js"), "w") do |f|
305
- c = Jsus::Container.new(*(@package.source_files.to_a + @package.linked_external_dependencies.to_a))
306
- paths = c.required_files(includes_root)
307
- f.puts Jsus::Util::CodeGenerator.generate_includes(paths)
308
- end
309
- checkpoint(:includes)
310
- end
87
+ opts.on_tail('--very-verbose', 'very verbose mode, shows pool stats beside usual verbose stuff') do
88
+ Jsus.verbose = true
89
+ options[:display_pool_stats] = true
90
+ end
311
91
 
312
- def generate_docs
313
- documenter = Jsus::Util::Documenter.new(:highlight_source => !options[:no_syntax_highlight])
314
- @package.source_files.each {|source| documenter << source }
315
- @pool.sources.each {|source| documenter << source }
316
- documenter.only(options[:documented_classes]).generate(@output_dir + "/docs")
317
- checkpoint(:documentation)
318
- end
92
+ opts.on_tail('-b', '--benchmark', 'shows time spent on various stages') do
93
+ options[:benchmark] = true
94
+ end
319
95
 
320
- def validate_sources
321
- validators_map = {"mooforge" => Jsus::Util::Validator::Mooforge}
322
- (options[:validators] || []).each do |validator_name|
323
- if validator = validators_map[validator_name]
324
- errors = validator.new(@pool.sources.to_a & @package.source_files.to_a).validation_errors
325
- unless errors.empty?
326
- puts "Validator #{validator_name} found errors: "
327
- errors.each {|e| puts " * #{e}"}
328
- end
329
- else
330
- puts "No such validator: #{validator_name}"
331
- end
332
- end
333
- checkpoint(:validators)
334
- end
96
+ opts.on_tail('--without-scripts-info', 'do not generate scripts.json') do
97
+ options[:without_scripts_info] = true
98
+ end
335
99
 
336
- def output_benchmarks
337
- if options[:benchmark]
338
- puts "Benchmarking results:"
339
- puts "Total execution time: #{formatted_time_for(:all)}"
340
- puts ""
341
- puts "Of them:"
342
- puts "Pool preloading time: #{formatted_time_for(:pool)}"
343
- puts "Docs generation time: #{formatted_time_for(:documentation)}" if options[:documented_classes] && !options[:documented_classes].empty?
344
- puts "Total compilation time: #{formatted_time_for(:compilation)}"
345
- puts "Post-processing time: #{formatted_time_for(:postproc)}" if options[:postproc]
346
- puts "Compression time: #{formatted_time_for(:compress)}" if options[:compress]
347
- puts ""
348
- puts "Compression ratio: #{sprintf("%.2f%%", @compression_ratio * 100)}" if Jsus.verbose? && @compression_ratio
349
- end
350
- end
100
+ opts.on_tail('--without-tree-info', 'do not generate tree.json') do
101
+ options[:without_tree_info] = true
102
+ end
351
103
 
352
- def checkpoint(checkpoint_name)
353
- @checkpoints ||= {}
354
- @time_for ||= {}
355
- @checkpoints[checkpoint_name] = Time.now
356
- if @last_checkpoint
357
- @time_for[checkpoint_name] = @checkpoints[checkpoint_name] - @last_checkpoint
358
- end
359
- @last_checkpoint = Time.now
360
- end
104
+ opts.on_tail('--watch', 'watch file system events for *.js files in subdirectories and rerun jsus with the same parameters') do
105
+ options[:watch] = true
106
+ end
361
107
 
362
- def checkpoint?(checkpoint_name)
363
- @checkpoints[checkpoint_name]
364
- end
108
+ opts.on_tail('-h', '--help', 'Show this message') do
109
+ puts opts
110
+ exit
111
+ end
112
+ end
113
+ cli.parse!
365
114
 
366
- def time_for(checkpoint_name)
367
- if checkpoint_name == :all
368
- @last_checkpoint - @checkpoints[:start]
369
- else
370
- @time_for[checkpoint_name]
371
- end
372
- end
115
+ options[:input_dir] ||= ARGV[0]
116
+ options[:output_dir] ||= ARGV[1]
373
117
 
374
- def formatted_time_for(checkpoint_name)
375
- "#{format("%.3f", time_for(checkpoint_name))}s"
376
- end
377
- end
118
+ unless options[:input_dir] && options[:output_dir]
119
+ puts cli
120
+ exit
378
121
  end
379
122
 
380
- Jsus::CLI.run!
123
+ options[:input_dir] = File.expand_path(options[:input_dir])
124
+ options[:output_dir] = File.expand_path(options[:output_dir])
125
+
126
+ Jsus::CLI.run!(options)