jake 1.0.1 → 1.1.0

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.
@@ -1,3 +1,8 @@
1
+ === 1.1.0 / 2012-04-07
2
+
3
+ * Add support for source maps from Packr 3.2
4
+
5
+
1
6
  === 1.0.0 / 2009-07-06
2
7
 
3
8
  * A proper test suite is now in place.
@@ -0,0 +1,273 @@
1
+ = Jake
2
+
3
+ Jake is a command-line line tool for building JavaScript packages from source
4
+ code. It's basically a thin wrapper around {Packr}[http://rubygems.org/gems/packr]
5
+ that lets you easily configure builds for multiple packages with different
6
+ compression settings, using a simple YAML config file.
7
+
8
+ It supports all the same compression settings as Packr, including generation of
9
+ {source maps}[http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/]
10
+ for your package files. You can also use ERB in your source files to generate
11
+ code.
12
+
13
+
14
+ == Usage
15
+
16
+ To begin with, create a file called <tt>jake.yml</tt> in the root directory of
17
+ your project; you will run the +jake+ command from here. A basic config looks
18
+ like this:
19
+
20
+ ---
21
+ source_directory: source
22
+ build_directory: build
23
+
24
+ layout: together
25
+
26
+ header: COPYRIGHT
27
+
28
+ builds:
29
+ src:
30
+ minify: false
31
+ min:
32
+ shrink_vars: true
33
+ private: true
34
+
35
+ packages:
36
+ [ DESCRIBED BELOW ]
37
+
38
+ * +source_directory+ is the directory relative to <tt>jake.yml</tt> where your
39
+ source files are, and +build_directory+ is where all the generated build files
40
+ will be placed.
41
+ * +layout+ describes whether files from separate builds should go in separate
42
+ directories. For example if you have a package called +foo+, with the above
43
+ config the +together+ layout will generate <tt>build/foo-src.js</tt> and
44
+ <tt>build/foo-min.js</tt>, whereas a +layout+ value of +apart+ will generate
45
+ <tt>build/src/foo.js</tt> and <tt>build/min/foo.js</tt>.
46
+ * +header+ specifies a file whose content should appear at the top of all
47
+ generated build files. The content of this file will typically be JavaScript
48
+ comments containing copyright and license information. This content is never
49
+ minified. The +header+ option may be omitted.
50
+
51
+
52
+ === Build listing
53
+
54
+ The build listing, given by the +builds+ option in the config file, lists all
55
+ the builds you want to produce for distribution, and what minification settings
56
+ each build should use. JavaScript projects typically distribute both compressed
57
+ and uncompressed copies of their code to suit both production and development
58
+ environments.
59
+
60
+ You can have as many builds as you like and the names are up to you. I'm using
61
+ +src+ and +min+ as readily understood examples. Each build may specify some
62
+ combination of the following options:
63
+
64
+ * <tt>minify: false</tt> -- Disables minification for this build. This precludes
65
+ use of further minification options.
66
+ * <tt>shrink_vars: true</tt> -- Tells the minifier to compress local variable
67
+ names inside functions.
68
+ * <tt>private: true</tt> -- Tells the minifier to obfuscate 'private' variables
69
+ with numeric replacements. JavaScript convention is that any name beginning
70
+ with an underscore, e.g. <tt>_foo</tt> or <tt>obj._bar</tt> should be
71
+ considered private. They are replaced with <tt>_0</tt>, <tt>_1</tt>, etc.
72
+ * <tt>base62: true</tt> -- Produces base-62 encoded minification.
73
+ * <tt>suffix: false</tt> -- Files from this build should not have a suffix if
74
+ using the +together+ layout, so you get <tt>build/foo.js</tt> rather than
75
+ <tt>build/foo-src.js</tt>, for example. Only one build may use this option,
76
+ otherwise file name clashes will occur.
77
+ * <tt>source_map: $build_name</tt> -- Generates a source map for each file in
78
+ this build, relative to a corresponding file in <tt>$build_name</tt>. For
79
+ example, a <tt>min</tt> build with <tt>source_map: src</tt> will produce a
80
+ files <tt>foo-min.js</tt> and <tt>foo-min.js.map</tt> where the source map
81
+ refers to locations in <tt>foo-src</tt>. You can make the source map relative
82
+ to the original source code by setting <tt>:source</tt> as the value of
83
+ <tt>$build_name</tt>.
84
+
85
+
86
+ === Package listing
87
+
88
+ The package listing, given under the +packages+ config option, describes the
89
+ packages you want to produce and which source files are used to generate them. A
90
+ package is named using the path under +build_directory+ where it should be
91
+ generated, e.g. <tt>foo</tt> or <tt>ext/awesome</tt> (you may omit the
92
+ <tt>.js</tt> extension). Each package lists one or more source files used to
93
+ build it, and may optionally list some extra options as described below.
94
+
95
+ For the examples, assume the source directory is +src+ and the build directory
96
+ is +dist+. This package uses a single source file <tt>src/foo.js</tt> and
97
+ generates <tt>dist/foo_dist.js</tt>:
98
+
99
+ foo_dist: foo
100
+
101
+ This package generates <tt>dist/bar.js</tt> from <tt>src/bar1.js</tt> and
102
+ <tt>src/bar2.js</tt>
103
+
104
+ bar:
105
+ - bar1
106
+ - bar2
107
+
108
+ This generates a package at <tt>dist/sub/dir.js</tt> from <tt>src/path/file.js</tt>
109
+ and <tt>src/path/baz.js</tt>:
110
+
111
+ sub/dir:
112
+ - path/file
113
+ - path/baz
114
+
115
+ If all the source files for a package live in the same subdirectory, you can
116
+ tidy things up using the +directory+ option. If you use any package-level
117
+ options, you must list the files under the +files+ option (the above examples
118
+ are just syntactic shorthands for this):
119
+
120
+ sub/dir:
121
+ directory: path
122
+ files:
123
+ - file
124
+ - baz
125
+
126
+ The full list of package options is as follows:
127
+
128
+ * +files+ - lists the source files used to build the package. Shorthand may be
129
+ used as above if no further options are used.
130
+ * +extends+ - name of another package from which to inherit configuration.
131
+ Useful for making a package that includes all the files from another, plus a
132
+ few extras.
133
+ * +directory+ - the directory under +source_directory+ in which to find source
134
+ files. May be omitted.
135
+ * +header+ - a custom header file to use on this package. Overrides the root
136
+ +header+ option. May be omitted.
137
+ * +packer+ - lists minification settings that override settings being used for
138
+ the current build. If a build listed above uses <tt>minify: false</tt>, this
139
+ takes precedence over package-specific instructions. Typically used to
140
+ override options for the minified build.
141
+ * +meta+ - should be a YAML dictionary containing arbitrary data useful to
142
+ user-defined build events. May be omitted. See 'Event hooks' below.
143
+
144
+ For example, here's a package listing that uses all the options:
145
+
146
+ packages:
147
+ foo_dist: foo
148
+
149
+ bar:
150
+ - bar1
151
+ - bar2
152
+
153
+ sub/whizz:
154
+ extends: foo_dist
155
+ directory: path
156
+ header: CUSTOM_HEADER
157
+ files:
158
+ - file1
159
+ - file2
160
+
161
+ last:
162
+ packer:
163
+ private: false
164
+ meta:
165
+ requires:
166
+ - jQuery
167
+ - GMap2
168
+ files:
169
+ - one_file
170
+ - another_file
171
+
172
+ In conjunction with the build options listed above, this matches the following
173
+ project layout (omitting build name suffixes for brevity):
174
+
175
+ - build/
176
+ - sub/
177
+ - whizz.js
178
+ - bar.js
179
+ - foo_dist.js
180
+ - last.js
181
+ - source/
182
+ - path/
183
+ - CUSTOM_HEADER
184
+ - file1.js
185
+ - file2.js
186
+ - another_file.js
187
+ - bar1.js
188
+ - bar2.js
189
+ - foo.js
190
+ - one_file.js
191
+ - COPYRIGHT
192
+ - jake.yml
193
+
194
+
195
+ === Using ERB in source files
196
+
197
+ Jake lets you use Ruby's ERB templating system within your source code so you
198
+ can insert values generated from Ruby functions. To use this feature, you need
199
+ to create a file called <tt>Jakefile</tt> in the root of your project. This
200
+ contains helper functions that are called in your source code to inject data.
201
+
202
+ For example, say you want to extract a version number from your version control
203
+ system and inject it into your code along with the build name. Your source code
204
+ should contain something like this:
205
+
206
+ MyJavaScriptLib.VERSION = "<%= version %>-<%= build %>";
207
+
208
+ And your <tt>Jakefile</tt> should contain a helper called +version+:
209
+
210
+ jake_helper :version do
211
+ # extract version number from svn, git, whatever
212
+ # e.g. return '1.0'
213
+ end
214
+
215
+ Jake has a built-in helper called +build+ that returns the current build name.
216
+ When built, the output would contain the following:
217
+
218
+ MyJavaScriptLib.VERSION = "1.0-src"; // or "1.0-min" for the 'min' build
219
+
220
+
221
+ === Event hooks
222
+
223
+ The +Jakefile+ may also define event hooks that are fired during a build when
224
+ interesting things happen. This allows you to extend your build process using
225
+ configuration data from Jake. All event callbacks are passed a +Build+ object as
226
+ the first argument, and may receive additional arguments depending on the
227
+ event type. We currently have two events:
228
+
229
+ +file_created+ is fired whenever a new build file is created. The callback is
230
+ passed the +Buildable+ package object, the current build type (+src+ or +min+
231
+ using the above examples), and the full path to the newly created file. The
232
+ package object may contain metadata (set using the +meta+ option, see above)
233
+ which you can use for further code generation.
234
+
235
+ +build_complete+ is fired after a build has finished running, that is after all
236
+ sets of minification options have been run. At this point you can use any
237
+ metadata you've gathered to generate more code, copy files to your distribution
238
+ directory, etc.
239
+
240
+ $register = {}
241
+
242
+ jake_hook :file_created do |build, pkg, build_type, path|
243
+ $register[path] = pkg.meta
244
+ end
245
+
246
+ jake_hook :build_complete do |build|
247
+ FileUtils.cp 'README', build.build_directory + '/README'
248
+ # generate code from $register
249
+ end
250
+
251
+
252
+ == License
253
+
254
+ (The MIT License)
255
+
256
+ Copyright (c) 2008-2012 James Coglan
257
+
258
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
259
+ this software and associated documentation files (the 'Software'), to deal in
260
+ the Software without restriction, including without limitation the rights to
261
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
262
+ the Software, and to permit persons to whom the Software is furnished to do so,
263
+ subject to the following conditions:
264
+
265
+ The above copyright notice and this permission notice shall be included in all
266
+ copies or substantial portions of the Software.
267
+
268
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
269
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
270
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
271
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
272
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
273
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/bin/jake CHANGED
@@ -1,7 +1,10 @@
1
- #!/usr/bin/ruby
1
+ #!/usr/bin/env ruby
2
+
3
+ $VERBOSE = nil
4
+
2
5
  require 'rubygems'
3
6
  require 'oyster'
4
- require File.dirname(__FILE__) + '/../lib/jake'
7
+ require File.expand_path('../../lib/jake', __FILE__)
5
8
 
6
9
  spec = Oyster.spec do
7
10
  name 'jake -- automated build tool for JavaScript projects'
@@ -11,7 +14,7 @@ spec = Oyster.spec do
11
14
  EOS
12
15
 
13
16
  description <<-EOS
14
- Jake builds JavaScript library packages from source code using PackR and
17
+ Jake builds JavaScript library packages from source code using Packr and
15
18
  ERB. Use --force to force a rebuild of files deemed up-to-date. DIR specifies
16
19
  where to find the jake.yml configuration file, by default this is set to the
17
20
  current working directory.
@@ -20,7 +23,7 @@ spec = Oyster.spec do
20
23
  flag :force, :default => false,
21
24
  :desc => 'Force a rebuild even if files are up-to-date'
22
25
 
23
- author 'James Coglan <jcoglan@googlemail.com>'
26
+ author 'James Coglan <jcoglan@gmail.com>'
24
27
  end
25
28
 
26
29
  begin; opts = spec.parse
@@ -34,11 +37,11 @@ build = Jake::Build.new(dir, opts)
34
37
 
35
38
  build.on(:file_created) do |build, pkg, build_type, path|
36
39
  size = (File.size(path) / 1024.0).ceil
37
- puts LOG_FORMAT % [pkg.name, build_type, path.gsub(dir, ''), "#{ size } kB"]
40
+ puts LOG_FORMAT % [pkg.name, build_type, path.gsub(dir + '/', ''), "#{ size } kB"]
38
41
  end
39
42
 
40
43
  build.on(:file_not_changed) do |build, pkg, build_type, path|
41
- puts LOG_FORMAT % [pkg.name, build_type, path.gsub(dir, ''), 'UP-TO-DATE']
44
+ puts LOG_FORMAT % [pkg.name, build_type, path.gsub(dir + '/', ''), '--']
42
45
  end
43
46
 
44
47
  build.run!
@@ -1,8 +1,6 @@
1
1
  require 'erb'
2
2
  require 'fileutils'
3
- require 'observer'
4
3
  require 'yaml'
5
- require 'rubygems'
6
4
  require 'packr'
7
5
  require 'eventful'
8
6
 
@@ -12,41 +10,41 @@ rescue LoadError
12
10
  end
13
11
 
14
12
  module Jake
15
- VERSION = '1.0.1'
13
+ VERSION = '1.1.0'
16
14
 
17
15
  CONFIG_FILE = 'jake.yml'
18
16
  HELPER_FILE = 'Jakefile'
19
17
  EXTENSION = '.js'
20
18
 
21
- # Runs a build in the given directory. The directory must contain a jake.yml
22
- # file, and may contain a Jakefile. See README for example YAML configurations.
19
+ dir = File.expand_path('../jake', __FILE__)
20
+ autoload :Build, dir + '/build'
21
+ autoload :Buildable, dir + '/buildable'
22
+ autoload :Bundle, dir + '/bundle'
23
+ autoload :Helper, dir + '/helper'
24
+ autoload :Package, dir + '/package'
25
+
23
26
  def self.build!(path, options = {})
24
27
  build = Build.new(path, options)
25
28
  build.run!
26
29
  end
27
30
 
28
- # Removes all registered build event hooks.
29
31
  def self.clear_hooks!
30
32
  Build.delete_observers
31
33
  end
32
34
 
33
- # Returns a path made by joining the given pieces and removing unnecessary
34
- # /. sections using expand_path.
35
35
  def self.path(*parts)
36
36
  parts = parts.compact.map { |p| p.to_s }
37
37
  File.expand_path(File.join(*parts))
38
38
  end
39
39
 
40
- # Returns the contents of the given path, which may be missing a .js extension.
41
40
  def self.read(path)
42
41
  path = File.expand_path(path)
43
- [path, "#{path}#{EXTENSION}"].each do |p|
44
- return File.read(p).strip if File.file?(p)
42
+ [path, "#{path}#{EXTENSION}"].each do |file|
43
+ return File.read(file) if File.file?(file)
45
44
  end
46
45
  return nil
47
46
  end
48
47
 
49
- # Returns a copy of the given hash with the keys cast to symbols.
50
48
  def self.symbolize_hash(hash, deep = true)
51
49
  hash.inject({}) do |output, (key, value)|
52
50
  value = Jake.symbolize_hash(value) if deep and value.is_a?(Hash)
@@ -55,18 +53,11 @@ module Jake
55
53
  end
56
54
  end
57
55
 
58
- # Returns either an Erubis or ERB instance, depending on what's available.
59
56
  def self.erb(template)
60
57
  defined?(Erubis) ? Erubis::Eruby.new(template) : ERB.new(template)
61
58
  end
62
-
63
- end
64
-
65
- %w(helper build buildable package bundle).each do |file|
66
- require File.dirname(__FILE__) + '/jake/' + file
67
59
  end
68
60
 
69
- # Adds a helper method that can be called from ERB.
70
61
  def jake_helper(name, &block)
71
62
  Jake::Helper.class_eval do
72
63
  define_method(name, &block)
@@ -74,7 +65,6 @@ def jake_helper(name, &block)
74
65
  end
75
66
  alias :jake :jake_helper
76
67
 
77
- # Registers an event listener that will fire whenever a build is run.
78
68
  def jake_hook(type, &block)
79
69
  Jake::Build.on(type, &block)
80
70
  end
@@ -1,18 +1,11 @@
1
1
  module Jake
2
- # A +Build+ encapsulates a single instance of running <tt>Jake.build!</tt>. It
3
- # is responsible for running the build and provides access to any configuration
4
- # data used to set up the build.
5
2
  class Build
6
3
  include Eventful
4
+ include Enumerable
5
+ attr_reader :config_files, :helper
7
6
 
8
7
  DEFAULT_LAYOUT = 'together'
9
8
 
10
- include Enumerable
11
- attr_reader :helper
12
-
13
- # Builds are initialized using a directory in which to run the build, and an
14
- # options hash. Options are passed through to helper methods in the +options+
15
- # object.
16
9
  def initialize(dir, options = {})
17
10
  @dir = File.expand_path(dir)
18
11
  @helper = Helper.new(options)
@@ -21,10 +14,14 @@ module Jake
21
14
  path = Jake.path(dir, CONFIG_FILE)
22
15
  yaml = File.read(path)
23
16
 
17
+ @config_files = [path]
24
18
  @config = Jake.symbolize_hash( YAML.load(Jake.erb(yaml).result(@helper.scope)) )
25
19
 
26
20
  helpers = Jake.path(dir, HELPER_FILE)
27
- load helpers if File.file?(helpers)
21
+ if File.file?(helpers)
22
+ load helpers
23
+ @config_files << helpers
24
+ end
28
25
 
29
26
  @builds = @config[:builds] || {:src => false, :min => @config[:packer]}
30
27
 
@@ -39,22 +36,18 @@ module Jake
39
36
  end
40
37
  end
41
38
 
42
- # Yields to the block for each build in the group.
43
39
  def each(&block)
44
40
  @builds.each(&block)
45
41
  end
46
42
 
47
- # Forces the build to generate new files even if target files appear up-to-date.
48
43
  def force!
49
44
  @forced = true
50
45
  end
51
46
 
52
- # Returns +true+ iff this is a forced build.
53
47
  def forced?
54
48
  defined?(@forced)
55
49
  end
56
50
 
57
- # Returns a list of names for all packages in the build.
58
51
  def packages
59
52
  list = []
60
53
  @packages.each { |name, pkg| list << name }
@@ -62,12 +55,10 @@ module Jake
62
55
  list
63
56
  end
64
57
 
65
- # Returns the +Buildable+ with the given name.
66
58
  def package(name)
67
59
  @packages[name.to_sym] || @bundles[name.to_sym]
68
60
  end
69
61
 
70
- # Runs the build, generating new files in +build_directory+.
71
62
  def run!
72
63
  FileUtils.cd(@dir) do
73
64
  @packages.each { |name, pkg| pkg.write! }
@@ -76,44 +67,34 @@ module Jake
76
67
  end
77
68
  end
78
69
 
79
- # Returns the path to the build directory, where generated files appear.
80
70
  def build_directory
81
71
  Jake.path(@dir, @config[:build_directory] || '.')
82
72
  end
83
73
  alias :build_dir :build_directory
84
74
 
85
- # Returns the path to the source directory, where source code is read from.
86
75
  def source_directory
87
76
  Jake.path(@dir, @config[:source_directory] || '.')
88
77
  end
89
78
  alias :source_dir :source_directory
90
79
 
91
- # Returns the header string used for the build, or an empty string if no
92
- # header file has been set.
93
80
  def header
94
81
  @config[:header] ?
95
82
  Jake.read(Jake.path(source_directory, @config[:header])) :
96
83
  ""
97
84
  end
98
85
 
99
- # Returns the minification settings for PackR for the given build name. Each
100
- # +Build+ object can build all its packages multiple times with different
101
- # minification settings in each run.
102
86
  def packer_settings(build_name)
103
87
  build = @builds[build_name.to_sym]
104
88
  return false unless build
105
89
  build[:packer].nil? ? build : build[:packer]
106
90
  end
107
91
 
108
- # Returns +true+ iff filename suffixes based on build name should be added
109
- # to generated files for the given build name.
110
92
  def use_suffix?(build_name)
111
93
  build = @builds[build_name.to_sym]
112
94
  return true unless build
113
95
  build[:suffix] != false
114
96
  end
115
97
 
116
- # Returns the name of the layout being used, either +together+ or +apart+.
117
98
  def layout
118
99
  @config[:layout] || DEFAULT_LAYOUT
119
100
  end