SVGJS_VERSION = '0.30' # all available modules in the correct loading order MODULES = %w[ svg regex default color array number viewbox bbox rbox element container fx event defs group arrange mask clip gradient use doc shape rect ellipse line poly path plotable image text textpath nested sugar set memory loader ] # how many bytes in a "kilobyte" KILO = 1024 # define default task task :default => :dist # module-aware file task class BuildTask < Rake::FileTask def modules prerequisites.map { |f| File.basename(f, '.js') } end def remove_prerequisites to_remove @prerequisites -= to_remove return self end def needed?() super or modules_mismatch? end def modules_mismatch? previous_modules != modules end def previous_modules first_line =~ / - ([\w,\s]+) - / && $1.split(/\W+/) end def first_line File.open(name, 'r') { |f| f.gets } end end BuildTask.define_task 'dist/svg.js' => MODULES.map {|m| "src/#{ m }.js" } do |task| mkdir_p 'dist', :verbose => false svgjs = '' task.prerequisites.each do |src| # bring in source files one by one, but without copyright info copyright = true File.open(src).each_line do |line| copyright = false if copyright and line !~ %r{^(/|\s*$)} svgjs << " #{ line }" unless copyright end svgjs << "\n\n" end File.open(task.name, 'w') do |file| file.puts "/* svg.js %s - %s - svgjs.com/license */" % [version_string, task.modules.join(' ')] file.puts ';(function() {' file.puts "\n" file.puts svgjs file.puts '}).call(this);' end end file 'dist/svg.min.js' => 'dist/svg.js' do |task| require 'rubygems' begin require 'uglifier' rescue LoadError; fail "Uglifier not available: #{$!}" else File.open(task.name, 'w') do |min| min << Uglifier.new.compile(File.read(task.prerequisites.first)) end end end file 'dist/svg.min.gz' => 'dist/svg.min.js' do |task| verbose false do tmp_file = task.name.sub('.gz', '') cp task.prerequisites.first, tmp_file sh 'gzip', '--best', tmp_file end end desc "Concatenate source files to build svg.js" task :concat, [:modules] do |task, args| modules = args[:modules].to_s.split(':') toattrsdd, to_exclude = modules.partition {|m| m.sub!(/^(-)?(.+)/, 'src/\2.js'); !$1 } Rake::Task['dist/svg.js']. remove_prerequisites(to_exclude).enhance(toattrsdd). invoke end desc "Generate svg.js distribution files and report size statistics" task :dist => ['dist/svg.js', 'dist/svg.min.js', 'dist/svg.min.gz'] do |task| orig_size, min_size, gz_size = task.prerequisites.map {|f| File.size(f) } puts "Original version: %.3fk" % (orig_size.to_f / KILO) puts "Minified: %.3fk" % (min_size.to_f / KILO) puts "Minified and gzipped: %.3fk, compression factor %.3f" % [gz_size.to_f / KILO, orig_size.to_f / gz_size] rm_f 'dist/svg.min.gz', :verbose => false end desc "List available modules" task :modules do Dir['src/**/*.js'].each do |file| name = file.gsub(/^src\//,'').gsub(/.js$/,'') puts name + (MODULES.include?(name) ? '*' : '') end puts "\n*included in default build" end task(:clean) { rm_rf 'dist' } desc "Run tests with PhantomJS" task :test do sh 'script/test' Rake::Task[:check_whitespace].invoke end desc "Strip trailing whitespace and ensure each file ends with a newline" task :whitespace do verbose false do files = Dir['{src,test,examples}/**/*.{js,html}'] ruby(*%w'-p -i -e $_.sub!(/\s*\Z/,"\n")'.concat(files)) end end desc "Checks for trailing whitespace in source files and tests" task :check_whitespace do flunked = false flunk = lambda {|file, num| flunked = true; puts "#{file}:#{num}" } Dir['{src,test,examples}/**/*.{js,html}'].each do |file| File.open(file, 'r') {|f| f.each_with_index {|ln, num| flunk.call(file, num + 1) if ln.chomp =~ /\s+$/ } } end fail if flunked end desc "Generate docco documentation from source files" task :docco do verbose false do sh 'docco', *Dir['src/*.js'] end end # svg.js version number + git sha if available def version_string desc = `git describe --tags HEAD 2>&1`.chomp if $?.success? desc else suffix, dir = '', File.basename(Dir.pwd) # detect git sha from directory name of GitHub zip/tarball suffix = "-g#{$1}" if dir =~ /^wout-svg.js-([a-f0-9]{7,40})$/ SVGJS_VERSION + suffix end end