#!/usr/bin/env ruby require 'rubygems' if File.exists?('./lib/jsus.rb') # override with local version of jsus $:.unshift File.expand_path(Dir.pwd) + "/lib" elsif File.exists?(File.expand_path(File.dirname(__FILE__)) + "/../lib/jsus.rb") $:.unshift File.expand_path(File.dirname(__FILE__)) + "/../lib" end require 'jsus' require "fileutils" require "optparse" start_time = Time.now options = {} cli = OptionParser.new do |opts| opts.banner = "jsus #{Jsus.version}. Usage: jsus [options] " opts.on('-i', '--input-directory [DIR]', '[DEPRECATED] path to input directory ') do |dir| $stderr.puts "DEPRECATION NOTICE: please do not use -i command-line argument" options[:input_dir] = dir end opts.on('-o', '--input-directory [DIR]', '[DEPRECATED] path to output directory ') do |dir| $stderr.puts "DEPRECATION NOTICE: please do not use -o command-line argument" options[:output_dir] = dir end opts.on('-d', '--with-dependencies [DEPS]', 'path to directory containing dependency packages') do |dir| options[:deps_dir] = dir end 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| options[:generate_includes] = true options[:includes_root] = dir end opts.on('--generate-docs [*CLASSES]', Array, "generate docs for some of the sources. When given empty array, defaults to /**/*") do |docs| if !docs options[:documented_classes] = ["/**/*"] else options[:documented_classes] = docs end end opts.on('--no-syntax-highlight', 'if you turned on docs generation, it will use syntax highlighting by default. This option prevents it') do options[:no_syntax_highlight] = true end opts.on('--validate-with [*VALIDATORS]', Array, 'performs a check against some of the validators. Available validators: mooforge') do |validators| options[:validators] = (validators || []).map {|v| v.downcase } end 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| options[:postproc] = postprocs end opts.on_tail('-v', '--verbose', 'verbose mode, shows various debug messages') do options[:verbose] = true end opts.on_tail('-b', '--benchmark', 'shows time spent on various stages') do options[:benchmark] = true end opts.on_tail('--without-scripts-info', 'do not generate scripts.json') do options[:without_scripts_info] = true end opts.on_tail('--without-tree-info', 'do not generate tree.json') do options[:without_tree_info] = true end opts.on_tail('-h', '--help', 'Show this message') do puts opts exit end end cli.parse! options[:input_dir] ||= ARGV[0] options[:output_dir] ||= ARGV[1] if !(options[:input_dir] && options[:output_dir]) puts cli exit end compile_start_time = Time.now Jsus.verbose = options[:verbose] pool_load_start_time = Time.now pool = if options[:deps_dir] Jsus::Pool.new(options[:deps_dir]) else Jsus::Pool.new end pool_load_finish_time = Time.now package = Jsus::Package.new(options[:input_dir], :pool => pool) package.include_dependencies! output_dir = options[:output_dir] package_content = package.compile(nil) if options[:postproc] options[:postproc].each do |processor| case processor.strip when /^moocompat12$/i package_content.gsub!(/\/\/<1.2compat>.*?\/\/<\/1.2compat>/m, '') package_content.gsub!(/\/\*<1.2compat>\*\/.*?\/\*<\/1.2compat>\*\//m, '') when /^mooltie8$/i package_content.gsub!(/\/\/.*?\/\/<\/ltIE8>/m, '') package_content.gsub!(/\/\*\*\/.*?\/\*<\/ltIE8>\*\//m, '') else $stderr.puts "Unknown post-processor: #{processor}" end end end FileUtils.mkdir_p(output_dir) package_filename = File.join(output_dir, package.filename) File.open(package_filename, 'w') {|f| f << package_content } package.generate_scripts_info(output_dir) unless options[:without_scripts_info] package.generate_tree(output_dir) unless options[:without_tree_info] # Validations validators_map = {"mooforge" => Jsus::Validator::Mooforge} (options[:validators] || []).each do |validator_name| if validator = validators_map[validator_name] errors = validator.new(pool.sources.to_a & package.source_files.to_a).validation_errors unless errors.empty? puts "Validator #{validator_name} found errors: " errors.each {|e| puts " * #{e}"} end else puts "No such validator: #{validator_name}" end end # Postprocs, sort of hack # Hack, hack, hack >:E if options[:generate_includes] includes_root = options[:includes_root] || output_dir File.open(File.join(output_dir, "includes.js"), "w") do |f| c = Jsus::Container.new(*(package.source_files.to_a + package.linked_external_dependencies.to_a)) script = %{ (function(prefix, loader) { var sources = %sources%; if (!loader) loader = function(path) { document.write(''); } for (var i = 0, j = sources.length; i < j; i++) loader(sources[i]); })(window.prefix, window.loader);}.sub("%sources%", JSON.pretty_generate(c.required_files(includes_root))) f.puts script end end docs_start_time = Time.now # Generate documentation if options[:documented_classes] && !options[:documented_classes].empty? documenter = Jsus::Documenter.new(:highlight_source => !options[:no_syntax_highlight]) package.source_files.each {|source| documenter << source } pool.sources.each {|source| documenter << source } if pool documenter.only(options[:documented_classes]).generate(output_dir + "/docs") end docs_finish_time = Time.now finish_time = Time.now if options[:benchmark] puts "Benchmarking results:" puts "Total execution time: #{format("%.3f" ,finish_time - start_time)}s" puts "" puts "Of them:" puts "Pool preloading time: #{format("%.3f", pool_load_finish_time - pool_load_start_time)}s" puts "Docs generation time: #{format("%.3f", docs_finish_time - docs_start_time)}s" if options[:documented_classes] puts "Total compilation time: #{format("%.3f", finish_time - compile_start_time - (pool_load_finish_time - pool_load_start_time))}s" end