lash 0.1.1 → 1.0.1
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/.autotest +10 -0
- data/.gitignore +2 -1
- data/.rspec +1 -0
- data/Gemfile +2 -1
- data/LICENSE.md +48 -0
- data/README.md +117 -5
- data/Rakefile +1 -0
- data/lib/lash.rb +17 -4
- data/lib/lash/assets_host.rb +74 -0
- data/lib/lash/bundle_helper.rb +6 -24
- data/lib/lash/capistrano.rb +2 -0
- data/lib/lash/closure_minifier.rb +20 -0
- data/lib/lash/files.rb +56 -0
- data/lib/lash/java_script_bundler.rb +117 -0
- data/lib/lash/java_script_minifier.rb +67 -0
- data/lib/lash/railtie.rb +4 -33
- data/lib/lash/sprite_bundler.rb +132 -0
- data/lib/lash/tasks/lash.rake +50 -181
- data/lib/lash/version.rb +1 -1
- data/spec/lib/assets_host_spec.rb +56 -0
- data/spec/lib/bundle_helper_spec.rb +99 -0
- data/spec/lib/closure_minifier_spec.rb +67 -0
- data/spec/lib/java_script_bundler_spec.rb +46 -0
- data/spec/lib/lash_files_spec.rb +68 -0
- data/spec/spec_helper.rb +15 -25
- data/spec/support/rails_fake.rb +31 -0
- data/spec/test_app/.gitignore +4 -0
- data/spec/test_app/Rakefile +8 -0
- data/spec/test_app/public/images/rails.png +0 -0
- data/spec/test_app/public/images/ui-sprite.png +0 -0
- data/spec/test_app/public/images/ui-sprite.png.sprite +3 -0
- data/spec/test_app/public/javascripts/application/README +0 -0
- data/spec/test_app/public/javascripts/application/application.bundleVersion.js +1 -0
- data/spec/test_app/public/javascripts/application/application.js +3 -0
- data/spec/test_app/public/javascripts/application/application2.js +3 -0
- data/spec/test_app/public/javascripts/application/tools/validate.js +3 -0
- data/spec/test_app/public/javascripts/bundle_application.js +1 -0
- data/spec/test_app/public/javascripts/bundle_application.js.gz +0 -0
- data/spec/test_app/public/javascripts/cdn/jquery.js +1 -0
- data/spec/test_app/public/javascripts/cdn/jquery.js.gz +0 -0
- data/spec/test_app/public/javascripts/cdn/jquery.min.js +1 -0
- data/spec/test_app/public/javascripts/cdn/jquery.min.js.gz +0 -0
- data/spec/test_app/public/javascripts/demand/huge.js +0 -0
- data/spec/test_app/public/javascripts/demand/huge.js.gz +0 -0
- data/spec/test_app/public/javascripts/demand/huge.min.js +1 -0
- data/spec/test_app/public/javascripts/demand/huge.min.js.gz +0 -0
- data/spec/test_app/public/sprites/ui/accept.png +0 -0
- data/spec/test_app/public/sprites/ui/add.png +0 -0
- data/spec/test_app/public/stylesheets/.gitkeep +0 -0
- data/spec/test_app/public/stylesheets/sass/_ui-sprite.scss +20 -0
- data/spec/test_app/public/stylesheets/sass/_version.scss +1 -0
- metadata +81 -10
data/lib/lash/version.rb
CHANGED
@@ -0,0 +1,56 @@
|
|
1
|
+
require File.expand_path( '../../spec_helper.rb', __FILE__ )
|
2
|
+
require 'lash/assets_host'
|
3
|
+
|
4
|
+
describe Lash::AssetsHost do
|
5
|
+
|
6
|
+
|
7
|
+
context "asset_id" do
|
8
|
+
it "should use the git repo hash for the cachebusting id" do
|
9
|
+
Rails.root = File.expand_path( "../../../", __FILE__ )
|
10
|
+
Lash::AssetsHost.use_git_asset_id
|
11
|
+
ENV['RAILS_ASSET_ID'].should match /\A[a-f0-9]{40}\Z/
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
context "static assets server" do
|
16
|
+
before :each do
|
17
|
+
Lash.lash_options[:use_asset_servers] = true
|
18
|
+
@request = mock()
|
19
|
+
@request.stub("ssl?").and_return(false)
|
20
|
+
@request.stub("host_with_port").and_return("lvh.me")
|
21
|
+
end
|
22
|
+
|
23
|
+
|
24
|
+
it "should prepend and assets subdomain" do
|
25
|
+
Lash::AssetsHost.resolve_static_asset_server_for_source( "pickles", @request ) \
|
26
|
+
.should match %r{http://assets\d\.lvh\.me}
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should return nil when disabled" do
|
30
|
+
Lash.lash_options[:use_asset_servers] = false
|
31
|
+
Lash::AssetsHost.resolve_static_asset_server_for_source( "poodles", @request ) \
|
32
|
+
.should be_nil
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should use https protocol in ssl" do
|
36
|
+
@request.stub("ssl?").and_return(true)
|
37
|
+
Lash::AssetsHost.resolve_static_asset_server_for_source( "aligators", @request ) \
|
38
|
+
.should match %r{\Ahttps://}
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should return nil in ssl when disabled " do
|
42
|
+
@request.stub("ssl?").and_return(true)
|
43
|
+
Lash.lash_options[:use_asset_servers_in_ssl] = false
|
44
|
+
Lash::AssetsHost.resolve_static_asset_server_for_source( "aligators", @request ) \
|
45
|
+
.should be_nil
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should modify subdomain when more than 2 parts" do
|
49
|
+
@request.stub("host_with_port").and_return("mickey.mouse.com")
|
50
|
+
Lash::AssetsHost.resolve_static_asset_server_for_source( "pickles", @request ) \
|
51
|
+
.should match %r{http://mickey-assets\d\.mouse\.com}
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
require File.expand_path( '../../spec_helper', __FILE__ )
|
2
|
+
require 'lash/bundle_helper'
|
3
|
+
|
4
|
+
|
5
|
+
class BH
|
6
|
+
include Lash::BundleHelper
|
7
|
+
|
8
|
+
attr_accessor :params
|
9
|
+
attr_accessor :cookies
|
10
|
+
def initialize
|
11
|
+
@params = {}
|
12
|
+
@cookies = {}
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class String
|
17
|
+
def html_safe
|
18
|
+
self
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
|
23
|
+
describe Lash::BundleHelper do
|
24
|
+
|
25
|
+
before :each do
|
26
|
+
@fake = BH.new
|
27
|
+
Rails.root = File.expand_path( "../../test_app", __FILE__ )
|
28
|
+
end
|
29
|
+
|
30
|
+
context "bundle_files?" do
|
31
|
+
context "in development" do
|
32
|
+
before :each do
|
33
|
+
Rails.env = :development
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should be false" do
|
37
|
+
@fake.bundle_files?.should == false
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should be true if params includes bundle=yes" do
|
41
|
+
@fake.params[:bundle] = "yes"
|
42
|
+
@fake.bundle_files?.should == true
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
context "in production" do
|
48
|
+
before :each do
|
49
|
+
Rails.env = :production
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should be true" do
|
53
|
+
@fake.bundle_files?.should == true
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should be false if params includes bundle=no in production" do
|
57
|
+
@fake.params[:bundle] = "no"
|
58
|
+
@fake.bundle_files?.should == false
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
|
65
|
+
|
66
|
+
context "javascript_bundle" do
|
67
|
+
|
68
|
+
before :each do
|
69
|
+
@fake.stub( :javascript_src_tag ).and_return {|f| "%#{f}%" }
|
70
|
+
end
|
71
|
+
|
72
|
+
|
73
|
+
context "when bundle_files? is true" do
|
74
|
+
before :each do
|
75
|
+
Rails.env = :production
|
76
|
+
end
|
77
|
+
|
78
|
+
it "should return bundle_application.js" do
|
79
|
+
script = @fake.javascript_bundle( "application" )
|
80
|
+
script.should =~ /%bundle_application.js%/
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
context "when bundle_files? is false" do
|
85
|
+
before :each do
|
86
|
+
Rails.env = :development
|
87
|
+
end
|
88
|
+
|
89
|
+
it "should return application, application2 and validate scripts" do
|
90
|
+
script = @fake.javascript_bundle( "application" )
|
91
|
+
%w{ application application2 tools/validate }.each do |s|
|
92
|
+
script.should match %r{application/#{s}.js}
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require File.expand_path( '../../spec_helper', __FILE__ )
|
2
|
+
require 'lash/files'
|
3
|
+
require 'lash/closure_minifier'
|
4
|
+
require 'fileutils'
|
5
|
+
|
6
|
+
describe Lash::ClosureMinifier, :slow => true do
|
7
|
+
|
8
|
+
before :each do
|
9
|
+
@minifier = Lash::ClosureMinifier.new
|
10
|
+
@target = File.join( TMP_ROOT, 'tmp.js' )
|
11
|
+
@application_scripts = Lash::Files.recursive_file_list( File.join( JAVASCRIPTS_ROOT, 'application' ), 'js' )
|
12
|
+
|
13
|
+
File.delete @target if File.exist? @target
|
14
|
+
File.delete "#{@target}.gz" if File.exist? "#{@target}.gz"
|
15
|
+
|
16
|
+
@result = @minifier.minify( @application_scripts, @target )
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should create output directory when it doesn't exist" do
|
20
|
+
outdir = File.dirname( @target )
|
21
|
+
FileUtils.remove_dir outdir, true
|
22
|
+
@minifier.minify( @application_scripts, @target )
|
23
|
+
File.exist?( outdir ).should be_true
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should not fail" do
|
27
|
+
@result.should be_true
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should minify to target folder" do
|
31
|
+
File.exist?( @target ).should be_true
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should be smaller than the original files" do
|
35
|
+
size = @application_scripts.inject(0) { |n,s| n = n + File.size( s ) }
|
36
|
+
File.size( @target ).should < size
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should not be zero length file" do
|
40
|
+
File.size( @target ).should > 0
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should create a gzippped companion file" do
|
44
|
+
File.exist?(@target + '.gz').should be_true
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should join compiler options" do
|
48
|
+
@minifier.options = {
|
49
|
+
:one => "1",
|
50
|
+
"--open" => "two",
|
51
|
+
"--on" => nil
|
52
|
+
}
|
53
|
+
|
54
|
+
@minifier.send( :compiler_options ).should == "one 1 --open two --on"
|
55
|
+
end
|
56
|
+
|
57
|
+
it "should fail when it contains invalid javascript" do
|
58
|
+
invalid = File.join( TMP_ROOT, "invalid.js" )
|
59
|
+
File.open( invalid, "w+" ) do |f|
|
60
|
+
f.write( "I don't make any sense")
|
61
|
+
end
|
62
|
+
|
63
|
+
@application_scripts << invalid
|
64
|
+
@minifier.minify( @application_scripts, @target ).should be_false
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require File.expand_path( '../../spec_helper.rb', __FILE__ )
|
2
|
+
require 'lash/files'
|
3
|
+
require 'lash/java_script_minifier'
|
4
|
+
require 'lash/java_script_bundler'
|
5
|
+
|
6
|
+
|
7
|
+
class SimpleMinifier < Lash::JavaScriptMinifier
|
8
|
+
end
|
9
|
+
|
10
|
+
describe Lash::JavaScriptBundler do
|
11
|
+
|
12
|
+
before :each do
|
13
|
+
Rails.root = RAILS_ROOT
|
14
|
+
@bundler = Lash::JavaScriptBundler.new( :minifiers => SimpleMinifier.new )
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should bundle into a single file :style => :single" do
|
18
|
+
@bundler.stub(:migrate_best_target)
|
19
|
+
@bundler.should_receive( :bundle_scripts_with_minifier ).once \
|
20
|
+
.and_return { |f| File.open( f.first + '.tmp', "w+" ) { |s| s.write( f ) }; "#{f.first}.tmp" }
|
21
|
+
@bundler.bundle 'application', :style => :single
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should bundle individual files when :style => :individual" do
|
25
|
+
@bundler.stub(:migrate_best_target)
|
26
|
+
@bundler.should_receive( :bundle_scripts_with_minifier ).at_least(3).times \
|
27
|
+
.and_return { |f| File.open( f.first + '.tmp', "w+" ) { |s| s.write( f ) }; "#{f.first}.tmp" }
|
28
|
+
@bundler.bundle 'application', :style => :individual
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should use single style for directories that are not included in cdn_dirs and demand_dirs" do
|
32
|
+
@bundler.should_receive(:bundle_into_single_script)
|
33
|
+
@bundler.bundle "application"
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should use individual style for directories that are not included in cdn_dirs" do
|
37
|
+
@bundler.should_receive(:bundle_individual_scripts)
|
38
|
+
@bundler.bundle "cdn"
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should use individual style for directories that are not included in demand_dirs" do
|
42
|
+
@bundler.should_receive(:bundle_individual_scripts)
|
43
|
+
@bundler.bundle "demand"
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require File.expand_path( '../../spec_helper.rb', __FILE__ )
|
2
|
+
require 'lash/files'
|
3
|
+
|
4
|
+
describe Lash::Files do
|
5
|
+
|
6
|
+
context "recursive_file_list" do
|
7
|
+
|
8
|
+
it "should find files with extension including a leading period" do
|
9
|
+
Lash::Files.recursive_file_list( File.join( JAVASCRIPTS_ROOT, 'application' ), '.js' ) \
|
10
|
+
.count.should > 0
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should find files with extension without a leading period" do
|
14
|
+
Lash::Files.recursive_file_list( File.join( JAVASCRIPTS_ROOT, 'application' ), 'js' ) \
|
15
|
+
.count.should > 0
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should find files without an extension" do
|
19
|
+
Lash::Files.recursive_file_list( File.join( JAVASCRIPTS_ROOT, 'application' ), nil ) \
|
20
|
+
.count.should > 0
|
21
|
+
end
|
22
|
+
|
23
|
+
context "javascripts/application" do
|
24
|
+
|
25
|
+
before :each do
|
26
|
+
@files = Lash::Files.recursive_file_list File.join( JAVASCRIPTS_ROOT, 'application' ), '.js'
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should find at least 3 files" do
|
30
|
+
@files.count.should >= 3
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should include all files in application folder" do
|
34
|
+
%w{ application.js application2.js tools/validate.js }.each do |f|
|
35
|
+
@files.should include( File.join( JAVASCRIPTS_ROOT, 'application', f ) )
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should not include README" do
|
40
|
+
%w{ README }.each do |f|
|
41
|
+
@files.should_not include( File.join( JAVASCRIPTS_ROOT, 'application', f ) )
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
context "get_top_level_directories" do
|
48
|
+
|
49
|
+
before :each do
|
50
|
+
@dirs = Lash::Files.get_top_level_directories( JAVASCRIPTS_ROOT )
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should find application, cdn, demand" do
|
54
|
+
%w{ application cdn demand }.each do |f|
|
55
|
+
@dirs.should include( File.join( JAVASCRIPTS_ROOT, f ) )
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should not find application/tools" do
|
60
|
+
%w{ application/tools }.each do |f|
|
61
|
+
@dirs.should_not include( File.join( JAVASCRIPTS_ROOT, f ) )
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,29 +1,19 @@
|
|
1
|
-
$:.unshift File.
|
1
|
+
$:.unshift File.join( File.dirname( __FILE__ ), 'support' )
|
2
2
|
|
3
|
-
require '
|
3
|
+
require 'lash'
|
4
4
|
|
5
|
+
RAILS_ROOT = File.expand_path( '../test_app', __FILE__ )
|
6
|
+
PUBLIC_ROOT = File.join( RAILS_ROOT, 'public' )
|
7
|
+
JAVASCRIPTS_ROOT = File.join( PUBLIC_ROOT, 'javascripts' )
|
8
|
+
STYLESHEETS_ROOT = File.join( PUBLIC_ROOT, 'stylesheets' )
|
9
|
+
IMAGES_ROOT = File.join( PUBLIC_ROOT, 'images' )
|
10
|
+
TMP_ROOT = File.expand_path( "../../tmp", __FILE__ )
|
5
11
|
|
6
|
-
|
7
|
-
require 'ffaker'
|
12
|
+
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
|
8
13
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
# If you prefer to use mocha, flexmock or RR, uncomment the appropriate line:
|
16
|
-
#
|
17
|
-
# config.mock_with :mocha
|
18
|
-
# config.mock_with :flexmock
|
19
|
-
# config.mock_with :rr
|
20
|
-
config.mock_with :rspec
|
21
|
-
|
22
|
-
# Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
|
23
|
-
# config.fixture_path = "#{::Rails.root}/spec/fixtures"
|
24
|
-
|
25
|
-
# If you're not using ActiveRecord, or you'd prefer not to run each of your
|
26
|
-
# examples within a transaction, remove the following line or assign false
|
27
|
-
# instead of true.
|
28
|
-
config.use_transactional_fixtures = true
|
29
|
-
end
|
14
|
+
RSpec.configure do |c|
|
15
|
+
c.filter_run :focus => true
|
16
|
+
c.run_all_when_everything_filtered = true
|
17
|
+
# c.fail_fast = true
|
18
|
+
c.filter_run_excluding :slow => true
|
19
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'rspec'
|
2
|
+
require 'rspec/mocks'
|
3
|
+
|
4
|
+
class RailsFake
|
5
|
+
attr_accessor :env
|
6
|
+
attr_accessor :root
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@env = RSpec::Mocks::Mock.new
|
10
|
+
end
|
11
|
+
|
12
|
+
def env=(s)
|
13
|
+
%w{ production development test }.each do |e|
|
14
|
+
@env.stub("#{e}?").and_return( e == s.to_s )
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
class String
|
21
|
+
def html_safe
|
22
|
+
self
|
23
|
+
end
|
24
|
+
|
25
|
+
def parameterize
|
26
|
+
self
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
::Rails = ::RailsFake.new
|
@@ -0,0 +1,8 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require File.expand_path( "../../support/rails_fake.rb", __FILE__ )
|
3
|
+
Rails.root = File.expand_path( '..', __FILE__ )
|
4
|
+
require 'lash'
|
5
|
+
|
6
|
+
import File.expand_path( "../../../lib/lash/tasks/lash.rake", __FILE__ )
|
7
|
+
|
8
|
+
Lash.lash_options[:use_git_asset_id] = false
|
Binary file
|
Binary file
|