Update to latest version of asset_packager plugin.

git-svn-id: http://www.rousette.org.uk/svn/tracks-repos/trunk@681 a4c988fc-2ded-0310-b66e-134b36920a42
This commit is contained in:
lukemelia 2007-12-10 20:04:28 +00:00
parent 00b9dd3292
commit 04f1bd87e7
12 changed files with 253 additions and 120 deletions

View file

@ -1,4 +1,51 @@
------------------------------------------------------------------------
r52 | sbecker | 2007-11-04 01:38:21 -0400 (Sun, 04 Nov 2007) | 3 lines
* Allow configuration of which environments the helpers should merge scripts with the Synthesis::AssetPackage.merge_environments variable.
* Refactored tests so they can all run together, and not depend on what the RAILS_ENV constant is.
* Only add file extension if it was explicitly passed in, fixes other helpers in rails.
------------------------------------------------------------------------
r51 | sbecker | 2007-10-26 16:24:48 -0400 (Fri, 26 Oct 2007) | 1 line
* Updated jsmin.rb to latest version from 2007-07-20
------------------------------------------------------------------------
r50 | sbecker | 2007-10-23 23:16:07 -0400 (Tue, 23 Oct 2007) | 1 line
Updated CHANGELOG
------------------------------------------------------------------------
r49 | sbecker | 2007-10-23 23:13:27 -0400 (Tue, 23 Oct 2007) | 1 line
* Finally committed the subdirectory patch. (Thanks James Coglan!)
------------------------------------------------------------------------
r48 | sbecker | 2007-10-15 15:10:43 -0400 (Mon, 15 Oct 2007) | 1 line
* Speed up rake tasks and remove rails environment dependencies
------------------------------------------------------------------------
r43 | sbecker | 2007-07-02 15:30:29 -0400 (Mon, 02 Jul 2007) | 1 line
* Updated the docs regarding testing.
------------------------------------------------------------------------
r42 | sbecker | 2007-07-02 15:27:00 -0400 (Mon, 02 Jul 2007) | 1 line
* For production helper test, build packages once - on first setup.
------------------------------------------------------------------------
r41 | sbecker | 2007-07-02 15:14:13 -0400 (Mon, 02 Jul 2007) | 1 line
* Put build_all in test setup and delete_all in test teardown so all tests will pass the on first run of test suite.
------------------------------------------------------------------------
r40 | sbecker | 2007-07-02 14:55:28 -0400 (Mon, 02 Jul 2007) | 1 line
* Fix quotes, add contact info
------------------------------------------------------------------------
r39 | sbecker | 2007-07-02 14:53:52 -0400 (Mon, 02 Jul 2007) | 1 line
* Add note on how to run the tests for asset packager.
------------------------------------------------------------------------
r38 | sbecker | 2007-01-25 15:36:42 -0500 (Thu, 25 Jan 2007) | 1 line
added CHANGELOG w/ subversion log entries
------------------------------------------------------------------------
r37 | sbecker | 2007-01-25 15:34:39 -0500 (Thu, 25 Jan 2007) | 1 line
updated jsmin with new version from 2007-01-23

View file

@ -152,20 +152,15 @@ All options for stylesheet_link_tag still work, so if you want to specify a diff
So you want to run the tests eh? Ok, then listen:
This plugin has a full suite of tests. But you've gotta follow a
certain procedure. If you do, all tests should pass. You cant run
them all at once (unfortunately) by running "rake" because the
tests depend on ENV['RAILS_ENV'] being different, and as far as I
know, this can't be changed in a running script once it is set. So,
we run them separately. Observe:
This plugin has a full suite of tests. But since they
depend on rails, it has to be run in the context of a
rails app, in the vendor/plugins directory. Observe:
> rails newtestapp
> cd newtestapp
> ./script/plugin install http://sbecker.net/shared/plugins/asset_packager
> cd vendor/plugins/asset_packager/test/
> ruby asset_packager_test.rb # all pass
> ruby asset_package_helper_development_test.rb # all pass
> ruby asset_package_helper_production_test.rb # all pass
> cd vendor/plugins/asset_packager/
> rake # all tests pass
== License
Copyright (c) 2006 Scott Becker - http://synthesis.sbecker.net

View file

@ -1,5 +1,5 @@
#!/usr/bin/ruby
# jsmin.rb 2007-01-23
# jsmin.rb 2007-07-20
# Author: Uladzislau Latynski
# This work is a translation from C to Ruby of jsmin.c published by
# Douglas Crockford. Permission is hereby granted to use the Ruby
@ -122,7 +122,9 @@ def action(a)
$theB = mynext
if ($theB == "/" && ($theA == "(" || $theA == "," || $theA == "=" ||
$theA == ":" || $theA == "[" || $theA == "!" ||
$theA == "&" || $theA == "|" || $theA == "?"))
$theA == "&" || $theA == "|" || $theA == "?" ||
$theA == "{" || $theA == "}" || $theA == ";" ||
$theA == "\n"))
$stdout.write $theA
$stdout.write $theB
while (true)
@ -180,7 +182,7 @@ def jsmin
end
when "\n"
case ($theA)
when "}","]",")","+","-","\"","\\"
when "}","]",")","+","-","\"","\\", "'", '"'
action(1)
else
if (isAlphanum($theA))
@ -196,4 +198,8 @@ def jsmin
end
end
ARGV.each do |anArg|
$stdout.write "// #{anArg}\n"
end
jsmin

View file

@ -1,86 +1,113 @@
module Synthesis
class AssetPackage
# class variables
@@asset_packages_yml = $asset_packages_yml ||
(File.exists?("#{RAILS_ROOT}/config/asset_packages.yml") ? YAML.load_file("#{RAILS_ROOT}/config/asset_packages.yml") : nil)
# singleton methods
def self.find_by_type(asset_type)
@@asset_packages_yml[asset_type].map { |p| self.new(asset_type, p) }
end
class << self
def merge_environments=(environments)
@@merge_environments = environments
end
def merge_environments
@@merge_environments ||= ["production"]
end
def parse_path(path)
/^(?:(.*)\/)?([^\/]+)$/.match(path).to_a
end
def self.find_by_target(asset_type, target)
package_hash = @@asset_packages_yml[asset_type].find {|p| p.keys.first == target }
package_hash ? self.new(asset_type, package_hash) : nil
end
def self.find_by_source(asset_type, source)
package_hash = @@asset_packages_yml[asset_type].find {|p| p[p.keys.first].include?(source) }
package_hash ? self.new(asset_type, package_hash) : nil
end
def self.targets_from_sources(asset_type, sources)
package_names = Array.new
sources.each do |source|
package = find_by_target(asset_type, source) || find_by_source(asset_type, source)
package_names << (package ? package.current_file : source)
def find_by_type(asset_type)
@@asset_packages_yml[asset_type].map { |p| self.new(asset_type, p) }
end
package_names.uniq
end
def self.sources_from_targets(asset_type, targets)
source_names = Array.new
targets.each do |target|
package = find_by_target(asset_type, target)
source_names += (package ? package.sources : target.to_a)
end
source_names.uniq
end
def self.build_all
@@asset_packages_yml.keys.each do |asset_type|
@@asset_packages_yml[asset_type].each { |p| self.new(asset_type, p).build }
end
end
def self.delete_all
@@asset_packages_yml.keys.each do |asset_type|
@@asset_packages_yml[asset_type].each { |p| self.new(asset_type, p).delete_all_builds }
end
end
def self.create_yml
unless File.exists?("#{RAILS_ROOT}/config/asset_packages.yml")
asset_yml = Hash.new
asset_yml['javascripts'] = [{"base" => build_file_list("#{RAILS_ROOT}/public/javascripts", "js")}]
asset_yml['stylesheets'] = [{"base" => build_file_list("#{RAILS_ROOT}/public/stylesheets", "css")}]
File.open("#{RAILS_ROOT}/config/asset_packages.yml", "w") do |out|
YAML.dump(asset_yml, out)
def find_by_target(asset_type, target)
package_hash = @@asset_packages_yml[asset_type].find {|p| p.keys.first == target }
package_hash ? self.new(asset_type, package_hash) : nil
end
def find_by_source(asset_type, source)
path_parts = parse_path(source)
package_hash = @@asset_packages_yml[asset_type].find do |p|
key = p.keys.first
p[key].include?(path_parts[2]) && (parse_path(key)[1] == path_parts[1])
end
puts "config/asset_packages.yml example file created!"
puts "Please reorder files under 'base' so dependencies are loaded in correct order."
else
puts "config/asset_packages.yml already exists. Aborting task..."
package_hash ? self.new(asset_type, package_hash) : nil
end
def targets_from_sources(asset_type, sources)
package_names = Array.new
sources.each do |source|
package = find_by_target(asset_type, source) || find_by_source(asset_type, source)
package_names << (package ? package.current_file : source)
end
package_names.uniq
end
def sources_from_targets(asset_type, targets)
source_names = Array.new
targets.each do |target|
package = find_by_target(asset_type, target)
source_names += (package ? package.sources.collect do |src|
package.target_dir.gsub(/^(.+)$/, '\1/') + src
end : target.to_a)
end
source_names.uniq
end
def build_all
@@asset_packages_yml.keys.each do |asset_type|
@@asset_packages_yml[asset_type].each { |p| self.new(asset_type, p).build }
end
end
def delete_all
@@asset_packages_yml.keys.each do |asset_type|
@@asset_packages_yml[asset_type].each { |p| self.new(asset_type, p).delete_all_builds }
end
end
def create_yml
unless File.exists?("#{RAILS_ROOT}/config/asset_packages.yml")
asset_yml = Hash.new
asset_yml['javascripts'] = [{"base" => build_file_list("#{RAILS_ROOT}/public/javascripts", "js")}]
asset_yml['stylesheets'] = [{"base" => build_file_list("#{RAILS_ROOT}/public/stylesheets", "css")}]
File.open("#{RAILS_ROOT}/config/asset_packages.yml", "w") do |out|
YAML.dump(asset_yml, out)
end
log "config/asset_packages.yml example file created!"
log "Please reorder files under 'base' so dependencies are loaded in correct order."
else
log "config/asset_packages.yml already exists. Aborting task..."
end
end
end
# instance methods
attr_accessor :asset_type, :target, :sources
attr_accessor :asset_type, :target, :target_dir, :sources
def initialize(asset_type, package_hash)
@target = package_hash.keys.first
@sources = package_hash[@target]
target_parts = self.class.parse_path(package_hash.keys.first)
@target_dir = target_parts[1].to_s
@target = target_parts[2].to_s
@sources = package_hash[package_hash.keys.first]
@asset_type = asset_type
@asset_path = $asset_base_path ? "#{$asset_base_path}/#{@asset_type}" : "#{RAILS_ROOT}/public/#{@asset_type}"
@asset_path = ($asset_base_path ? "#{$asset_base_path}/" : "#{RAILS_ROOT}/public/") +
"#{@asset_type}#{@target_dir.gsub(/^(.+)$/, '/\1')}"
@extension = get_extension
@match_regex = Regexp.new("\\A#{@target}_\\d+.#{@extension}\\z")
end
def current_file
Dir.new(@asset_path).entries.delete_if { |x| ! (x =~ @match_regex) }.sort.reverse[0].chomp(".#{@extension}")
@target_dir.gsub(/^(.+)$/, '\1/') +
Dir.new(@asset_path).entries.delete_if { |x| ! (x =~ @match_regex) }.sort.reverse[0].chomp(".#{@extension}")
end
def build
@ -126,10 +153,10 @@ module Synthesis
def create_new_build
if File.exists?("#{@asset_path}/#{@target}_#{revision}.#{@extension}")
puts "Latest version already exists: #{@asset_path}/#{@target}_#{revision}.#{@extension}"
log "Latest version already exists: #{@asset_path}/#{@target}_#{revision}.#{@extension}"
else
File.open("#{@asset_path}/#{@target}_#{revision}.#{@extension}", "w") {|f| f.write(compressed_file) }
puts "Created #{@asset_path}/#{@target}_#{revision}.#{@extension}"
log "Created #{@asset_path}/#{@target}_#{revision}.#{@extension}"
end
end
@ -187,6 +214,10 @@ module Synthesis
when "stylesheets" then "css"
end
end
def log(message)
puts message
end
def self.build_file_list(path, extension)
re = Regexp.new(".#{extension}\\z")
@ -197,4 +228,4 @@ module Synthesis
end
end
end
end

View file

@ -1,6 +1,10 @@
module Synthesis
module AssetPackageHelper
def should_merge?
AssetPackage.merge_environments.include?(RAILS_ENV)
end
def javascript_include_merged(*sources)
options = sources.last.is_a?(Hash) ? sources.pop.stringify_keys : { }
@ -13,11 +17,10 @@ module Synthesis
end
sources.collect!{|s| s.to_s}
sources = if suppress_packaging?
AssetPackage.sources_from_targets("javascripts", sources)
else
AssetPackage.targets_from_sources("javascripts", sources)
end
sources = (should_merge? ?
AssetPackage.targets_from_sources("javascripts", sources) :
AssetPackage.sources_from_targets("javascripts", sources))
sources.collect {|source| javascript_include_tag(source, options) }.join("\n")
end
@ -25,11 +28,9 @@ module Synthesis
options = sources.last.is_a?(Hash) ? sources.pop.stringify_keys : { }
sources.collect!{|s| s.to_s}
sources = if suppress_packaging?
AssetPackage.sources_from_targets("stylesheets", sources)
else
AssetPackage.targets_from_sources("stylesheets", sources)
end
sources = (should_merge? ?
AssetPackage.targets_from_sources("stylesheets", sources) :
AssetPackage.sources_from_targets("stylesheets", sources))
sources.collect { |source|
source = stylesheet_path(source)
@ -38,18 +39,11 @@ module Synthesis
end
private
def suppress_packaging?
return true if RAILS_ENV == "development"
return true if SUPPRESS_ASSET_PACKAGER == true rescue nil
return false
end
# rewrite compute_public_path to allow us to not include the query string timestamp
# used by ActionView::Helpers::AssetTagHelper
def compute_public_path(source, dir, ext, add_asset_id=true)
def compute_public_path(source, dir, ext=nil, add_asset_id=true)
source = source.dup
source << ".#{ext}" if File.extname(source).blank?
source << ".#{ext}" if File.extname(source).blank? && ext
unless source =~ %r{^[-a-z]+://}
source = "/#{dir}/#{source}" unless source[0] == ?/
asset_id = rails_asset_id(source)

View file

@ -1,21 +1,20 @@
require File.dirname(__FILE__) + '/../lib/synthesis/asset_package'
namespace :asset do
namespace :packager do
desc "Merge and compress assets"
task :build_all => :environment do
require 'synthesis/asset_package'
task :build_all do
Synthesis::AssetPackage.build_all
end
desc "Delete all asset builds"
task :delete_all => :environment do
require 'synthesis/asset_package'
task :delete_all do
Synthesis::AssetPackage.delete_all
end
desc "Generate asset_packages.yml from existing assets"
task :create_yml => :environment do
require 'synthesis/asset_package'
task :create_yml do
Synthesis::AssetPackage.create_yml
end

View file

@ -4,6 +4,7 @@ ENV['RAILS_ENV'] = "development"
require File.dirname(__FILE__) + '/../../../../config/environment'
require 'test/unit'
require 'rubygems'
require 'mocha'
require 'action_controller/test_process'
@ -20,6 +21,8 @@ class AssetPackageHelperProductionTest < Test::Unit::TestCase
include Synthesis::AssetPackageHelper
def setup
Synthesis::AssetPackage.any_instance.stubs(:log)
@controller = Class.new do
attr_reader :request
def initialize
@ -77,18 +80,18 @@ class AssetPackageHelperProductionTest < Test::Unit::TestCase
end
def test_css_multiple_packages
assert_dom_equal build_css_expected_string("screen", "foo"),
stylesheet_link_merged("screen", "foo")
assert_dom_equal build_css_expected_string("screen", "foo", "subdir/bar"),
stylesheet_link_merged("screen", "foo", "subdir/bar")
end
def test_css_unpackaged_file
assert_dom_equal build_css_expected_string("screen", "foo", "not_part_of_a_package"),
stylesheet_link_merged("screen", "foo", "not_part_of_a_package")
assert_dom_equal build_css_expected_string("screen", "foo", "not_part_of_a_package", "subdir/bar"),
stylesheet_link_merged("screen", "foo", "not_part_of_a_package", "subdir/bar")
end
def test_css_multiple_from_same_package
assert_dom_equal build_css_expected_string("screen", "header", "not_part_of_a_package", "foo", "bar"),
stylesheet_link_merged("screen", "header", "not_part_of_a_package", "foo", "bar")
assert_dom_equal build_css_expected_string("screen", "header", "not_part_of_a_package", "foo", "bar", "subdir/foo", "subdir/bar"),
stylesheet_link_merged("screen", "header", "not_part_of_a_package", "foo", "bar", "subdir/foo", "subdir/bar")
end
def test_css_by_package_name
@ -97,8 +100,8 @@ class AssetPackageHelperProductionTest < Test::Unit::TestCase
end
def test_css_multiple_package_names
assert_dom_equal build_css_expected_string("screen", "header", "foo", "bar"),
stylesheet_link_merged(:base, :secondary)
assert_dom_equal build_css_expected_string("screen", "header", "foo", "bar", "subdir/foo", "subdir/bar"),
stylesheet_link_merged(:base, :secondary, "subdir/styles")
end
end
end

View file

@ -1,9 +1,9 @@
$:.unshift(File.dirname(__FILE__) + '/../lib')
ENV['RAILS_ENV'] = "production"
require File.dirname(__FILE__) + '/../../../../config/environment'
require 'test/unit'
require 'rubygems'
require 'mocha'
require 'action_controller/test_process'
@ -22,6 +22,9 @@ class AssetPackageHelperProductionTest < Test::Unit::TestCase
cattr_accessor :packages_built
def setup
Synthesis::AssetPackage.any_instance.stubs(:log)
self.stubs(:should_merge?).returns(true)
@controller = Class.new do
attr_reader :request
@ -34,10 +37,10 @@ class AssetPackageHelperProductionTest < Test::Unit::TestCase
end
end.new
build_packages_once
end
def build_packages_once
unless @@packages_built
Synthesis::AssetPackage.build_all
@ -105,9 +108,10 @@ class AssetPackageHelperProductionTest < Test::Unit::TestCase
def test_css_multiple_packages
current_file1 = Synthesis::AssetPackage.find_by_source("stylesheets", "screen").current_file
current_file2 = Synthesis::AssetPackage.find_by_source("stylesheets", "foo").current_file
current_file3 = Synthesis::AssetPackage.find_by_source("stylesheets", "subdir/bar").current_file
assert_dom_equal build_css_expected_string(current_file1, current_file2),
stylesheet_link_merged("screen", "foo")
assert_dom_equal build_css_expected_string(current_file1, current_file2, current_file3),
stylesheet_link_merged("screen", "foo", "subdir/bar")
end
def test_css_unpackaged_file
@ -121,9 +125,10 @@ class AssetPackageHelperProductionTest < Test::Unit::TestCase
def test_css_multiple_from_same_package
current_file1 = Synthesis::AssetPackage.find_by_source("stylesheets", "screen").current_file
current_file2 = Synthesis::AssetPackage.find_by_source("stylesheets", "foo").current_file
current_file3 = Synthesis::AssetPackage.find_by_source("stylesheets", "subdir/bar").current_file
assert_dom_equal build_css_expected_string(current_file1, "not_part_of_a_package", current_file2),
stylesheet_link_merged("screen", "header", "not_part_of_a_package", "foo", "bar")
assert_dom_equal build_css_expected_string(current_file1, "not_part_of_a_package", current_file2, current_file3),
stylesheet_link_merged("screen", "header", "not_part_of_a_package", "foo", "bar", "subdir/foo", "subdir/bar")
end
def test_css_by_package_name
@ -135,8 +140,9 @@ class AssetPackageHelperProductionTest < Test::Unit::TestCase
def test_css_multiple_package_names
package_name1 = Synthesis::AssetPackage.find_by_target("stylesheets", "base").current_file
package_name2 = Synthesis::AssetPackage.find_by_target("stylesheets", "secondary").current_file
assert_dom_equal build_css_expected_string(package_name1, package_name2),
stylesheet_link_merged(:base, :secondary)
package_name3 = Synthesis::AssetPackage.find_by_target("stylesheets", "subdir/styles").current_file
assert_dom_equal build_css_expected_string(package_name1, package_name2, package_name3),
stylesheet_link_merged(:base, :secondary, "subdir/styles")
end
def test_image_tag
@ -144,4 +150,4 @@ class AssetPackageHelperProductionTest < Test::Unit::TestCase
assert_dom_equal %(<img alt="Rails" src="/images/rails.png?#{timestamp}" />), image_tag("rails")
end
end
end

View file

@ -1,5 +1,6 @@
require File.dirname(__FILE__) + '/../../../../config/environment'
require 'test/unit'
require 'mocha'
$asset_packages_yml = YAML.load_file("#{RAILS_ROOT}/vendor/plugins/asset_packager/test/asset_packages.yml")
$asset_base_path = "#{RAILS_ROOT}/vendor/plugins/asset_packager/test/assets"
@ -8,6 +9,7 @@ class AssetPackagerTest < Test::Unit::TestCase
include Synthesis
def setup
Synthesis::AssetPackage.any_instance.stubs(:log)
Synthesis::AssetPackage.build_all
end
@ -38,20 +40,25 @@ class AssetPackagerTest < Test::Unit::TestCase
Synthesis::AssetPackage.delete_all
js_package_names = Dir.new("#{$asset_base_path}/javascripts").entries.delete_if { |x| ! (x =~ /\A\w+_\d+.js/) }
css_package_names = Dir.new("#{$asset_base_path}/stylesheets").entries.delete_if { |x| ! (x =~ /\A\w+_\d+.css/) }
css_subdir_package_names = Dir.new("#{$asset_base_path}/stylesheets/subdir").entries.delete_if { |x| ! (x =~ /\A\w+_\d+.css/) }
assert_equal 0, js_package_names.length
assert_equal 0, css_package_names.length
assert_equal 0, css_subdir_package_names.length
Synthesis::AssetPackage.build_all
js_package_names = Dir.new("#{$asset_base_path}/javascripts").entries.delete_if { |x| ! (x =~ /\A\w+_\d+.js/) }.sort
css_package_names = Dir.new("#{$asset_base_path}/stylesheets").entries.delete_if { |x| ! (x =~ /\A\w+_\d+.css/) }.sort
css_subdir_package_names = Dir.new("#{$asset_base_path}/stylesheets/subdir").entries.delete_if { |x| ! (x =~ /\A\w+_\d+.css/) }.sort
assert_equal 2, js_package_names.length
assert_equal 2, css_package_names.length
assert_equal 1, css_subdir_package_names.length
assert js_package_names[0].match(/\Abase_\d+.js\z/)
assert js_package_names[1].match(/\Asecondary_\d+.js\z/)
assert css_package_names[0].match(/\Abase_\d+.css\z/)
assert css_package_names[1].match(/\Asecondary_\d+.css\z/)
assert css_subdir_package_names[0].match(/\Astyles_\d+.css\z/)
end
def test_js_names_from_sources
@ -72,4 +79,14 @@ class AssetPackagerTest < Test::Unit::TestCase
assert_equal package_names[3], "noexist2"
end
def test_should_return_merge_environments_when_set
Synthesis::AssetPackage.merge_environments = ["staging", "production"]
assert_equal ["staging", "production"], Synthesis::AssetPackage.merge_environments
end
def test_should_only_return_production_merge_environment_when_not_set
assert_equal ["production"], Synthesis::AssetPackage.merge_environments
end
end

View file

@ -15,3 +15,6 @@ stylesheets:
- secondary:
- foo
- bar
- subdir/styles:
- foo
- bar

View file

@ -0,0 +1,16 @@
#bar1 {
background: #fff;
color: #000;
text-align: center;
}
#bar2 {
background: #fff;
color: #000;
text-align: center;
}
#bar3 {
background: #fff;
color: #000;
text-align: center;
}

View file

@ -0,0 +1,16 @@
#foo1 {
background: #fff;
color: #000;
text-align: center;
}
#foo2 {
background: #fff;
color: #000;
text-align: center;
}
#foo3 {
background: #fff;
color: #000;
text-align: center;
}