jake 0.9.3 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,6 +1,44 @@
1
- === 1.0.0 / 2008-07-04
1
+ === 1.0.0 / 2009-07-06
2
2
 
3
- * 1 major enhancement
3
+ * A proper test suite is now in place.
4
4
 
5
- * Birthday!
5
+ * Helper methods and event hooks and are now separated. Use `jake_helper`
6
+ and `jake_hook` instead of just `jake`.
7
+
8
+ * :after_build event is now called :build_complete, and we added
9
+ a :file_created event that is called whenever a new package file is
10
+ written to disk.
11
+
12
+ * Metadata can be added to packages using the :meta option. This
13
+ data is available as Package#meta inside event hooks.
14
+
15
+ * Erubis is now used instead of ERB if available.
16
+
17
+
18
+ === 0.9.3 / 2009-05-10
19
+
20
+ * Adds an 'extends' option to packages to allow one package to
21
+ inherit config from another. Useful for making packages that include
22
+ all the files from another, plus a few extras.
23
+
24
+ * Helper methods have access to commandline input via `options`.
25
+
26
+
27
+ === 0.9.2 / 2008-11-14
28
+
29
+ * Allows '-min' suffixes to be omitted.
30
+
31
+ * Supports use of ERB in the jake.yml file to generate configs.
32
+
33
+
34
+ === 0.9.1 / 2008-09-11
35
+
36
+ * Adds ERB support to header files.
37
+
38
+
39
+ === 0.9.0 / 2008-09-11
40
+
41
+ * First release, supports packages, bundles, ERB code generation.
42
+
43
+ * Supports :after_build event hook for post-build tasks.
6
44
 
@@ -4,8 +4,30 @@ README.txt
4
4
  Rakefile
5
5
  bin/jake
6
6
  lib/jake.rb
7
+ lib/jake/helper.rb
7
8
  lib/jake/build.rb
8
9
  lib/jake/buildable.rb
9
10
  lib/jake/package.rb
10
11
  lib/jake/bundle.rb
11
12
  test/test_jake.rb
13
+ test/jake.yml
14
+ test/Jakefile
15
+ test/packages.erb
16
+ test/expected/combo/box.js
17
+ test/expected/combo/box-min.js
18
+ test/expected/sub/dir/foo.js
19
+ test/expected/sub/dir/foo-min.js
20
+ test/expected/sub/path/bar.js
21
+ test/expected/sub/path/bar-min.js
22
+ test/expected/basic.js
23
+ test/expected/basic-min.js
24
+ test/expected/ext.js
25
+ test/expected/ext-min.js
26
+ test/expected/LISTING
27
+ test/expected/README
28
+ test/src/foo/bar.js
29
+ test/src/foo/foo.js
30
+ test/src/basic.js
31
+ test/src/basic-ext.js
32
+ test/src/head.js
33
+ test/src/head2.js
data/README.txt CHANGED
@@ -2,97 +2,267 @@
2
2
 
3
3
  * http://github.com/jcoglan/jake
4
4
 
5
- == Description
5
+ Jake is a command line tool for building JavaScript packages from source
6
+ code. Using simple YAML config files, you can specify any number of build
7
+ files to be generated by concatenating and minifying groups of source files.
8
+ It allows ERB to be used inside source files to generate code, and provides
9
+ event hooks into the build process so you can extend it for your own needs.
6
10
 
7
- Jake is a tool for building JavaScript library packages from source code. It allows
8
- builds to be specified using simple YAML files, and provides a command-line tool for
9
- generating package files. It also allows ERB to be embedded in JavaScript source code
10
- so that build data or new code can be generated during the build process.
11
11
 
12
12
  == Features
13
13
 
14
- * Easy automated builds of JavaScript packages with a single command
15
- * Uses lightweight YAML to specify files and compression options
16
- * Compression is configurable both globally and per-package
17
- * Multiple builds with different compression setups
18
- * Headers such as copyright information can be injected into all build files
19
- * ERB can be used to inject code at build time using Ruby functions
14
+ * Concatenate and minify groups of source files for distribution
15
+ * Configured using simple YAML files
16
+ * Easily generate multiple distros with different compression settings
17
+ * Use ERB templating to generate source code
18
+ * Extensible using Ruby/ERB and event hooks during the build process
19
+ * Tested on Ruby 1.8.6, 1.8.7, 1.9.1
20
20
 
21
- == Usage
22
21
 
23
- Jake builds are configured using a YAML file and (optionally) a 'Jakefile' containing
24
- helper methods for use with Jake's ERB features. You place a file called <tt>jake.yml</tt>
25
- in the root directory of your project (you will run the +jake+ command from this
26
- directory). If you use a Jakefile, place this in the same directory.
22
+ == Installation
23
+
24
+ sudo gem install jake
27
25
 
28
- This example <tt>jake.yml</tt> demonstrates the layout of the file:
29
26
 
30
- --
31
- source_directory: src
32
- build_directory: dist
27
+ == Usage
28
+
29
+ To begin with, create a file called <tt>jake.yml</tt> in the root directory
30
+ of your project; you will run the +jake+ command from here. A basic config
31
+ looks like this:
32
+
33
+ ---
34
+ source_directory: source
35
+ build_directory: build
36
+
37
+ layout: together
38
+
33
39
  header: COPYRIGHT
34
- packer:
35
- shrink_vars: true
36
- private: true
37
- base62: true
40
+
41
+ builds:
42
+ src:
43
+ packer: false
44
+ min:
45
+ shrink_vars: true
46
+ private: true
38
47
 
39
48
  packages:
40
- foo: foo
49
+ [ DESCRIBED BELOW ]
50
+
51
+ * +source_directory+ is the directory relative to <tt>jake.yml</tt> where
52
+ your source files are, and +build_directory+ is where all the generated
53
+ build files will be placed.
54
+ * +layout+ describes whether files from separate builds should go in
55
+ separate directories. For example if you have a package called +foo+,
56
+ with the above config the +together+ layout will generate
57
+ <tt>build/foo-src.js</tt> and <tt>build/foo-min.js</tt>, whereas a
58
+ +layout+ value of +apart+ will generate <tt>build/src/foo.js</tt> and
59
+ <tt>build/min/foo.js</tt>.
60
+ * +header+ specifies a file whose content should appear at the top of
61
+ all generated build files. The content of this file will typically be
62
+ JavaScript comments containing copyright and license information. This
63
+ content is never minified. The +header+ option may be omitted.
64
+
65
+
66
+ === Build listing
67
+
68
+ The build listing, given by the +builds+ option in the config file, lists
69
+ all the builds you want to produce for distribution, and what minification
70
+ settings each build should use. JavaScript projects typically distribute
71
+ both compressed and uncompressed copies of their code to suit both production
72
+ and development environments.
73
+
74
+ You can have as many builds as you like and the names are up to you. I'm
75
+ using +src+ and +min+ as readily understood examples. Each build may specify
76
+ some combination of the following options:
77
+
78
+ * <tt>packer: false</tt> - disables minification for this build. This
79
+ precludes use of further minification options.
80
+ * <tt>shrink_vars: true</tt> - tells the minifier to compress local
81
+ variable names inside functions.
82
+ * <tt>private: true</tt> - tells the minifier to obfuscate 'private'
83
+ variables with numeric replacements. JavaScript convention is that any
84
+ name beginning with an underscore, e.g. <tt>_foo</tt> or <tt>obj._bar</tt>
85
+ should be considered private. They are replaced with <tt>_0</tt>,
86
+ <tt>_1</tt>, etc.
87
+ * <tt>base62: true</tt> - produces base-62 encoded minification.
88
+ * <tt>suffix: false</tt> - files from this build should not have a
89
+ suffix if using the +together+ layout, so you get <tt>build/foo.js</tt>
90
+ rather than <tt>build/foo-src.js</tt>, for example. Only one build
91
+ may use this option, otherwise file name clashes will occur.
92
+
93
+
94
+ === Package listing
95
+
96
+ The package listing, given under the +packages+ config option, describes
97
+ the packages you want to produce and which source files are used to generate
98
+ them. A package is named using the path under +build_directory+ where it
99
+ should be generated, e.g. <tt>foo</tt> or <tt>ext/awesome</tt> (you may
100
+ omit the <tt>.js</tt> extension). Each package lists one or more source
101
+ files used to build it, and may optionally list some extra options as described
102
+ below.
103
+
104
+ For the examples, assume the source directory is +src+ and the build
105
+ directory is +dist+. This package uses a single source file <tt>src/foo.js</tt>
106
+ and generates <tt>dist/foo_dist.js</tt>:
107
+
108
+ foo_dist: foo
109
+
110
+ This package generates <tt>dist/bar.js</tt> from <tt>src/bar1.js</tt> and
111
+ <tt>src/bar2.js</tt>
112
+
113
+ bar:
114
+ - bar1
115
+ - bar2
116
+
117
+ This generates a package at <tt>dist/sub/dir.js</tt> from <tt>src/path/file.js</tt>
118
+ and <tt>src/path/baz.js</tt>:
119
+
120
+ sub/dir:
121
+ - path/file
122
+ - path/baz
123
+
124
+ If all the source files for a package live in the same subdirectory, you
125
+ can tidy things up using the +directory+ option. If you use any package-level
126
+ options, you must list the files under the +files+ option (the above examples
127
+ are just syntactic shorthands for this):
128
+
129
+ sub/dir:
130
+ directory: path
131
+ files:
132
+ - file
133
+ - baz
134
+
135
+ The full list of package options is as follows:
136
+
137
+ * +files+ - lists the source files used to build the package. Shorthand may
138
+ be used as above if no further options are used.
139
+ * +extends+ - name of another package from which to inherit configuration.
140
+ Useful for making a package that includes all the files from another,]
141
+ plus a few extras.
142
+ * +directory+ - the directory under +source_directory+ in which to find
143
+ source files. May be omitted.
144
+ * +header+ - a custom header file to use on this package. Overrides the
145
+ root +header+ option. May be omitted.
146
+ * +packer+ - lists minification settings that override settings being used
147
+ for the current build. If a build listed above uses <tt>packer: false</tt>,
148
+ this takes precedence over package-specific instructions. Typically used
149
+ to override options for the minified build.
150
+ * +meta+ - should be a YAML dictionary containing arbitrary data useful to
151
+ user-defined build events. May be omitted. See 'Event hooks' below.
152
+
153
+ For example, here's a package listing that uses all the options:
154
+
155
+ packages:
156
+ foo_dist: foo
41
157
 
42
158
  bar:
43
- - bar_file1
44
- - bar_file2
159
+ - bar1
160
+ - bar2
161
+
162
+ sub/whizz:
163
+ extends: foo_dist
164
+ directory: path
165
+ header: CUSTOM_HEADER
166
+ files:
167
+ - file1
168
+ - file2
45
169
 
46
- baz:
47
- directory: baz
48
- header: COPYRIGHT
170
+ last:
49
171
  packer:
50
- base62: false
172
+ private: false
173
+ meta:
174
+ requires:
175
+ - jQuery
176
+ - GMap2
51
177
  files:
52
- - model
53
- - view
54
- - controller
55
-
56
- bundles:
57
- my_lib:
58
- - foo
59
- - bar
60
- - baz
61
-
62
- This configuration would match a project layed out as follows:
178
+ - one_file
179
+ - another_file
180
+
181
+ In conjunction with the build options listed above, this matches the
182
+ following project layout (omitting build name suffixes for brevity):
63
183
 
64
- - dist/
184
+ - build/
185
+ - sub/
186
+ - whizz.js
65
187
  - bar.js
66
- - baz.js
67
- - foo.js
68
- - my_lib.js
69
- - src/
70
- - baz/
71
- - controller.js
72
- - COPYRIGHT
73
- - model.js
74
- - view.js
75
- - bar_file1.js
76
- - bar_file2.js
188
+ - foo_dist.js
189
+ - last.js
190
+ - source/
191
+ - path/
192
+ - CUSTOM_HEADER
193
+ - file1.js
194
+ - file2.js
195
+ - another_file.js
196
+ - bar1.js
197
+ - bar2.js
77
198
  - foo.js
199
+ - one_file.js
78
200
  - COPYRIGHT
79
201
  - jake.yml
80
202
 
81
- == Requirements
82
203
 
83
- * Rubygems
84
- * Oyster
85
- * PackR
204
+ === Using ERB in source files
86
205
 
87
- == Installation
206
+ Jake lets you use Ruby's ERB templating system within your source code so
207
+ you can insert values generated from Ruby functions. To use this feature,
208
+ you need to create a file called <tt>Jakefile</tt> in the root of your project.
209
+ This contains helper functions that are called in your source code to inject data.
210
+
211
+ For example, say you want to extract a version number from your version control
212
+ system and inject it into your code along with the build name. Your source code
213
+ should contain something like this:
214
+
215
+ MyJavaScriptLib.VERSION = "<%= version %>-<%= build %>";
216
+
217
+ And your <tt>Jakefile</tt> should contain a helper called +version+:
218
+
219
+ jake_helper :version do
220
+ # extract version number from svn, git, whatever
221
+ # e.g. return '1.0'
222
+ end
223
+
224
+ Jake has a built-in helper called +build+ that returns the current build
225
+ name. When built, the output would contain the following:
226
+
227
+ MyJavaScriptLib.VERSION = "1.0-src"; // or "1.0-min" for the 'min' build
228
+
229
+
230
+ === Event hooks
231
+
232
+ The +Jakefile+ may also define event hooks that are fired during a build when
233
+ interesting things happen. This allows you to extend your build process using
234
+ configuration data from Jake. All event callbacks are passed a +Build+ object
235
+ as the first argument, and may receive additional arguments depending on the
236
+ event type. We currently have two events:
237
+
238
+ +file_created+ is fired whenever a new build file is created. The callback is
239
+ passed the +Buildable+ package object, the current build type (+src+ or +min+
240
+ using the above examples), and the full path to the newly created file.
241
+ The package object may contain metadata (set using the +meta+ option, see
242
+ above) which you can use for further code generation.
243
+
244
+ +build_complete+ is fired after a build has finished running, that is after
245
+ all sets of minification options have been run. At this point you can use any
246
+ metadata you've gathered to generate more code, copy files to your distribution
247
+ directory, etc.
248
+
249
+ $register = {}
250
+
251
+ jake_hook :file_created do |build, pkg, build_type, path|
252
+ $register[path] = pkg.meta
253
+ end
254
+
255
+ jake_hook :build_complete do |build|
256
+ FileUtils.cp 'README', build.build_directory + '/README'
257
+ # generate code from $register
258
+ end
88
259
 
89
- * sudo gem install jake -y
90
260
 
91
261
  == License
92
262
 
93
263
  (The MIT License)
94
264
 
95
- Copyright (c) 2008 James Coglan
265
+ Copyright (c) 2008-2009 James Coglan
96
266
 
97
267
  Permission is hereby granted, free of charge, to any person obtaining
98
268
  a copy of this software and associated documentation files (the
data/Rakefile CHANGED
@@ -4,10 +4,10 @@ require 'rubygems'
4
4
  require 'hoe'
5
5
  require './lib/jake.rb'
6
6
 
7
- Hoe.new('jake', Jake::VERSION) do |p|
7
+ Hoe.spec('jake') do |p|
8
8
  # p.rubyforge_name = 'jakex' # if different than lowercase project name
9
9
  p.developer('James Coglan', 'jcoglan@googlemail.com')
10
- p.extra_deps = %w(oyster packr)
10
+ p.extra_deps = %w(eventful packr oyster)
11
11
  end
12
12
 
13
13
  # vim: syntax=Ruby
data/bin/jake CHANGED
@@ -27,5 +27,19 @@ begin; opts = spec.parse
27
27
  rescue Oyster::HelpRendered; exit
28
28
  end
29
29
 
30
- Jake.build(File.expand_path(opts[:unclaimed].first || '.'), opts)
30
+ LOG_FORMAT = "%-020s %-10s %-040s %-07s"
31
+
32
+ dir = File.expand_path(opts[:unclaimed].first || '.')
33
+ build = Jake::Build.new(dir, opts)
34
+
35
+ build.on(:file_created) do |build, pkg, build_type, path|
36
+ size = (File.size(path) / 1024.0).ceil
37
+ puts LOG_FORMAT % [pkg.name, build_type, path.gsub(dir, ''), "#{ size } kB"]
38
+ end
39
+
40
+ 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']
42
+ end
43
+
44
+ build.run!
31
45
 
@@ -1,21 +1,45 @@
1
+ require 'erb'
2
+ require 'fileutils'
3
+ require 'observer'
4
+ require 'yaml'
5
+ require 'rubygems'
6
+ require 'packr'
7
+ require 'eventful'
8
+
9
+ begin
10
+ require 'erubis'
11
+ rescue LoadError
12
+ end
13
+
1
14
  module Jake
2
- VERSION = '0.9.3'
15
+ VERSION = '1.0.0'
3
16
 
4
17
  CONFIG_FILE = 'jake.yml'
5
18
  HELPER_FILE = 'Jakefile'
19
+ EXTENSION = '.js'
6
20
 
7
- def self.build(path, options = {})
8
- build = Build.new(path, nil, options)
9
- build.force! if options[:force]
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.
23
+ def self.build!(path, options = {})
24
+ build = Build.new(path, options)
10
25
  build.run!
11
26
  end
12
27
 
28
+ # Removes all registered build event hooks.
29
+ def self.clear_hooks!
30
+ Build.delete_observers
31
+ end
32
+
33
+ # Returns the contents of the given path, which may be missing a .js extension.
13
34
  def self.read(path)
14
35
  path = File.expand_path(path)
15
- path = File.file?(path) ? path : ( File.file?("#{path}.js") ? "#{path}.js" : nil )
16
- path and File.read(path).strip
36
+ [path, "#{path}#{EXTENSION}"].each do |p|
37
+ return File.read(p).strip if File.file?(p)
38
+ end
39
+ return nil
17
40
  end
18
41
 
42
+ # Returns a copy of the given hash with the keys cast to symbols.
19
43
  def self.symbolize_hash(hash, deep = true)
20
44
  hash.inject({}) do |output, (key, value)|
21
45
  value = Jake.symbolize_hash(value) if deep and value.is_a?(Hash)
@@ -24,27 +48,27 @@ module Jake
24
48
  end
25
49
  end
26
50
 
27
- class Helper
28
- attr_accessor :build
29
- attr_reader :options
30
-
31
- def initialize(options = {})
32
- @options = options
33
- end
34
-
35
- def scope; binding; end
51
+ # Returns either an Erubis or ERB instance, depending on what's available.
52
+ def self.erb(template)
53
+ defined?(Erubis) ? Erubis::Eruby.new(template) : ERB.new(template)
36
54
  end
55
+
37
56
  end
38
57
 
39
- require 'erb'
40
-
41
- %w(build buildable package bundle).each do |file|
58
+ %w(helper build buildable package bundle).each do |file|
42
59
  require File.dirname(__FILE__) + '/jake/' + file
43
60
  end
44
61
 
45
- def jake(name, &block)
62
+ # Adds a helper method that can be called from ERB.
63
+ def jake_helper(name, &block)
46
64
  Jake::Helper.class_eval do
47
65
  define_method(name, &block)
48
66
  end
49
67
  end
50
-
68
+ alias :jake :jake_helper
69
+
70
+ # Registers an event listener that will fire whenever a build is run.
71
+ def jake_hook(type, &block)
72
+ Jake::Build.on(type, &block)
73
+ end
74
+
@@ -1,22 +1,27 @@
1
- require 'yaml'
2
- require 'fileutils'
3
-
4
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
5
  class Build
6
+ include Eventful
6
7
 
7
8
  DEFAULT_LAYOUT = 'together'
8
9
 
9
10
  include Enumerable
10
11
  attr_reader :helper
11
12
 
12
- def initialize(dir, config = nil, options = {})
13
- @dir = File.expand_path(dir)
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
+ def initialize(dir, options = {})
17
+ @dir = File.expand_path(dir)
14
18
  @helper = Helper.new(options)
19
+ force! if options[:force]
15
20
 
16
- path = "#{dir}/#{CONFIG_FILE}"
17
- yaml = File.read(path)
21
+ path = "#{dir}/#{CONFIG_FILE}"
22
+ yaml = File.read(path)
18
23
 
19
- @config = Jake.symbolize_hash( config || YAML.load(ERB.new(yaml).result(@helper.scope)) )
24
+ @config = Jake.symbolize_hash( YAML.load(Jake.erb(yaml).result(@helper.scope)) )
20
25
 
21
26
  helpers = "#{dir}/#{HELPER_FILE}"
22
27
  load helpers if File.file?(helpers)
@@ -34,54 +39,81 @@ module Jake
34
39
  end
35
40
  end
36
41
 
42
+ # Yields to the block for each build in the group.
37
43
  def each(&block)
38
44
  @builds.each(&block)
39
45
  end
40
46
 
47
+ # Forces the build to generate new files even if target files appear up-to-date.
41
48
  def force!
42
49
  @forced = true
43
50
  end
44
51
 
52
+ # Returns +true+ iff this is a forced build.
45
53
  def forced?
46
- !!@forced
54
+ defined?(@forced)
55
+ end
56
+
57
+ # Returns a list of names for all packages in the build.
58
+ def packages
59
+ list = []
60
+ @packages.each { |name, pkg| list << name }
61
+ @bundles.each { |name, pkg| list << name }
62
+ list
47
63
  end
48
64
 
65
+ # Returns the +Buildable+ with the given name.
49
66
  def package(name)
50
67
  @packages[name.to_sym] || @bundles[name.to_sym]
51
68
  end
52
69
 
70
+ # Runs the build, generating new files in +build_directory+.
53
71
  def run!
54
- @packages.each { |name, pkg| pkg.write! }
55
- @bundles.each { |name, pkg| pkg.write! }
56
- @helper.after_build(self) if @helper.respond_to?(:after_build)
72
+ FileUtils.cd(@dir) do
73
+ @packages.each { |name, pkg| pkg.write! }
74
+ @bundles.each { |name, pkg| pkg.write! }
75
+ fire(:build_complete)
76
+ end
57
77
  end
58
78
 
79
+ # Returns the path to the build directory, where generated files appear.
59
80
  def build_directory
60
81
  "#{ @dir }/#{ @config[:build_directory] || '.' }"
61
82
  end
83
+ alias :build_dir :build_directory
62
84
 
85
+ # Returns the path to the source directory, where source code is read from.
63
86
  def source_directory
64
87
  "#{ @dir }/#{ @config[:source_directory] || '.' }"
65
88
  end
89
+ alias :source_dir :source_directory
66
90
 
91
+ # Returns the header string used for the build, or an empty string if no
92
+ # header file has been set.
67
93
  def header
68
94
  @config[:header] ?
69
95
  Jake.read("#{ source_directory }/#{ @config[:header] }") :
70
96
  ""
71
97
  end
72
98
 
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.
73
102
  def packer_settings(build_name)
74
103
  build = @builds[build_name.to_sym]
75
104
  return false unless build
76
105
  build[:packer].nil? ? build : build[:packer]
77
106
  end
78
107
 
108
+ # Returns +true+ iff filename suffixes based on build name should be added
109
+ # to generated files for the given build name.
79
110
  def use_suffix?(build_name)
80
111
  build = @builds[build_name.to_sym]
81
112
  return true unless build
82
113
  build[:suffix] != false
83
114
  end
84
115
 
116
+ # Returns the name of the layout being used, either +together+ or +apart+.
85
117
  def layout
86
118
  @config[:layout] || DEFAULT_LAYOUT
87
119
  end
@@ -1,11 +1,15 @@
1
- require 'fileutils'
2
- require 'packr'
3
-
4
1
  module Jake
2
+ # A +Buildable+ represents a group of files that may be merged to form a single
3
+ # build file. There are two subtypes of +Buildable+; a +Package+ takes several
4
+ # source files and produces a build file, and a +Bundle+ takes several +Package+
5
+ # build files to produce another build file. This class should be considered
6
+ # abstract as some of its methods must be filled in by subtypes.
5
7
  class Buildable
6
8
 
7
9
  attr_reader :name
8
10
 
11
+ # Create a new +Buildable+ using a +Build+ container, a name and a configuration
12
+ # hash, typically a subsection of jake.yml.
9
13
  def initialize(build, name, config)
10
14
  @build, @name = build, name
11
15
  @config = case config
@@ -16,17 +20,21 @@ module Jake
16
20
  @code = {}
17
21
  end
18
22
 
23
+ # Returns the parent +Buildable+ set using the +extends+ option, or +nil+ if
24
+ # there is no parent.
19
25
  def parent
20
26
  return nil unless @config[:extends]
21
27
  @parent ||= @build.package(@config[:extends])
22
28
  end
23
29
 
30
+ # Returns the source directory for this package.
24
31
  def directory
25
32
  dir = @config[:directory]
26
33
  return parent.directory if parent && !dir
27
34
  "#{ @build.source_directory }/#{ @config[:directory] }"
28
35
  end
29
36
 
37
+ # Returns the path to the output file from this package for the given build name.
30
38
  def build_path(build_name)
31
39
  suffix = @build.use_suffix?(build_name) ? "-#{ build_name }" : ""
32
40
  @build.layout == 'together' ?
@@ -34,6 +42,8 @@ module Jake
34
42
  "#{ @build.build_directory }/#{ build_name }/#{ @name }.js"
35
43
  end
36
44
 
45
+ # Returns +true+ if the build file for the given build name is out of date and
46
+ # should be regenerated.
37
47
  def build_needed?(name)
38
48
  return true if @build.forced?
39
49
  path = build_path(name)
@@ -42,13 +52,15 @@ module Jake
42
52
  files.any? { |path| File.mtime(path) > build_time }
43
53
  end
44
54
 
55
+ # Returns the header string being used for this package.
45
56
  def header
46
57
  content = @config[:header] ?
47
58
  Jake.read("#{ directory }/#{ @config[:header] }") :
48
59
  (parent ? parent.header : @build.header)
49
- ERB.new(content).result(@build.helper.scope).strip
60
+ Jake.erb(content).result(@build.helper.scope).strip
50
61
  end
51
62
 
63
+ # Returns the PackR settings to use for this package during the given build.
52
64
  def packer_settings(build_name)
53
65
  global = @build.packer_settings(build_name)
54
66
  local = @config[:packer]
@@ -57,20 +69,28 @@ module Jake
57
69
  {}.merge(global || {}).merge(local || {})
58
70
  end
59
71
 
72
+ # Returns a hash containing any metadata attached to the package in the config.
73
+ def meta
74
+ @config[:meta] || {}
75
+ end
76
+
77
+ # Generates all the build files for this package by looping over all the
78
+ # required builds and compressing the source code using each set of minification
79
+ # options. Files are only generated if they are out of date or the build has
80
+ # been forced.
60
81
  def write!
61
- puts "Package #{@name}..."
62
-
63
82
  @build.each do |name, settings|
64
- next unless build_needed?(name)
65
-
66
- @build.helper.build = name
67
83
  path = build_path(name)
84
+ @build.fire(:file_not_changed, self, name, path) and next unless build_needed?(name)
85
+
86
+ @build.helper.build = name.to_s
68
87
  FileUtils.mkdir_p(File.dirname(path))
69
88
  File.open(path, 'wb') { |f| f.write( (header + "\n\n" + code(name)).strip ) }
70
89
 
90
+ @build.fire(:file_created, self, name, path)
91
+
71
92
  size = (File.size(path)/1024.0).ceil
72
93
  path = path.sub(@build.build_directory, '')
73
- puts " -- build '#{ name }' created #{ path }, #{ size } kb"
74
94
  end
75
95
  end
76
96
 
@@ -1,15 +1,22 @@
1
1
  module Jake
2
2
  class Bundle < Buildable
3
3
 
4
+ # Returns a list of paths to all the files used to build this package.
4
5
  def files
5
6
  base = parent ? parent.files : []
6
7
  base + @config[:files].map { |pkg| @build.package(pkg).files }.flatten
7
8
  end
8
9
 
10
+ # Returns the full uncompressed source code of this package, before
11
+ # ERB processing. ERB output will be build-dependent; this method
12
+ # simply builds the raw template for further processing by other
13
+ # methods.
9
14
  def source
10
15
  @source ||= @config[:files].map { |pkg| @build.package(pkg).source }.join("\n\n\n")
11
16
  end
12
17
 
18
+ # Returns the result of building the source template and minifying
19
+ # the output using the given named set of PackR settings.
13
20
  def code(name)
14
21
  joiner = (packer_settings(name) == false) ? "\n\n\n" : "\n"
15
22
  @code[name] ||= @config[:files].map { |pkg| @build.package(pkg).code(name) }.join(joiner)
@@ -0,0 +1,15 @@
1
+ module Jake
2
+ # The +Helper+ class stores helper methods that can be called from ERB
3
+ # when generating source code. Use +jake_helper+ to define new helpers.
4
+ class Helper
5
+ attr_accessor :build
6
+ attr_reader :options
7
+
8
+ def initialize(options = {})
9
+ @options = options
10
+ end
11
+
12
+ def scope; binding; end
13
+ end
14
+ end
15
+
@@ -1,6 +1,7 @@
1
1
  module Jake
2
2
  class Package < Buildable
3
3
 
4
+ # Returns a list of paths to all the files used to build this package.
4
5
  def files
5
6
  base = parent ? parent.files : []
6
7
  base + @config[:files].map do |path|
@@ -9,22 +10,23 @@ module Jake
9
10
  end
10
11
  end
11
12
 
13
+ # Returns the full uncompressed source code of this package, before
14
+ # ERB processing. ERB output will be build-dependent; this method
15
+ # simply builds the raw template for further processing by other
16
+ # methods.
12
17
  def source
13
18
  @source ||= files.map { |path| Jake.read(path) }.join("\n\n\n")
14
19
  end
15
20
 
21
+ # Returns the result of building the source template and minifying
22
+ # the output using the given named set of PackR settings.
16
23
  def code(name)
17
24
  return @code[name] if @code[name]
18
25
  settings = packer_settings(name)
19
- output = ERB.new(source).result(@build.helper.scope)
26
+ output = Jake.erb(source).result(@build.helper.scope)
20
27
  @code[name] = settings ? Packr.pack(output, settings) : output
21
28
  end
22
29
 
23
- def header
24
- reqs = @config[:requires] || []
25
- [super, *reqs.map { |r| "// @require #{r}" }].join("\n")
26
- end
27
-
28
30
  end
29
31
  end
30
32
 
@@ -0,0 +1,22 @@
1
+ jake_helper :version do
2
+ "0.5.0"
3
+ end
4
+
5
+ FILES = []
6
+ DEPS = {}
7
+
8
+ jake_hook :file_created do |build, package, build_type, path|
9
+ FILES << File.basename(path)
10
+ DEPS[path] = package.meta if build_type == :min
11
+ end
12
+
13
+ jake_hook :build_complete do |build|
14
+ write = lambda do |file, content|
15
+ File.open(File.join(build.build_dir, file), 'w') { |f| f.write(content) }
16
+ end
17
+ write['README', 'Should be generated after build']
18
+ write['LISTING', FILES.sort * "\n"]
19
+
20
+ write['packages.js', ERB.new(File.read('packages.erb')).result(binding)]
21
+ end
22
+
@@ -0,0 +1,10 @@
1
+ bar-min.js
2
+ bar.js
3
+ basic-min.js
4
+ basic.js
5
+ box-min.js
6
+ box.js
7
+ ext-min.js
8
+ ext.js
9
+ foo-min.js
10
+ foo.js
@@ -0,0 +1 @@
1
+ Should be generated after build
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Jake test files should all include this
3
+ * even if they have been minified.
4
+ * 0.5.0-min
5
+ **/
6
+
7
+ Basic={VERSION:"0.5.0-min",function(a){var b=4;return b+this._0+a}};
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Jake test files should all include this
3
+ * even if they have been minified.
4
+ * 0.5.0-src
5
+ **/
6
+
7
+ Basic = {
8
+ VERSION: "0.5.0-src",
9
+
10
+ function(something) {
11
+ var myVar = 4;
12
+ return myVar + this._foo + something;
13
+ }
14
+ };
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Jake test files should all include this
3
+ * even if they have been minified.
4
+ * 0.5.0-min
5
+ **/
6
+
7
+ Foo=(function(b,c){var a=true;return{_0:null,field:a,global:foo}})(window,something);
8
+ Basic={VERSION:"0.5.0-min",function(a){var b=4;return b+this._foo+a}};Basic.Ext="MIN";
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Jake test files should all include this
3
+ * even if they have been minified.
4
+ * 0.5.0-src
5
+ **/
6
+
7
+ Foo = (function(my, vars) {
8
+ var another = true;
9
+
10
+ return {
11
+ _priv: null,
12
+ field: another,
13
+ global: foo
14
+ };
15
+ })(window, something);
16
+
17
+
18
+ Basic = {
19
+ VERSION: "0.5.0-src",
20
+
21
+ function(something) {
22
+ var myVar = 4;
23
+ return myVar + this._foo + something;
24
+ }
25
+ };
26
+
27
+
28
+ Basic.Ext = "SRC";
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Jake test files should all include this
3
+ * even if they have been minified.
4
+ * 0.5.0-min
5
+ **/
6
+
7
+ Basic={VERSION:"0.5.0-min",function(a){var b=4;return b+this._foo+a}};Basic.Ext="MIN";
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Jake test files should all include this
3
+ * even if they have been minified.
4
+ * 0.5.0-src
5
+ **/
6
+
7
+ Basic = {
8
+ VERSION: "0.5.0-src",
9
+
10
+ function(something) {
11
+ var myVar = 4;
12
+ return myVar + this._foo + something;
13
+ }
14
+ };
15
+
16
+
17
+ Basic.Ext = "SRC";
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Jake test files should all include this
3
+ * even if they have been minified.
4
+ * 0.5.0-min
5
+ **/
6
+
7
+ Foo=(function(b,c){var a=true;return{_0:null,field:a,global:foo}})(window,something);
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Jake test files should all include this
3
+ * even if they have been minified.
4
+ * 0.5.0-src
5
+ **/
6
+
7
+ Foo = (function(my, vars) {
8
+ var another = true;
9
+
10
+ return {
11
+ _priv: null,
12
+ field: another,
13
+ global: foo
14
+ };
15
+ })(window, something);
@@ -0,0 +1,3 @@
1
+ /** Alternate header 0.5.0-min **/
2
+
3
+ (function(object){var Bar={_0:object}})();
@@ -0,0 +1,5 @@
1
+ /** Alternate header 0.5.0-src **/
2
+
3
+ (function(object) {
4
+ var Bar = {_another: object};
5
+ })();
@@ -0,0 +1,38 @@
1
+ ---
2
+ source_directory: src
3
+ build_directory: output
4
+ builds:
5
+ min:
6
+ shrink_vars: true
7
+ private: true
8
+ src:
9
+ packer: false
10
+ suffix: false
11
+ header: head
12
+ packages:
13
+ basic: basic
14
+ ext:
15
+ extends: basic
16
+ packer:
17
+ private: false
18
+ files:
19
+ - basic-ext
20
+ meta:
21
+ provides:
22
+ - Basic
23
+ requires:
24
+ - Foo
25
+ sub/dir/foo:
26
+ - foo/foo
27
+ sub/path/bar:
28
+ directory: foo
29
+ header: ../head2
30
+ packer:
31
+ shrink_vars: false
32
+ files:
33
+ - bar
34
+ bundles:
35
+ combo/box:
36
+ - sub/dir/foo
37
+ - ext
38
+
@@ -0,0 +1,8 @@
1
+ JS.Packages(function() { with(this) {
2
+ <% DEPS.each do |path, meta| %>
3
+ file('<%= path %>')
4
+ .provides(<%= (meta[:provides] || []).map { |p| p.inspect } * ', ' %>)
5
+ .requires(<%= (meta[:requires] || []).map { |p| p.inspect } * ', ' %>);
6
+ <% end %>
7
+ }});
8
+
@@ -0,0 +1,2 @@
1
+ Basic.Ext = "<%= build.upcase %>";
2
+
@@ -0,0 +1,9 @@
1
+ Basic = {
2
+ VERSION: "<%= version %>-<%= build %>",
3
+
4
+ function(something) {
5
+ var myVar = 4;
6
+ return myVar + this._foo + something;
7
+ }
8
+ };
9
+
@@ -0,0 +1,4 @@
1
+ (function(object) {
2
+ var Bar = {_another: object};
3
+ })();
4
+
@@ -0,0 +1,10 @@
1
+ Foo = (function(my, vars) {
2
+ var another = true;
3
+
4
+ return {
5
+ _priv: null,
6
+ field: another,
7
+ global: foo
8
+ };
9
+ })(window, something);
10
+
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Jake test files should all include this
3
+ * even if they have been minified.
4
+ * <%= version %>-<%= build %>
5
+ **/
6
+
@@ -0,0 +1,7 @@
1
+
2
+
3
+
4
+ /** Alternate header <%= version %>-<%= build %> **/
5
+
6
+
7
+
@@ -0,0 +1,29 @@
1
+ require "test/unit"
2
+ require "jake"
3
+ require "fileutils"
4
+ require "find"
5
+
6
+ class TestJake < Test::Unit::TestCase
7
+ DIR = File.dirname(__FILE__)
8
+
9
+ def setup
10
+ FileUtils.rm_rf(File.join(DIR, 'output'))
11
+ end
12
+
13
+ def test_build
14
+ Jake.clear_hooks!
15
+ Jake.build!(DIR)
16
+ expected = File.join(DIR, 'expected')
17
+ actual = File.join(DIR, 'output')
18
+ Find.find(expected) do |path|
19
+ next unless File.file?(path)
20
+ actual_path = actual + path.gsub(expected, '')
21
+
22
+ flunk "File #{actual_path} is missing" unless File.file?(actual_path)
23
+
24
+ assert_equal File.read(path).strip, File.read(actual_path),
25
+ "File #{actual_path} does not match #{path}"
26
+ end
27
+ end
28
+ end
29
+
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jake
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.3
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - James Coglan
@@ -9,11 +9,11 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-05-10 00:00:00 +01:00
12
+ date: 2009-07-06 00:00:00 +01:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
- name: oyster
16
+ name: eventful
17
17
  type: :runtime
18
18
  version_requirement:
19
19
  version_requirements: !ruby/object:Gem::Requirement
@@ -32,6 +32,16 @@ dependencies:
32
32
  - !ruby/object:Gem::Version
33
33
  version: "0"
34
34
  version:
35
+ - !ruby/object:Gem::Dependency
36
+ name: oyster
37
+ type: :runtime
38
+ version_requirement:
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: "0"
44
+ version:
35
45
  - !ruby/object:Gem::Dependency
36
46
  name: hoe
37
47
  type: :development
@@ -40,9 +50,9 @@ dependencies:
40
50
  requirements:
41
51
  - - ">="
42
52
  - !ruby/object:Gem::Version
43
- version: 1.12.1
53
+ version: 2.0.0
44
54
  version:
45
- description: Jake is a tool for building JavaScript library packages from source code. It allows builds to be specified using simple YAML files, and provides a command-line tool for generating package files. It also allows ERB to be embedded in JavaScript source code so that build data or new code can be generated during the build process.
55
+ description: ""
46
56
  email:
47
57
  - jcoglan@googlemail.com
48
58
  executables:
@@ -60,13 +70,37 @@ files:
60
70
  - Rakefile
61
71
  - bin/jake
62
72
  - lib/jake.rb
73
+ - lib/jake/helper.rb
63
74
  - lib/jake/build.rb
64
75
  - lib/jake/buildable.rb
65
76
  - lib/jake/package.rb
66
77
  - lib/jake/bundle.rb
67
78
  - test/test_jake.rb
79
+ - test/jake.yml
80
+ - test/Jakefile
81
+ - test/packages.erb
82
+ - test/expected/combo/box.js
83
+ - test/expected/combo/box-min.js
84
+ - test/expected/sub/dir/foo.js
85
+ - test/expected/sub/dir/foo-min.js
86
+ - test/expected/sub/path/bar.js
87
+ - test/expected/sub/path/bar-min.js
88
+ - test/expected/basic.js
89
+ - test/expected/basic-min.js
90
+ - test/expected/ext.js
91
+ - test/expected/ext-min.js
92
+ - test/expected/LISTING
93
+ - test/expected/README
94
+ - test/src/foo/bar.js
95
+ - test/src/foo/foo.js
96
+ - test/src/basic.js
97
+ - test/src/basic-ext.js
98
+ - test/src/head.js
99
+ - test/src/head2.js
68
100
  has_rdoc: true
69
101
  homepage: http://github.com/jcoglan/jake
102
+ licenses: []
103
+
70
104
  post_install_message:
71
105
  rdoc_options:
72
106
  - --main
@@ -88,9 +122,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
88
122
  requirements: []
89
123
 
90
124
  rubyforge_project: jake
91
- rubygems_version: 1.3.1
125
+ rubygems_version: 1.3.3
92
126
  signing_key:
93
- specification_version: 2
94
- summary: Jake is a tool for building JavaScript library packages from source code
127
+ specification_version: 3
128
+ summary: ""
95
129
  test_files:
96
130
  - test/test_jake.rb