jsus 0.3.4 → 0.3.5

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 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)