bagger 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +6 -0
- data/.travis.yml +6 -0
- data/Gemfile +4 -0
- data/README.md +37 -0
- data/Rakefile +33 -0
- data/bagger.gemspec +29 -0
- data/lib/bagger/packager.rb +148 -0
- data/lib/bagger/version.rb +3 -0
- data/lib/bagger.rb +9 -0
- data/test/bagger_test.rb +265 -0
- data/test/test_helper.rb +11 -0
- data/tests.watchr +38 -0
- metadata +137 -0
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
# bagger
|
2
|
+
|
3
|
+
A framework agnostic packaging solution to speed up client side
|
4
|
+
rendering by using the following techniques:
|
5
|
+
|
6
|
+
* Generating versioned assets to maximize cache efficiency
|
7
|
+
* Combine, minify and lint javascript and css files to reduce bandwidth
|
8
|
+
* Zip assets to further reduce bandwidth consumption
|
9
|
+
* Generating a file manifest to lookup an asset's location
|
10
|
+
* Rewrite urls in css files with the versioned file name
|
11
|
+
* Bundle up the assets as a zip file
|
12
|
+
|
13
|
+
## Similar projects
|
14
|
+
|
15
|
+
* [jammit](https://github.com/documentcloud/jammit)
|
16
|
+
* [Rails 3 asset pipeline](http://blog.nodeta.com/2011/06/14/rails-3-1-asset-pipeline-in-the-real-world/)
|
17
|
+
* [assets.io](http://www.assets.io/)
|
18
|
+
|
19
|
+
## Roadmap
|
20
|
+
|
21
|
+
### Version 0.0.1 (Minimal Viable Product)
|
22
|
+
|
23
|
+
* Versioned assets
|
24
|
+
* Manifest files
|
25
|
+
* Combine javascript
|
26
|
+
* Combine css
|
27
|
+
* Rewrite css urls
|
28
|
+
* CLI binary
|
29
|
+
* Solid test suite
|
30
|
+
* Support for the following Ruby versions (MRI 1.8.7, 1.9.2, REE 1.8.7)
|
31
|
+
* Pass all tests on travisci.org
|
32
|
+
* Examples on how to integrate it into the development workflow using
|
33
|
+
tools like watch or supervisor
|
34
|
+
|
35
|
+
## Tests
|
36
|
+
|
37
|
+
check the build status on [travis.ci](http://travis-ci.org/wooga/bagger)
|
data/Rakefile
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'bundler/gem_tasks'
|
2
|
+
|
3
|
+
require 'rake/testtask'
|
4
|
+
|
5
|
+
task :default => ['test:units']
|
6
|
+
|
7
|
+
def rubies
|
8
|
+
require 'yaml'
|
9
|
+
rubies = YAML.load_file('.travis.yml')['rvm']
|
10
|
+
end
|
11
|
+
|
12
|
+
namespace :test do
|
13
|
+
Rake::TestTask.new(:units) do |t|
|
14
|
+
t.libs << "test"
|
15
|
+
t.test_files = FileList['test/*_test.rb']
|
16
|
+
|
17
|
+
t.verbose = true
|
18
|
+
end
|
19
|
+
|
20
|
+
desc 'run test suite with all ruby versions'
|
21
|
+
task :multi_ruby do
|
22
|
+
rubies.each do |ruby_version|
|
23
|
+
puts `rvm use #{ruby_version} && rake`
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
desc 'run bundle install for all rubies'
|
29
|
+
task :prepare_rubies do
|
30
|
+
rubies.each do |ruby_version|
|
31
|
+
puts `rvm use #{ruby_version} && gem install bundler && bundle`
|
32
|
+
end
|
33
|
+
end
|
data/bagger.gemspec
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "bagger/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "bagger"
|
7
|
+
s.version = Bagger::VERSION
|
8
|
+
s.authors = ["Patrick Huesler"]
|
9
|
+
s.email = ["patrick.huesler@gmail.com"]
|
10
|
+
s.homepage = ""
|
11
|
+
s.summary = "Asset packaging for the rest of us"
|
12
|
+
s.description = "A framework agnostic packaging solution for your assets: version files, combine them, minify them and create a manifest"
|
13
|
+
|
14
|
+
s.rubyforge_project = "bagger"
|
15
|
+
|
16
|
+
s.add_dependency "json"
|
17
|
+
s.add_dependency "addressable"
|
18
|
+
s.add_dependency "uglifier"
|
19
|
+
s.add_dependency "rainpress"
|
20
|
+
|
21
|
+
s.add_development_dependency "rake"
|
22
|
+
s.add_development_dependency "shoulda-context"
|
23
|
+
s.add_development_dependency "mocha"
|
24
|
+
|
25
|
+
s.files = `git ls-files`.split("\n")
|
26
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
27
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
28
|
+
s.require_paths = ["lib"]
|
29
|
+
end
|
@@ -0,0 +1,148 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
require 'json'
|
3
|
+
require 'digest/md5'
|
4
|
+
require 'addressable/uri'
|
5
|
+
require 'uglifier'
|
6
|
+
require 'rainpress'
|
7
|
+
|
8
|
+
module Bagger
|
9
|
+
class Packager
|
10
|
+
|
11
|
+
def initialize(options)
|
12
|
+
@options = options
|
13
|
+
@manifest_name = 'manifest.json'
|
14
|
+
@stylesheets = (@options[:combine] || {})[:stylesheets] || []
|
15
|
+
@javascripts = (@options[:combine] || {})[:javascripts] || []
|
16
|
+
@source_dir = @options[:source_dir]
|
17
|
+
@target_dir = @options[:target_dir]
|
18
|
+
@stylesheet_path = (@options[:combine] || {})[:stylesheet_path] || 'combined.css'
|
19
|
+
@javascript_path = (@options[:combine] || {})[:javascript_path] || 'combined.js'
|
20
|
+
@path_prefix = @options[:path_prefix] || ''
|
21
|
+
@manifest = {}
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_manifest(path, keep_original = true)
|
25
|
+
content = File.open(File.join(@target_dir, path)) { |f| f.read }
|
26
|
+
extension = File.extname(path)
|
27
|
+
basename = File.basename(path, extension)
|
28
|
+
dirname = File.dirname(path)
|
29
|
+
FileUtils.mkdir_p(File.join(@target_dir, dirname))
|
30
|
+
md5 = Digest::MD5.hexdigest(content)
|
31
|
+
new_file_name = "#{basename}.#{md5}#{extension}"
|
32
|
+
new_file_path = File.join(@target_dir, dirname, new_file_name)
|
33
|
+
File.open(new_file_path, 'w') { |f| f.write content }
|
34
|
+
FileUtils.rm(File.join(@target_dir, path)) unless keep_original
|
35
|
+
manifest_key_path = File.expand_path("/#{dirname}/#{basename}#{extension}")
|
36
|
+
effective_path = File.expand_path(@path_prefix + "/" + File.join(dirname, new_file_name))
|
37
|
+
@manifest[manifest_key_path] = effective_path
|
38
|
+
end
|
39
|
+
|
40
|
+
def manifest_path
|
41
|
+
File.join(@options[:source_dir], @manifest_name)
|
42
|
+
end
|
43
|
+
|
44
|
+
def run
|
45
|
+
combine_css
|
46
|
+
combine_js
|
47
|
+
version_files
|
48
|
+
rewrite_urls_in_css
|
49
|
+
compress_css
|
50
|
+
to_manifest(@stylesheet_path, false)
|
51
|
+
compress_js
|
52
|
+
to_manifest(@javascript_path, false)
|
53
|
+
generate_and_version_cache_manifest
|
54
|
+
write_manifest
|
55
|
+
end
|
56
|
+
|
57
|
+
def write_manifest
|
58
|
+
File.open(manifest_path, 'w') do |f|
|
59
|
+
f.write JSON.pretty_generate(@manifest)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def version_files
|
64
|
+
FileUtils.cd(@source_dir) do
|
65
|
+
Dir["**/*"].reject{ |f| f =~ /\.(css|js)$/ }.each do |path|
|
66
|
+
if File.directory? path
|
67
|
+
FileUtils.mkdir_p(File.join(@target_dir, path))
|
68
|
+
next
|
69
|
+
end
|
70
|
+
FileUtils.cp(path, File.join(@target_dir, path))
|
71
|
+
to_manifest(path, false)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def combine_css
|
77
|
+
combine_files(@stylesheets, @stylesheet_path)
|
78
|
+
end
|
79
|
+
|
80
|
+
def rewrite_urls_in_css
|
81
|
+
url_regex = /(^|[{;])(.*?url\(\s*['"]?)(.*?)(['"]?\s*\).*?)([;}]|$)/ui
|
82
|
+
behavior_regex = /behavior:\s*url/ui
|
83
|
+
data_regex = /^\s*data:/ui
|
84
|
+
input = File.open(File.join(@target_dir, @stylesheet_path)){|f| f.read}
|
85
|
+
output = input.gsub(url_regex) do |full_match|
|
86
|
+
pre, url_match, post = ($1 + $2), $3, ($4 + $5)
|
87
|
+
if behavior_regex.match(pre) || data_regex.match(url_match)
|
88
|
+
full_match
|
89
|
+
else
|
90
|
+
path = Addressable::URI.parse("/") + url_match
|
91
|
+
target_url = @manifest[path.to_s]
|
92
|
+
if target_url
|
93
|
+
pre + target_url + post
|
94
|
+
else
|
95
|
+
full_match
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
File.open(File.join(@target_dir, @stylesheet_path), 'w') do |f|
|
100
|
+
f.write output
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def compress_css
|
105
|
+
css = File.open(File.join(@target_dir, @stylesheet_path)){|f| f.read}
|
106
|
+
compressed = Rainpress.compress(css)
|
107
|
+
File.open(File.join(@target_dir, @stylesheet_path), 'w') do |f|
|
108
|
+
f.write compressed
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def combine_js
|
113
|
+
combine_files(@javascripts, @javascript_path)
|
114
|
+
end
|
115
|
+
|
116
|
+
def compress_js
|
117
|
+
javascript = File.open(File.join(@target_dir, @javascript_path)){|f| f.read}
|
118
|
+
compressed = Uglifier.compile(javascript)
|
119
|
+
File.open(File.join(@target_dir, @javascript_path), 'w'){|f| f.write compressed}
|
120
|
+
end
|
121
|
+
|
122
|
+
def generate_and_version_cache_manifest
|
123
|
+
File.open(File.join(@target_dir, 'cache.manifest'), 'w') do |f|
|
124
|
+
f.puts 'CACHE MANIFEST'
|
125
|
+
f.puts ''
|
126
|
+
f.puts '# Explicitely cached entries'
|
127
|
+
f.puts @manifest.values.join("\n")
|
128
|
+
f.puts ''
|
129
|
+
f.puts 'NETWORK:'
|
130
|
+
f.puts '*'
|
131
|
+
end
|
132
|
+
to_manifest('cache.manifest')
|
133
|
+
end
|
134
|
+
|
135
|
+
private
|
136
|
+
|
137
|
+
def combine_files(files, path)
|
138
|
+
output = ''
|
139
|
+
FileUtils.mkdir_p(File.join(@target_dir, File.dirname(path)))
|
140
|
+
target_path = File.join(@target_dir, path)
|
141
|
+
files.each do |file|
|
142
|
+
output << File.open(File.join(@source_dir, file)) { |f| f.read }
|
143
|
+
output << "\n"
|
144
|
+
end
|
145
|
+
File.open(target_path, "w") { |f| f.write(output) }
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
data/lib/bagger.rb
ADDED
data/test/bagger_test.rb
ADDED
@@ -0,0 +1,265 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
require 'test_helper'
|
3
|
+
|
4
|
+
class BaggerTest < Test::Unit::TestCase
|
5
|
+
|
6
|
+
def setup
|
7
|
+
@source_dir = Dir.mktmpdir
|
8
|
+
@target_dir = Dir.mktmpdir
|
9
|
+
Uglifier.stubs(:compile).returns('//minfied js');
|
10
|
+
end
|
11
|
+
|
12
|
+
def teardown
|
13
|
+
FileUtils.remove_entry_secure @source_dir
|
14
|
+
FileUtils.remove_entry_secure @target_dir
|
15
|
+
end
|
16
|
+
|
17
|
+
def write_file(path, content)
|
18
|
+
File.open(path, 'w') do |f|
|
19
|
+
f.write content
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def default_options
|
24
|
+
{
|
25
|
+
:source_dir => @source_dir,
|
26
|
+
:target_dir => @target_dir,
|
27
|
+
}
|
28
|
+
end
|
29
|
+
|
30
|
+
def manifest
|
31
|
+
path = File.join(@source_dir, 'manifest.json')
|
32
|
+
json = File.open(path){|f| f.read}
|
33
|
+
JSON.parse(json)
|
34
|
+
end
|
35
|
+
|
36
|
+
context 'manifest' do
|
37
|
+
should 'generate one' do
|
38
|
+
Bagger.bagit!(default_options)
|
39
|
+
assert File.exists?(File.join(@source_dir, 'manifest.json')), 'manifest was not created'
|
40
|
+
end
|
41
|
+
|
42
|
+
should 'version files with md5' do
|
43
|
+
test_content = 'testcontent'
|
44
|
+
write_file(File.join(@source_dir, 'test.txt'), test_content)
|
45
|
+
Bagger.bagit!(default_options)
|
46
|
+
md5 = Digest::MD5.hexdigest(test_content)
|
47
|
+
assert_equal md5, manifest['/test.txt'].split('.')[1]
|
48
|
+
end
|
49
|
+
|
50
|
+
should 'copy over the versioned files' do
|
51
|
+
test_content = 'testcontent'
|
52
|
+
write_file(File.join(@source_dir, 'test.txt'), test_content)
|
53
|
+
Bagger.bagit!(default_options)
|
54
|
+
assert File.exists?(File.join(@target_dir, manifest['/test.txt']))
|
55
|
+
end
|
56
|
+
|
57
|
+
should 'support a path prefix' do
|
58
|
+
test_content = 'testcontent'
|
59
|
+
write_file(File.join(@source_dir, 'test.txt'), test_content)
|
60
|
+
Bagger.bagit!(default_options.merge(:path_prefix => '/path_prefix'))
|
61
|
+
assert_match /\/path_prefix\/test\..*\.txt/, manifest['/test.txt']
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
context 'html 5 cache manifest' do
|
66
|
+
should 'generate one' do
|
67
|
+
Bagger.bagit!(default_options)
|
68
|
+
expected_path = File.join(@target_dir, 'cache.manifest')
|
69
|
+
assert File.exists?(expected_path), 'cache manifest not found'
|
70
|
+
end
|
71
|
+
|
72
|
+
should 'add the cache manifest to the manifest' do
|
73
|
+
Bagger.bagit!(default_options)
|
74
|
+
assert_match /\/cache\..*\.manifest/, manifest['/cache.manifest']
|
75
|
+
end
|
76
|
+
|
77
|
+
should 'create a versioned cache manifest' do
|
78
|
+
Bagger.bagit!(default_options)
|
79
|
+
expected_path = File.join(@target_dir, manifest['/cache.manifest'])
|
80
|
+
assert File.exists?(expected_path), 'versioned cache manifest not found'
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
context 'css files' do
|
85
|
+
setup do
|
86
|
+
@config = {
|
87
|
+
:stylesheets => [],
|
88
|
+
:stylesheet_path => 'css/combined.css'
|
89
|
+
}
|
90
|
+
@css_dir = File.join(@source_dir, 'css')
|
91
|
+
FileUtils.mkdir_p(@css_dir)
|
92
|
+
%w(one two).each do |file|
|
93
|
+
write_file(
|
94
|
+
File.join(@css_dir, "#{file}.css"),
|
95
|
+
".#{file}{}"
|
96
|
+
)
|
97
|
+
@config[:stylesheets] << "css/#{file}.css"
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
should 'add it to the manifest' do
|
102
|
+
Bagger.bagit!(
|
103
|
+
:source_dir => @source_dir,
|
104
|
+
:target_dir => @target_dir,
|
105
|
+
:combine => @config
|
106
|
+
)
|
107
|
+
|
108
|
+
assert manifest['/css/combined.css']
|
109
|
+
end
|
110
|
+
|
111
|
+
should 'combine it' do
|
112
|
+
Bagger.bagit!(
|
113
|
+
:source_dir => @source_dir,
|
114
|
+
:target_dir => @target_dir,
|
115
|
+
:combine => @config
|
116
|
+
)
|
117
|
+
expected_file_path = File.join(@target_dir, manifest['/css/combined.css'])
|
118
|
+
assert File.exists?(expected_file_path), 'combined css not found'
|
119
|
+
end
|
120
|
+
|
121
|
+
should 'only copy over the generate files' do
|
122
|
+
Bagger.bagit!(
|
123
|
+
:source_dir => @source_dir,
|
124
|
+
:target_dir => @target_dir,
|
125
|
+
:combine => @config
|
126
|
+
)
|
127
|
+
assert !File.exists?(File.join(@target_dir, 'css', 'one.css'))
|
128
|
+
end
|
129
|
+
|
130
|
+
should 'compress it' do
|
131
|
+
Rainpress.stubs(:compress).returns('//super minified css');
|
132
|
+
Bagger.bagit!(
|
133
|
+
:source_dir => @source_dir,
|
134
|
+
:target_dir => @target_dir,
|
135
|
+
:combine => @config
|
136
|
+
)
|
137
|
+
expected_file_path = File.join(@target_dir, manifest['/css/combined.css'])
|
138
|
+
compressed_content = File.open(expected_file_path){|f| f.read}
|
139
|
+
assert_equal '//super minified css', compressed_content , 'combined css not found'
|
140
|
+
end
|
141
|
+
|
142
|
+
context 'url rewriting' do
|
143
|
+
setup do
|
144
|
+
css = <<-EOF
|
145
|
+
#documentRootBasedUrl {
|
146
|
+
background: url("/images/root.png") top center;
|
147
|
+
}
|
148
|
+
#relativeUrl {
|
149
|
+
background: url("../images/relative.png") top center;
|
150
|
+
}
|
151
|
+
#absoluteUrl {
|
152
|
+
background: url('http://localhost/absolute.png') top center;
|
153
|
+
}
|
154
|
+
EOF
|
155
|
+
write_file(File.join(@css_dir, "urled.css"), css)
|
156
|
+
@config[:stylesheets] << 'css/urled.css'
|
157
|
+
FileUtils.mkdir_p(File.join(@source_dir, 'images'))
|
158
|
+
%w(root relative absolute).each do |type|
|
159
|
+
FileUtils.touch(File.join(@source_dir, 'images', "#{type}.png"))
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
should 'rewrite document root based urls' do
|
164
|
+
Bagger.bagit!(
|
165
|
+
:source_dir => @source_dir,
|
166
|
+
:target_dir => @target_dir,
|
167
|
+
:combine => @config
|
168
|
+
)
|
169
|
+
combined_css = File.open(File.join(@target_dir, manifest['/css/combined.css'])){|f| f.read}
|
170
|
+
assert combined_css.include?(manifest['/images/root.png'])
|
171
|
+
end
|
172
|
+
|
173
|
+
should 'rewrite relative (anchored by the css file) urls to absolute paths' do
|
174
|
+
Bagger.bagit!(
|
175
|
+
:source_dir => @source_dir,
|
176
|
+
:target_dir => @target_dir,
|
177
|
+
:combine => @config
|
178
|
+
)
|
179
|
+
combined_css = File.open(File.join(@target_dir, manifest['/css/combined.css'])){|f| f.read}
|
180
|
+
assert combined_css.include?(manifest['/images/relative.png'])
|
181
|
+
end
|
182
|
+
|
183
|
+
should 'not rewrite absolute urls' do
|
184
|
+
Bagger.bagit!(
|
185
|
+
:source_dir => @source_dir,
|
186
|
+
:target_dir => @target_dir,
|
187
|
+
:combine => @config
|
188
|
+
)
|
189
|
+
combined_css = File.open(File.join(@target_dir, manifest['/css/combined.css'])){|f| f.read}
|
190
|
+
assert combined_css.include?('http://localhost/absolute.png')
|
191
|
+
end
|
192
|
+
|
193
|
+
should 'support a path prefix' do
|
194
|
+
Bagger.bagit!(
|
195
|
+
:source_dir => @source_dir,
|
196
|
+
:target_dir => @target_dir,
|
197
|
+
:path_prefix => '/path_prefix',
|
198
|
+
:combine => @config
|
199
|
+
)
|
200
|
+
combined_css_path = manifest['/css/combined.css'].gsub(/path_prefix/,'')
|
201
|
+
combined_css = File.open(File.join(@target_dir, combined_css_path)){|f| f.read}
|
202
|
+
assert_match /\/path_prefix\/images\/relative\..*\.png/, combined_css
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
context 'combine javascript' do
|
208
|
+
setup do
|
209
|
+
@config = {
|
210
|
+
:javascripts => [],
|
211
|
+
:javascript_path => 'js/combined.js'
|
212
|
+
}
|
213
|
+
@js_dir = File.join(@source_dir, 'js')
|
214
|
+
FileUtils.mkdir_p(@js_dir)
|
215
|
+
%w(one two).each do |file|
|
216
|
+
write_file(
|
217
|
+
File.join(@js_dir, "#{file}.js"),
|
218
|
+
"var #{file} = 1;"
|
219
|
+
)
|
220
|
+
@config[:javascripts] << "js/#{file}.js"
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
should 'add it to the manifest' do
|
225
|
+
Bagger.bagit!(
|
226
|
+
:source_dir => @source_dir,
|
227
|
+
:target_dir => @target_dir,
|
228
|
+
:combine => @config
|
229
|
+
)
|
230
|
+
assert manifest['/js/combined.js']
|
231
|
+
end
|
232
|
+
|
233
|
+
should 'combine it' do
|
234
|
+
Bagger.bagit!(
|
235
|
+
:source_dir => @source_dir,
|
236
|
+
:target_dir => @target_dir,
|
237
|
+
:combine => @config
|
238
|
+
)
|
239
|
+
expected_file_path = File.join(@target_dir, manifest['/js/combined.js'])
|
240
|
+
assert File.exists?(expected_file_path), 'combined js not found'
|
241
|
+
end
|
242
|
+
|
243
|
+
should 'only copy over the generate files' do
|
244
|
+
Bagger.bagit!(
|
245
|
+
:source_dir => @source_dir,
|
246
|
+
:target_dir => @target_dir,
|
247
|
+
:combine => @config
|
248
|
+
)
|
249
|
+
assert !File.exists?(File.join(@target_dir, 'js', 'one.js'))
|
250
|
+
end
|
251
|
+
|
252
|
+
should 'compress the javascript' do
|
253
|
+
expected_path = File.join(@target_dir, 'js', 'combined.js')
|
254
|
+
Uglifier.expects(:compile).returns('//minified javascript')
|
255
|
+
|
256
|
+
Bagger.bagit!(
|
257
|
+
:source_dir => @source_dir,
|
258
|
+
:target_dir => @target_dir,
|
259
|
+
:combine => @config
|
260
|
+
)
|
261
|
+
expected_file_path = File.join(@target_dir, manifest['/js/combined.js'])
|
262
|
+
assert_equal '//minified javascript', File.open(expected_file_path){|f| f.read}
|
263
|
+
end
|
264
|
+
end
|
265
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
$LOAD_PATH.unshift( File.join( File.dirname(__FILE__), "..", "lib") )
|
2
|
+
|
3
|
+
require "rubygems"
|
4
|
+
require 'test/unit'
|
5
|
+
require 'mocha'
|
6
|
+
require 'shoulda-context'
|
7
|
+
require 'bagger'
|
8
|
+
require 'fileutils'
|
9
|
+
|
10
|
+
TEST_TEMP_DIR = File.expand_path(File.join(File.dirname(__FILE__), '..', 'tmp'))
|
11
|
+
|
data/tests.watchr
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
# Run me with:
|
2
|
+
# $ watchr specs.watchr
|
3
|
+
|
4
|
+
# --------------------------------------------------
|
5
|
+
# Rules
|
6
|
+
# --------------------------------------------------
|
7
|
+
watch( '^test.*/test_.*\.rb' ) { |m| ruby m[0] }
|
8
|
+
watch( '^lib/(.*)\.rb' ) { |m| ruby "test/#{m[1]}_test.rb" }
|
9
|
+
watch( '^test/test_helper\.rb' ) { ruby tests }
|
10
|
+
watch( '^test/bagger_test\.rb' ) { ruby tests }
|
11
|
+
watch( '^lib/bagger\.rb' ) { ruby tests }
|
12
|
+
|
13
|
+
|
14
|
+
# --------------------------------------------------
|
15
|
+
# Signal Handling
|
16
|
+
# --------------------------------------------------
|
17
|
+
Signal.trap('QUIT') { ruby tests } # Ctrl-\
|
18
|
+
Signal.trap('INT' ) { abort("\n") } # Ctrl-C
|
19
|
+
|
20
|
+
# --------------------------------------------------
|
21
|
+
# Helpers
|
22
|
+
# --------------------------------------------------
|
23
|
+
def ruby(*paths)
|
24
|
+
run "ruby #{gem_opt} -I.:lib:test -e'%w( #{paths.flatten.join(' ')} ).each {|p| require p }'"
|
25
|
+
end
|
26
|
+
|
27
|
+
def tests
|
28
|
+
Dir['test/**/test_*.rb'] - ['test/test_helper.rb']
|
29
|
+
end
|
30
|
+
|
31
|
+
def run( cmd )
|
32
|
+
puts cmd
|
33
|
+
system cmd
|
34
|
+
end
|
35
|
+
|
36
|
+
def gem_opt
|
37
|
+
defined?(Gem) ? "-rubygems" : ""
|
38
|
+
end
|
metadata
ADDED
@@ -0,0 +1,137 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: bagger
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Patrick Huesler
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2011-08-09 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: json
|
16
|
+
requirement: &70307486940240 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *70307486940240
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: addressable
|
27
|
+
requirement: &70307486939720 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
33
|
+
type: :runtime
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *70307486939720
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: uglifier
|
38
|
+
requirement: &70307486939180 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
44
|
+
type: :runtime
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *70307486939180
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: rainpress
|
49
|
+
requirement: &70307486938540 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
type: :runtime
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *70307486938540
|
58
|
+
- !ruby/object:Gem::Dependency
|
59
|
+
name: rake
|
60
|
+
requirement: &70307486938000 !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ! '>='
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: '0'
|
66
|
+
type: :development
|
67
|
+
prerelease: false
|
68
|
+
version_requirements: *70307486938000
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: shoulda-context
|
71
|
+
requirement: &70307486937460 !ruby/object:Gem::Requirement
|
72
|
+
none: false
|
73
|
+
requirements:
|
74
|
+
- - ! '>='
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '0'
|
77
|
+
type: :development
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: *70307486937460
|
80
|
+
- !ruby/object:Gem::Dependency
|
81
|
+
name: mocha
|
82
|
+
requirement: &70307486936940 !ruby/object:Gem::Requirement
|
83
|
+
none: false
|
84
|
+
requirements:
|
85
|
+
- - ! '>='
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: '0'
|
88
|
+
type: :development
|
89
|
+
prerelease: false
|
90
|
+
version_requirements: *70307486936940
|
91
|
+
description: ! 'A framework agnostic packaging solution for your assets: version files,
|
92
|
+
combine them, minify them and create a manifest'
|
93
|
+
email:
|
94
|
+
- patrick.huesler@gmail.com
|
95
|
+
executables: []
|
96
|
+
extensions: []
|
97
|
+
extra_rdoc_files: []
|
98
|
+
files:
|
99
|
+
- .gitignore
|
100
|
+
- .travis.yml
|
101
|
+
- Gemfile
|
102
|
+
- README.md
|
103
|
+
- Rakefile
|
104
|
+
- bagger.gemspec
|
105
|
+
- lib/bagger.rb
|
106
|
+
- lib/bagger/packager.rb
|
107
|
+
- lib/bagger/version.rb
|
108
|
+
- test/bagger_test.rb
|
109
|
+
- test/test_helper.rb
|
110
|
+
- tests.watchr
|
111
|
+
homepage: ''
|
112
|
+
licenses: []
|
113
|
+
post_install_message:
|
114
|
+
rdoc_options: []
|
115
|
+
require_paths:
|
116
|
+
- lib
|
117
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
118
|
+
none: false
|
119
|
+
requirements:
|
120
|
+
- - ! '>='
|
121
|
+
- !ruby/object:Gem::Version
|
122
|
+
version: '0'
|
123
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
124
|
+
none: false
|
125
|
+
requirements:
|
126
|
+
- - ! '>='
|
127
|
+
- !ruby/object:Gem::Version
|
128
|
+
version: '0'
|
129
|
+
requirements: []
|
130
|
+
rubyforge_project: bagger
|
131
|
+
rubygems_version: 1.8.6
|
132
|
+
signing_key:
|
133
|
+
specification_version: 3
|
134
|
+
summary: Asset packaging for the rest of us
|
135
|
+
test_files:
|
136
|
+
- test/bagger_test.rb
|
137
|
+
- test/test_helper.rb
|