summaryrefslogtreecommitdiffstats
path: root/Rakefile
blob: dae3710f147b1dd22a4103be989e1c512de720db (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
SVGJS_VERSION = '0.24'

# all available modules in the correct loading order
MODULES = %w[ svg regex default color 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 nested sugar set ]

# 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