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.
- data/Gemfile +2 -1
- data/Gemfile.lock +2 -0
- data/HISTORY +13 -0
- data/README.md +148 -0
- data/Rakefile +6 -3
- data/bin/jim +1 -2
- data/default +0 -0
- data/jim.gemspec +142 -105
- data/lib/jim.rb +1 -1
- data/lib/jim/bundler.rb +168 -73
- data/lib/jim/cli.rb +200 -151
- data/lib/jim/index.rb +20 -9
- data/lib/jim/installer.rb +46 -46
- data/lib/jim/rack.rb +57 -20
- data/lib/jim/templates/jimfile +11 -5
- data/lib/jim/version_parser.rb +3 -3
- data/test/fixtures/infoincomments.js +1 -1
- data/test/fixtures/jimfile +14 -7
- data/test/fixtures/jquery-1.4.1.js +3 -6057
- data/test/fixtures/jquery.color.js +1 -1
- data/test/fixtures/localfile.js +1 -1
- data/test/fixtures/mustache.js/package.json +1 -1
- data/test/fixtures/noversion.js +1 -1
- data/test/fixtures/old_jimfile +7 -0
- data/test/fixtures/sammy-0.5.0/examples/backend/app.rb +4 -4
- data/test/fixtures/sammy-0.5.0/examples/backend/public/javascripts/app.js +18 -18
- data/test/fixtures/sammy-0.5.0/examples/backend/public/javascripts/jquery.cloudkit.js +1 -1
- data/test/fixtures/sammy-0.5.0/examples/backend/public/javascripts/jquery.js +1 -1
- data/test/fixtures/sammy-0.5.0/examples/backend/public/javascripts/sammy.js +161 -161
- data/test/fixtures/sammy-0.5.0/examples/backend/public/templates/task.html.erb +1 -1
- data/test/fixtures/sammy-0.5.0/examples/backend/public/templates/task_details.html.erb +1 -1
- data/test/fixtures/sammy-0.5.0/examples/backend/views/app.sass +6 -6
- data/test/fixtures/sammy-0.5.0/examples/backend/views/index.haml +5 -5
- data/test/fixtures/sammy-0.5.0/examples/form_handling/index.html +16 -16
- data/test/fixtures/sammy-0.5.0/examples/hello_world/index.html +13 -13
- data/test/fixtures/sammy-0.5.0/examples/location_override/data.html +28 -28
- data/test/fixtures/sammy-0.5.0/examples/location_override/index.html +18 -18
- data/test/fixtures/sammy-0.5.0/examples/location_override/test.html +36 -36
- data/test/fixtures/sammy-0.5.0/lib/min/sammy-0.5.0.min.js +1 -1
- data/test/fixtures/sammy-0.5.0/lib/min/sammy-lastest.min.js +1 -1
- data/test/fixtures/sammy-0.5.0/lib/plugins/sammy.cache.js +13 -13
- data/test/fixtures/sammy-0.5.0/lib/plugins/sammy.haml.js +2 -2
- data/test/fixtures/sammy-0.5.0/lib/plugins/sammy.json.js +15 -15
- data/test/fixtures/sammy-0.5.0/lib/plugins/sammy.mustache.js +46 -46
- data/test/fixtures/sammy-0.5.0/lib/plugins/sammy.nested_params.js +29 -29
- data/test/fixtures/sammy-0.5.0/lib/plugins/sammy.storage.js +54 -54
- data/test/fixtures/sammy-0.5.0/lib/plugins/sammy.template.js +17 -17
- data/test/fixtures/sammy-0.5.0/lib/sammy.js +220 -220
- data/test/fixtures/sammy-0.5.0/test/fixtures/partial.html +1 -1
- data/test/fixtures/sammy-0.5.0/test/index.html +26 -26
- data/test/fixtures/sammy-0.5.0/test/test_sammy_application.js +60 -60
- data/test/fixtures/sammy-0.5.0/test/test_sammy_event_context.js +21 -21
- data/test/fixtures/sammy-0.5.0/test/test_sammy_location_proxy.js +3 -3
- data/test/fixtures/sammy-0.5.0/test/test_sammy_plugins.js +17 -17
- data/test/fixtures/sammy-0.5.0/test/test_sammy_storage.js +4 -4
- data/test/helper.rb +15 -0
- data/test/test_jim_bundler.rb +114 -74
- data/test/test_jim_cli.rb +34 -18
- data/test/test_jim_index.rb +19 -19
- data/test/test_jim_installer.rb +13 -13
- data/test/test_jim_rack.rb +41 -0
- data/test/test_jim_version_parser.rb +4 -4
- metadata +204 -41
- data/.gitignore +0 -24
- data/README.rdoc +0 -105
- 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
|
-
|
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
|
-
#
|
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
|
-
#
|
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
|
-
#
|
36
|
-
#
|
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
|
-
#
|
44
|
-
#
|
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 "
|
46
|
+
logger.info "Fetching #{fetch_path}"
|
47
47
|
@fetched_path = Downlow.get(fetch_path, tmp_path, :tmp_dir => tmp_root)
|
48
|
-
logger.debug "
|
48
|
+
logger.debug "Fetched #{@fetched_path}"
|
49
49
|
@fetched_path
|
50
50
|
end
|
51
51
|
|
52
|
-
#
|
53
|
-
#
|
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, "
|
67
|
+
raise(Jim::InstallError, "Could not determine name for #{@fetched_path}")
|
68
68
|
end
|
69
|
-
|
70
|
-
logger.info "
|
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 "
|
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 "
|
93
|
+
logger.info "Extracted to #{install_path}, #{installed_paths.length} file(s)"
|
94
94
|
return installed_paths
|
95
95
|
end
|
96
|
-
|
97
|
-
logger.debug "
|
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 "
|
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 "
|
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
|
-
#
|
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
|
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
|
-
# :
|
11
|
-
#
|
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
|
-
|
20
|
-
@
|
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
|
30
|
-
|
31
|
-
|
32
|
-
|
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
|
-
|
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, {
|
75
|
+
[200, {
|
76
|
+
'Content-Type' => 'text/javascript'
|
77
|
+
}, [@bundler.send(action , *args)]]
|
41
78
|
rescue => e
|
42
|
-
|
43
|
-
<p>Jim failed in helping you out. There was an error when trying to #{
|
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
|
data/lib/jim/templates/jimfile
CHANGED
@@ -1,6 +1,12 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
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
|
|
data/lib/jim/version_parser.rb
CHANGED
@@ -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
|
data/test/fixtures/jimfile
CHANGED
@@ -1,7 +1,14 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
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
|
+
}
|