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.
Files changed (52) hide show
  1. data/.autotest +10 -0
  2. data/.gitignore +2 -1
  3. data/.rspec +1 -0
  4. data/Gemfile +2 -1
  5. data/LICENSE.md +48 -0
  6. data/README.md +117 -5
  7. data/Rakefile +1 -0
  8. data/lib/lash.rb +17 -4
  9. data/lib/lash/assets_host.rb +74 -0
  10. data/lib/lash/bundle_helper.rb +6 -24
  11. data/lib/lash/capistrano.rb +2 -0
  12. data/lib/lash/closure_minifier.rb +20 -0
  13. data/lib/lash/files.rb +56 -0
  14. data/lib/lash/java_script_bundler.rb +117 -0
  15. data/lib/lash/java_script_minifier.rb +67 -0
  16. data/lib/lash/railtie.rb +4 -33
  17. data/lib/lash/sprite_bundler.rb +132 -0
  18. data/lib/lash/tasks/lash.rake +50 -181
  19. data/lib/lash/version.rb +1 -1
  20. data/spec/lib/assets_host_spec.rb +56 -0
  21. data/spec/lib/bundle_helper_spec.rb +99 -0
  22. data/spec/lib/closure_minifier_spec.rb +67 -0
  23. data/spec/lib/java_script_bundler_spec.rb +46 -0
  24. data/spec/lib/lash_files_spec.rb +68 -0
  25. data/spec/spec_helper.rb +15 -25
  26. data/spec/support/rails_fake.rb +31 -0
  27. data/spec/test_app/.gitignore +4 -0
  28. data/spec/test_app/Rakefile +8 -0
  29. data/spec/test_app/public/images/rails.png +0 -0
  30. data/spec/test_app/public/images/ui-sprite.png +0 -0
  31. data/spec/test_app/public/images/ui-sprite.png.sprite +3 -0
  32. data/spec/test_app/public/javascripts/application/README +0 -0
  33. data/spec/test_app/public/javascripts/application/application.bundleVersion.js +1 -0
  34. data/spec/test_app/public/javascripts/application/application.js +3 -0
  35. data/spec/test_app/public/javascripts/application/application2.js +3 -0
  36. data/spec/test_app/public/javascripts/application/tools/validate.js +3 -0
  37. data/spec/test_app/public/javascripts/bundle_application.js +1 -0
  38. data/spec/test_app/public/javascripts/bundle_application.js.gz +0 -0
  39. data/spec/test_app/public/javascripts/cdn/jquery.js +1 -0
  40. data/spec/test_app/public/javascripts/cdn/jquery.js.gz +0 -0
  41. data/spec/test_app/public/javascripts/cdn/jquery.min.js +1 -0
  42. data/spec/test_app/public/javascripts/cdn/jquery.min.js.gz +0 -0
  43. data/spec/test_app/public/javascripts/demand/huge.js +0 -0
  44. data/spec/test_app/public/javascripts/demand/huge.js.gz +0 -0
  45. data/spec/test_app/public/javascripts/demand/huge.min.js +1 -0
  46. data/spec/test_app/public/javascripts/demand/huge.min.js.gz +0 -0
  47. data/spec/test_app/public/sprites/ui/accept.png +0 -0
  48. data/spec/test_app/public/sprites/ui/add.png +0 -0
  49. data/spec/test_app/public/stylesheets/.gitkeep +0 -0
  50. data/spec/test_app/public/stylesheets/sass/_ui-sprite.scss +20 -0
  51. data/spec/test_app/public/stylesheets/sass/_version.scss +1 -0
  52. metadata +81 -10
@@ -1,3 +1,3 @@
1
1
  module Lash
2
- VERSION = "0.1.1"
2
+ VERSION = "1.0.1"
3
3
  end
@@ -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
@@ -1,29 +1,19 @@
1
- $:.unshift File.expand_path( File.join( File.dirname( __FILE__ ), '..' ) )
1
+ $:.unshift File.join( File.dirname( __FILE__ ), 'support' )
2
2
 
3
- require 'rubygems'
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
- ENV["RAILS_ENV"] ||= 'test'
7
- require 'ffaker'
12
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
8
13
 
9
- Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}
10
- Dir[Rails.root.join("spec/factories/**/*.rb")].each { |f| require f }
11
-
12
- RSpec.configure do |config|
13
- # == Mock Framework
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,4 @@
1
+ .bundle
2
+ db/*.sqlite3
3
+ log/*.log
4
+ tmp/
@@ -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
@@ -0,0 +1,3 @@
1
+ 16 x 32
2
+ I public/sprites/ui/accept.png 0 0 16 16
3
+ I public/sprites/ui/add.png 0 16 16 16