jim 0.2.3 → 0.3.0.pre

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.
Files changed (66) hide show
  1. data/Gemfile +2 -1
  2. data/Gemfile.lock +2 -0
  3. data/HISTORY +13 -0
  4. data/README.md +148 -0
  5. data/Rakefile +6 -3
  6. data/bin/jim +1 -2
  7. data/default +0 -0
  8. data/jim.gemspec +142 -105
  9. data/lib/jim.rb +1 -1
  10. data/lib/jim/bundler.rb +168 -73
  11. data/lib/jim/cli.rb +200 -151
  12. data/lib/jim/index.rb +20 -9
  13. data/lib/jim/installer.rb +46 -46
  14. data/lib/jim/rack.rb +57 -20
  15. data/lib/jim/templates/jimfile +11 -5
  16. data/lib/jim/version_parser.rb +3 -3
  17. data/test/fixtures/infoincomments.js +1 -1
  18. data/test/fixtures/jimfile +14 -7
  19. data/test/fixtures/jquery-1.4.1.js +3 -6057
  20. data/test/fixtures/jquery.color.js +1 -1
  21. data/test/fixtures/localfile.js +1 -1
  22. data/test/fixtures/mustache.js/package.json +1 -1
  23. data/test/fixtures/noversion.js +1 -1
  24. data/test/fixtures/old_jimfile +7 -0
  25. data/test/fixtures/sammy-0.5.0/examples/backend/app.rb +4 -4
  26. data/test/fixtures/sammy-0.5.0/examples/backend/public/javascripts/app.js +18 -18
  27. data/test/fixtures/sammy-0.5.0/examples/backend/public/javascripts/jquery.cloudkit.js +1 -1
  28. data/test/fixtures/sammy-0.5.0/examples/backend/public/javascripts/jquery.js +1 -1
  29. data/test/fixtures/sammy-0.5.0/examples/backend/public/javascripts/sammy.js +161 -161
  30. data/test/fixtures/sammy-0.5.0/examples/backend/public/templates/task.html.erb +1 -1
  31. data/test/fixtures/sammy-0.5.0/examples/backend/public/templates/task_details.html.erb +1 -1
  32. data/test/fixtures/sammy-0.5.0/examples/backend/views/app.sass +6 -6
  33. data/test/fixtures/sammy-0.5.0/examples/backend/views/index.haml +5 -5
  34. data/test/fixtures/sammy-0.5.0/examples/form_handling/index.html +16 -16
  35. data/test/fixtures/sammy-0.5.0/examples/hello_world/index.html +13 -13
  36. data/test/fixtures/sammy-0.5.0/examples/location_override/data.html +28 -28
  37. data/test/fixtures/sammy-0.5.0/examples/location_override/index.html +18 -18
  38. data/test/fixtures/sammy-0.5.0/examples/location_override/test.html +36 -36
  39. data/test/fixtures/sammy-0.5.0/lib/min/sammy-0.5.0.min.js +1 -1
  40. data/test/fixtures/sammy-0.5.0/lib/min/sammy-lastest.min.js +1 -1
  41. data/test/fixtures/sammy-0.5.0/lib/plugins/sammy.cache.js +13 -13
  42. data/test/fixtures/sammy-0.5.0/lib/plugins/sammy.haml.js +2 -2
  43. data/test/fixtures/sammy-0.5.0/lib/plugins/sammy.json.js +15 -15
  44. data/test/fixtures/sammy-0.5.0/lib/plugins/sammy.mustache.js +46 -46
  45. data/test/fixtures/sammy-0.5.0/lib/plugins/sammy.nested_params.js +29 -29
  46. data/test/fixtures/sammy-0.5.0/lib/plugins/sammy.storage.js +54 -54
  47. data/test/fixtures/sammy-0.5.0/lib/plugins/sammy.template.js +17 -17
  48. data/test/fixtures/sammy-0.5.0/lib/sammy.js +220 -220
  49. data/test/fixtures/sammy-0.5.0/test/fixtures/partial.html +1 -1
  50. data/test/fixtures/sammy-0.5.0/test/index.html +26 -26
  51. data/test/fixtures/sammy-0.5.0/test/test_sammy_application.js +60 -60
  52. data/test/fixtures/sammy-0.5.0/test/test_sammy_event_context.js +21 -21
  53. data/test/fixtures/sammy-0.5.0/test/test_sammy_location_proxy.js +3 -3
  54. data/test/fixtures/sammy-0.5.0/test/test_sammy_plugins.js +17 -17
  55. data/test/fixtures/sammy-0.5.0/test/test_sammy_storage.js +4 -4
  56. data/test/helper.rb +15 -0
  57. data/test/test_jim_bundler.rb +114 -74
  58. data/test/test_jim_cli.rb +34 -18
  59. data/test/test_jim_index.rb +19 -19
  60. data/test/test_jim_installer.rb +13 -13
  61. data/test/test_jim_rack.rb +41 -0
  62. data/test/test_jim_version_parser.rb +4 -4
  63. metadata +204 -41
  64. data/.gitignore +0 -24
  65. data/README.rdoc +0 -105
  66. data/lib/jim/templates/commands +0 -58
data/lib/jim/index.rb CHANGED
@@ -2,16 +2,21 @@ module Jim
2
2
  # Index managages a list of directories which are searched to find requirements
3
3
  class Index
4
4
  attr_reader :directories
5
-
5
+
6
+ # Initialize an Index with a list of directories. The firse directory
7
+ # is assumed to be the JIMHOME
6
8
  def initialize(*directories)
7
9
  @directories = [directories].flatten.compact
8
10
  @jimhome_re = /#{Pathname.new(@directories.first).expand_path.to_s}/
9
11
  end
10
12
 
13
+ # Add a directory to the index
11
14
  def add(directory)
12
15
  @directories.unshift directory
13
16
  end
14
-
17
+
18
+ # List all available files in the directories or only those matching `search`.
19
+ # Returns a sorted array of arrays.
15
20
  def list(search = nil)
16
21
  list = {}
17
22
  each_file_in_index('.js') do |filename|
@@ -33,9 +38,12 @@ module Jim
33
38
  list.sort
34
39
  end
35
40
 
41
+ # Find a file in the index by `name` and an optional `version`.
42
+ # If found, returns a `Pathname` where the file can be retrieved.
36
43
  def find(name, version = nil)
37
44
  name = Pathname.new(name)
38
45
  stem = name.basename
46
+ version = version && version.strip != '' ? version.strip : nil
39
47
  ext = '.js'
40
48
  possible_paths = if version
41
49
  [
@@ -60,20 +68,23 @@ module Jim
60
68
  end
61
69
  final
62
70
  end
63
-
64
- def in_jimhome?(path)
65
- !!(path.to_s =~ @jimhome_re)
66
- end
67
-
71
+
72
+ # Find _all_ paths matching `name` and `version`. Returning an array.
68
73
  def find_all(name, version = nil)
69
74
  matched = []
70
75
  find(name, version) {|p| matched << p }
71
76
  matched
72
77
  end
73
-
78
+
79
+ # Is this path in the JIMHOME
80
+ def in_jimhome?(path)
81
+ !!(path.to_s =~ @jimhome_re)
82
+ end
83
+
84
+ # Iterate through every file in the index yielding the path to the block
74
85
  def each_file_in_index(ext, &block)
75
86
  Jim.each_path_in_directories(@directories, ext, [], &block)
76
87
  end
77
88
 
78
89
  end
79
- end
90
+ end
data/lib/jim/installer.rb CHANGED
@@ -1,11 +1,11 @@
1
1
  module Jim
2
- # Installer is the workhorse of Jim. It handles taking an install path
3
- # (a url, a local path, anything that Downlow.get can handle), staging it
4
- # into a temporary directory and extracting the file(s) into a path for the
5
- # specific name and version of the lib. names and versions are determined
6
- # automatically or can be passed in as options.
2
+ # Installer is the workhorse of Jim. It handles taking an install path
3
+ # (a url, a local path, anything that Downlow.get can handle), staging it
4
+ # into a temporary directory and extracting the file(s) into a path for the
5
+ # specific name and version of the lib. names and versions are determined
6
+ # automatically or can be passed in as options.
7
7
  class Installer
8
-
8
+
9
9
  IGNORE_DIRS = %w{
10
10
  vendor
11
11
  external
@@ -19,113 +19,113 @@ module Jim
19
19
  \_([^\/]+)
20
20
  \.([^\/]+)
21
21
  }
22
-
23
- # get the tmp_root where files are staged
22
+
23
+ # Get the tmp_root where files are staged
24
24
  def self.tmp_root
25
25
  @tmp_root ||= Pathname.new('/tmp/jim')
26
26
  end
27
-
28
- # set the tmp_root where files are staged. Default: '/tmp/jim'
27
+
28
+ # Set the tmp_root where files are staged. Default: '/tmp/jim'
29
29
  def self.tmp_root=(new_tmp_root)
30
30
  @tmp_root = Pathname.new(new_tmp_root)
31
31
  end
32
-
32
+
33
33
  attr_reader :fetch_path, :install_path, :options, :fetched_path, :name, :version, :package_json
34
-
35
- # create an installer. fetch_path is anything that Downlow can understand.
36
- # install path is the final directory
34
+
35
+ # Create an installer. fetch_path is anything that Downlow can understand.
36
+ # Install path is the final directory
37
37
  def initialize(fetch_path, install_path, options = {})
38
38
  @fetch_path = Pathname.new(fetch_path)
39
39
  @install_path = Pathname.new(install_path)
40
40
  @options = options
41
41
  end
42
42
 
43
- # fetch the file at fetch_path with and stage into a tmp directory.
44
- # returns the staged directory of fetched file(s).
43
+ # Fetch the file at fetch_path with and stage into a tmp directory.
44
+ # Returns the staged directory of fetched file(s).
45
45
  def fetch
46
- logger.info "fetching #{fetch_path}"
46
+ logger.info "Fetching #{fetch_path}"
47
47
  @fetched_path = Downlow.get(fetch_path, tmp_path, :tmp_dir => tmp_root)
48
- logger.debug "fetched #{@fetched_path}"
48
+ logger.debug "Fetched #{@fetched_path}"
49
49
  @fetched_path
50
50
  end
51
51
 
52
- # fetch and install the files determining their name and version if not provided.
53
- # if the fetch_path contains a directory of files, it itterates over the directory
52
+ # Fetch and install the files determining their name and version if not provided.
53
+ # If the fetch_path contains a directory of files, it iterates over the directory
54
54
  # installing each file that isn't in IGNORE_DIRS and a name and version can be
55
55
  # determined for. It also installs a package.json file along side the JS file
56
56
  # that contains meta data including the name and version, also merging with the
57
57
  # original package.json if found.
58
- #
58
+ #
59
59
  # If options[:shallow] == true it will just copy the single file without any leading
60
60
  # directories or a package.json. 'shallow' installation is used for Bundle#vendor
61
61
  def install
62
62
  fetch
63
63
  parse_package_json
64
64
  determine_name_and_version
65
-
65
+
66
66
  if !name || name.to_s =~ /^\s*$/ # blank
67
- raise(Jim::InstallError, "could not determine name for #{@fetched_path}")
67
+ raise(Jim::InstallError, "Could not determine name for #{@fetched_path}")
68
68
  end
69
-
70
- logger.info "installing #{name} #{version}"
69
+
70
+ logger.info "Installing #{name} #{version}"
71
71
  logger.debug "fetched_path #{@fetched_path}"
72
-
72
+
73
73
  if options[:shallow]
74
74
  shallow_filename = [name, (version == "0" ? nil : version)].compact.join('-')
75
75
  final_path = install_path + "#{shallow_filename}#{fetched_path.extname}"
76
76
  else
77
77
  final_path = install_path + 'lib' + "#{name}-#{version}" + "#{name}.js"
78
78
  end
79
-
79
+
80
80
  if @fetched_path.directory?
81
81
  # install every js file
82
82
  installed_paths = []
83
83
  sub_options = options.merge({
84
- :name => nil,
84
+ :name => nil,
85
85
  :version => nil,
86
- :parent_version => version,
86
+ :parent_version => version,
87
87
  :package_json => package_json.merge("name" => nil)
88
88
  })
89
89
  Jim.each_path_in_directories([@fetched_path], '.js', IGNORE_DIRS) do |subfile|
90
- logger.info "found file #{subfile}"
90
+ logger.info "Found file #{subfile}"
91
91
  installed_paths << Jim::Installer.new(subfile, install_path, sub_options).install
92
92
  end
93
- logger.info "extracted to #{install_path}, #{installed_paths.length} file(s)"
93
+ logger.info "Extracted to #{install_path}, #{installed_paths.length} file(s)"
94
94
  return installed_paths
95
95
  end
96
-
97
- logger.debug "installing to #{final_path}"
98
- if final_path.exist?
96
+
97
+ logger.debug "Installing to #{final_path}"
98
+ if final_path.exist?
99
99
  logger.debug "#{final_path} already exists"
100
100
  if options[:force]
101
101
  FileUtils.rm_rf(final_path)
102
102
  elsif Digest::MD5.hexdigest(File.read(final_path)) == Digest::MD5.hexdigest(File.read(@fetched_path))
103
- logger.info "duplicate file, skipping"
103
+ logger.info "Duplicate file, skipping"
104
104
  return final_path
105
105
  else
106
106
  raise(Jim::FileExists.new(final_path))
107
107
  end
108
108
  end
109
-
109
+
110
110
  Downlow.extract(@fetched_path, :destination => final_path, :tmp_dir => tmp_root)
111
111
  # install json
112
112
  install_package_json(final_path.dirname + 'package.json') if !options[:shallow]
113
113
  installed = final_path.directory? ? Dir.glob(final_path + '**/*').length : 1
114
- logger.info "extracted to #{final_path}, #{installed} file(s)"
114
+ logger.info "Extracted to #{final_path}, #{installed} file(s)"
115
115
  final_path
116
116
  ensure
117
117
  FileUtils.rm_rf(@fetched_path) if @fetched_path && @fetched_path.exist?
118
118
  final_path
119
119
  end
120
-
121
- # determine the name and version of the @fetched_path. Tries a number of
120
+
121
+ # Determine the name and version of the @fetched_path. Tries a number of
122
122
  # strategies in order until both name and version are found:
123
123
  #
124
124
  # * from options (options[:name] ...)
125
125
  # * from comments (// name: )
126
126
  # * from a package.json ({"name": })
127
127
  # * from the filename (name-1.0.js)
128
- #
128
+ #
129
129
  # If no version can be found, version is set as "0"
130
130
  def determine_name_and_version
131
131
  (name && version) ||
@@ -138,7 +138,7 @@ module Jim
138
138
 
139
139
  private
140
140
  def tmp_root
141
- @tmp_root ||= make_tmp_root
141
+ @tmp_root ||= make_tmp_root
142
142
  end
143
143
 
144
144
  def tmp_dir
@@ -152,17 +152,17 @@ module Jim
152
152
  def logger
153
153
  Jim.logger
154
154
  end
155
-
155
+
156
156
  def make_tmp_root
157
157
  self.class.tmp_root + (Time.now.to_i + rand(10000)).to_s
158
158
  end
159
-
159
+
160
160
  def make_tmp_dir
161
161
  dir = tmp_root + fetch_path.stem
162
162
  dir.mkpath
163
163
  dir
164
164
  end
165
-
165
+
166
166
  def parse_package_json
167
167
  @package_json = @options[:package_json] || {}
168
168
  package_json_path = if fetched_path.directory?
@@ -180,7 +180,7 @@ module Jim
180
180
 
181
181
  def install_package_json(to_path, options = {})
182
182
  hash = @package_json.merge({
183
- "name" => name,
183
+ "name" => name,
184
184
  "version" => version,
185
185
  "install" => {
186
186
  "at" => Time.now.httpdate,
@@ -235,4 +235,4 @@ module Jim
235
235
  end
236
236
 
237
237
  end
238
- end
238
+ end
data/lib/jim/rack.rb CHANGED
@@ -2,51 +2,88 @@ require 'jim'
2
2
 
3
3
  module Jim
4
4
  # Jim::Rack is a Rack middleware for allowing live bundling and compression
5
- # of the requirements in your Jimfile without having to rebundle using the command
5
+ # of the bunldes in your Jimfile without having to rebundle using the command
6
6
  # line. You can specify a number of options:
7
7
  #
8
8
  # :jimfile: Path to your Jimfile (default ./Jimfile)
9
9
  # :jimhome: Path to your JIMHOME directory (default ENV['JIMHOME'] or ~/.jim)
10
- # :bundled_uri: URI to serve the bundled requirements
11
- # :compressed_uri: URI to serve the compressed requirements
10
+ # :bundle_uri: URI to serve the bundled requirements (default '/javascripts/')
11
+ #
12
+ # The `bundle_uri` should be ~ a directory and a bundle can be generated by
13
+ # requesting the bundlename.js behind the directory. For example, given a Jimfile
14
+ # like:
15
+ #
16
+ # {
17
+ # "bundles": {
18
+ # "default": [
19
+ # "jquery",
20
+ # "jquery.color",
21
+ # ["sammy", "0.6.3"]
22
+ # ]
23
+ # }
24
+ # }
25
+ #
26
+ # You could get the 'default' bundle by
27
+ #
28
+ # GET /javascripts/default.js
29
+ #
30
+ # Or the compressed version with:
31
+ #
32
+ # GET /javascripts/default.min.js
33
+ #
12
34
  class Rack
13
-
35
+
14
36
  def initialize(app, options = {})
15
37
  @app = app
16
38
  jimfile = Pathname.new(options[:jimfile] || 'Jimfile')
17
39
  jimhome = Pathname.new(options[:jimhome] || ENV['JIMHOME'] || '~/.jim').expand_path
18
40
  @bundler = Jim::Bundler.new(jimfile, Jim::Index.new(jimhome), options)
19
- @bundled_uri = options[:bundled_uri] || @bundler.options[:bundled_path]
20
- @compressed_uri = options[:compressed_uri] || @bundler.options[:compressed_path]
41
+ # unset the bundlers bundle dir so it returns a string
42
+ @bundler.bundle_dir = nil
43
+ @bundle_uri = options[:bundle_uri] || '/javascripts/'
21
44
  end
22
-
45
+
23
46
  def call(env)
24
47
  dup._call(env)
25
48
  end
26
-
49
+
27
50
  def _call(env)
28
51
  uri = env['PATH_INFO']
29
- if uri == @bundled_uri
30
- run_action(:bundle!)
31
- elsif uri == @compressed_uri
32
- run_action(:compress!)
52
+ if uri =~ bundle_matcher
53
+ name = $1
54
+ if name =~ compressed_matcher
55
+ run_action(:compress!, name.gsub(compressed_matcher, ''))
56
+ else
57
+ run_action(:bundle!, name)
58
+ end
33
59
  else
34
60
  @app.call(env)
35
61
  end
36
62
  end
37
-
38
- def run_action(which)
63
+
64
+ private
65
+ def bundle_matcher
66
+ @bundle_matcher ||= /^#{@bundle_uri}([\w\d\-\.]+)\.js$/
67
+ end
68
+
69
+ def compressed_matcher
70
+ @compressed_matcher ||= /#{@bundler.options[:compressed_suffix]}$/
71
+ end
72
+
73
+ def run_action(action, *args)
39
74
  begin
40
- [200, {'Content-Type' => 'text/javascript'}, @bundler.send(which, false)]
75
+ [200, {
76
+ 'Content-Type' => 'text/javascript'
77
+ }, [@bundler.send(action , *args)]]
41
78
  rescue => e
42
- [500, {'Content-Type' => 'text/html'}, <<-EOT
43
- <p>Jim failed in helping you out. There was an error when trying to #{which}.</p>
79
+ response = <<-EOT
80
+ <p>Jim failed in helping you out. There was an error when trying to run #{action}(#{args}).</p>
44
81
  <p>#{e}</p>
45
82
  <pre>#{e.backtrace}</pre>
46
83
  EOT
47
- ]
84
+ [500, {'Content-Type' => 'text/html'}, [response]]
48
85
  end
49
86
  end
50
-
87
+
51
88
  end
52
- end
89
+ end
@@ -1,6 +1,12 @@
1
- // bundled_path: public/javascripts/bundled.js
2
- // compressed_path: public/javascripts/compressed.js
3
- // vendor_dir: public/javascripts/vendor
4
-
5
- / start adding your requirements below:
1
+ {
2
+ "bundle_dir": "public/javascripts/",
3
+ "vendor_dir": "public/javascripts/vendor",
4
+ "bundles": {
5
+ /*
6
+ "default": [
7
+ "jquery"
8
+ ]
9
+ */
10
+ }
11
+ }
6
12
 
@@ -8,9 +8,9 @@ module Jim
8
8
  extension = f.scan(/\.[^\.\d\s\-\_][^\.]*$/)[0]
9
9
  if NOT_EXTENSIONS.include?(extension)
10
10
  extension = nil
11
- else
11
+ else
12
12
  f.gsub!(/#{extension}$/, '')
13
- end
13
+ end
14
14
 
15
15
  name, after_name, delimiter, version = f.scan(/^([a-z\.\-\_]+)(([\.\-\_\s])v?(([\w\d]{6,7})|(\d[\d\w\.]*)))?$/i)[0]
16
16
  [name || f, version || "0"]
@@ -23,4 +23,4 @@ module Jim
23
23
 
24
24
 
25
25
  end
26
- end
26
+ end
@@ -1,4 +1,4 @@
1
1
  // This file has its info in the comments
2
2
  // name: myproject
3
3
  // version: 1.2.2
4
- (function() {});
4
+ (function() {});
@@ -1,7 +1,14 @@
1
- // bundled_path: test/tmp/public/javascripts/bundled.js
2
- // compressed_path: test/tmp/public/javascripts/compressed.js
3
- // vendor_dir: test/tmp/public/javascripts/vendor
4
-
5
- jquery 1.4.1
6
- myproject
7
- localfile
1
+ {
2
+ "bundle_dir": "test/tmp/",
3
+ "vendor_dir": "test/tmp/public/javascripts/vendor",
4
+ "bundles": {
5
+ "default": [
6
+ ["jquery", "1.4.1"],
7
+ "myproject",
8
+ "localfile"
9
+ ],
10
+ "base": [
11
+ "jquery"
12
+ ]
13
+ }
14
+ }