diff --git a/Gemfile b/Gemfile new file mode 100644 index 00000000..410e858a --- /dev/null +++ b/Gemfile @@ -0,0 +1,15 @@ +source 'http://rubygems.org' + +gemspec + +group :development, :test do + gem "rake", "0.9.2" + gem "rails", "2.3.11" + gem "yui-compressor", "0.9.3" + gem "closure-compiler", "1.1.5" + gem "uglifier", "0.4.0" +end + +group :development do + gem "RedCloth", "4.2.9" +end diff --git a/LICENSE b/LICENSE index 9644b34c..21987a88 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2009 Jeremy Ashkenas, DocumentCloud +Copyright (c) 2009-2011 Jeremy Ashkenas, DocumentCloud Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation diff --git a/index.html b/index.html index 5819b511..f386ecb3 100644 --- a/index.html +++ b/index.html @@ -93,7 +93,7 @@

- Current Version: 0.6.3 + Current Version: 0.6.5

@@ -699,6 +699,12 @@

JavaScript Templates

Change Log

+

+ 0.6.5Nov 30, 2011
+ Added the ability to pass HTML tag options to include_javascripts. + Fixed a bug that would always cause JS to be recompiled, regardless of mtimes. +

+

0.6.3May 26, 2011
Quick bugfix release for Rails 3.1 compatibility, which changes the method diff --git a/jammit.gemspec b/jammit.gemspec index 47fd8d9a..23fd32f6 100644 --- a/jammit.gemspec +++ b/jammit.gemspec @@ -1,7 +1,7 @@ Gem::Specification.new do |s| s.name = 'jammit' - s.version = '0.6.3' # Keep version in sync with jammit.rb - s.date = Time.now.strftime('%Y-%m-%d') + s.version = '0.6.5' # Keep version in sync with jammit.rb + s.date = '2011-11-30' s.homepage = "http://documentcloud.github.com/jammit/" s.summary = "Industrial Strength Asset Packaging for Rails" diff --git a/lib/jammit.rb b/lib/jammit.rb index 7939add2..a0df171b 100644 --- a/lib/jammit.rb +++ b/lib/jammit.rb @@ -4,13 +4,13 @@ # to all of the configuration options. module Jammit - VERSION = "0.6.3" + VERSION = "0.6.5" ROOT = File.expand_path(File.dirname(__FILE__) + '/..') ASSET_ROOT = File.expand_path((defined?(Rails) && Rails.root.to_s.length > 0) ? Rails.root : ENV['RAILS_ROOT'] || ".") unless defined?(ASSET_ROOT) - PUBLIC_ROOT = (defined?(Rails) && Rails.public_path.to_s.length > 0) ? Rails.public_path : File.join(ASSET_ROOT, 'public') unless defined?(PUBLIC_ROOT) + DEFAULT_PUBLIC_ROOT = (defined?(Rails) && Rails.public_path.to_s.length > 0) ? Rails.public_path : File.join(ASSET_ROOT, 'public') unless defined?(PUBLIC_ROOT) DEFAULT_CONFIG_PATH = File.join(ASSET_ROOT, 'config', 'assets.yml') @@ -26,8 +26,6 @@ module Jammit DEFAULT_COMPRESSOR = :yui - RAILS_ENV = (defined?(Rails) ? Rails.env : ENV['RAILS_ENV'] || "development") - # Extension matchers for JavaScript and JST, which need to be disambiguated. JS_EXTENSION = /\.js\Z/ DEFAULT_JST_EXTENSION = "jst" @@ -37,7 +35,7 @@ module Jammit class PackageNotFound < NameError; end # Jammit raises a MissingConfiguration exception when you try to load the - # configuration of an assets.yml file that doesn't exist, or are missing + # configuration of an assets.yml file that doesn't exist, or are missing # a piece of required configuration. class MissingConfiguration < NameError; end @@ -54,12 +52,13 @@ class << self :package_path, :mhtml_enabled, :include_jst_script, :config_path, :javascript_compressor, :compressor_options, :css_compressor_options, :template_extension, :template_extension_matcher, :allow_debugging, - :rewrite_relative_paths + :rewrite_relative_paths, :public_root attr_accessor :compressors end # The minimal required configuration. @configuration = {} + @public_root = DEFAULT_PUBLIC_ROOT @package_path = DEFAULT_PACKAGE_PATH @compressors = COMPRESSORS @@ -72,7 +71,8 @@ def self.load_configuration(config_path, soft=false) conf = YAML.load(ERB.new(File.read(config_path)).result) # Optionally overwrite configuration based on the environment. - conf.merge! conf.delete RAILS_ENV if conf.has_key? RAILS_ENV + rails_env = (defined?(Rails) ? ::Rails.env : ENV['RAILS_ENV'] || "development") + conf.merge! conf.delete rails_env if conf.has_key? rails_env @config_path = config_path @configuration = symbolize_keys(conf) @@ -90,6 +90,7 @@ def self.load_configuration(config_path, soft=false) set_template_function(conf[:template_function]) set_template_namespace(conf[:template_namespace]) set_template_extension(conf[:template_extension]) + set_public_root(conf[:public_root]) if conf[:public_root] symbolize_keys(conf[:stylesheets]) if conf[:stylesheets] symbolize_keys(conf[:javascripts]) if conf[:javascripts] check_for_deprecations @@ -127,9 +128,11 @@ def self.package!(options={}) :config_path => Jammit::DEFAULT_CONFIG_PATH, :output_folder => nil, :base_url => nil, + :public_root => nil, :force => false }.merge(options) load_configuration(options[:config_path]) + set_public_root(options[:public_root]) if options[:public_root] packager.force = options[:force] packager.package_names = options[:package_names] packager.precache_all(options[:output_folder], options[:base_url]) @@ -137,6 +140,12 @@ def self.package!(options={}) private + # Allows command-line definition of `PUBLIC_ROOT`, for those using Jammit + # outside of Rails. + def self.set_public_root(public_root=nil) + @public_root = public_root if public_root + end + # Ensure that the JavaScript compressor is a valid choice. def self.set_javascript_compressor(value) value = value && value.to_sym diff --git a/lib/jammit/command_line.rb b/lib/jammit/command_line.rb index 36daec6d..07e3ef19 100644 --- a/lib/jammit/command_line.rb +++ b/lib/jammit/command_line.rb @@ -66,6 +66,10 @@ def parse_options opts.on('-p', '--packages LIST', 'list of packages to build (ex: "core,ui", default: all)') do |package_names| @options[:package_names] = package_names.split(/,\s*/).map {|n| n.to_sym } end + opts.on('-P', '--public-root PATH', 'path to public assets (default: "public")') do |public_root| + puts "Option for PUBLIC_ROOT" + @options[:public_root] = public_root + end opts.on_tail('-v', '--version', 'display Jammit version') do puts "Jammit version #{Jammit::VERSION}" exit diff --git a/lib/jammit/compressor.rb b/lib/jammit/compressor.rb index 01348d4b..0854f977 100644 --- a/lib/jammit/compressor.rb +++ b/lib/jammit/compressor.rb @@ -187,14 +187,14 @@ def construct_asset_path(asset_path, css_path, variant) # not be relative, given the path of the stylesheet that contains it. def absolute_path(asset_pathname, css_pathname) (asset_pathname.absolute? ? - Pathname.new(File.join(PUBLIC_ROOT, asset_pathname)) : + Pathname.new(File.join(Jammit.public_root, asset_pathname)) : css_pathname.dirname + asset_pathname).cleanpath end # CSS assets that are referenced by relative paths, and are *not* being # embedded, must be rewritten relative to the newly-merged stylesheet path. def relative_path(absolute_path) - File.join('../', absolute_path.sub(PUBLIC_ROOT, '')) + File.join('../', absolute_path.sub(Jammit.public_root, '')) end # Similar to the AssetTagHelper's method of the same name, this will @@ -246,7 +246,7 @@ def concatenate(paths) # `File.read`, but in "binary" mode. def read_binary_file(path) - File.open(path, 'rb') {|f| f.read } + File.open(path, 'rb:UTF-8') {|f| f.read } end end diff --git a/lib/jammit/controller.rb b/lib/jammit/controller.rb index 53f65bb2..0ebbd71c 100644 --- a/lib/jammit/controller.rb +++ b/lib/jammit/controller.rb @@ -11,7 +11,7 @@ class Controller < ActionController::Base SUFFIX_STRIPPER = /-(datauri|mhtml)\Z/ - NOT_FOUND_PATH = "#{PUBLIC_ROOT}/404.html" + NOT_FOUND_PATH = "#{Jammit.public_root}/404.html" # The "package" action receives all requests for asset packages that haven't # yet been cached. The package will be built, cached, and gzipped. diff --git a/lib/jammit/helper.rb b/lib/jammit/helper.rb index 727e5a19..530bc1bf 100644 --- a/lib/jammit/helper.rb +++ b/lib/jammit/helper.rb @@ -25,10 +25,11 @@ def include_stylesheets(*packages) # Writes out the URL to the bundled and compressed javascript package, # except in development, where it references the individual scripts. def include_javascripts(*packages) + options = packages.extract_options! html_safe packages.map {|pack| should_package? ? Jammit.asset_url(pack, :js) : Jammit.packager.individual_urls(pack.to_sym, :js) }.flatten.map {|pack| - javascript_include_tag pack + javascript_include_tag pack, options }.join("\n") end @@ -72,8 +73,8 @@ def embedded_image_stylesheets(packages, options) # Generate the stylesheet tags for a batch of packages, with options, by # yielding each package to a block. def tags_with_options(packages, options) - packages.dup.map {|package| - yield package + packages.dup.map {|package| + yield package }.flatten.map {|package| stylesheet_link_tag package, options }.join("\n") diff --git a/lib/jammit/packager.rb b/lib/jammit/packager.rb index acce7a72..4b06f185 100644 --- a/lib/jammit/packager.rb +++ b/lib/jammit/packager.rb @@ -6,10 +6,6 @@ module Jammit # with the correct timestamps. class Packager - # In Rails, the difference between a path and an asset URL is "public". - PATH_DIFF = PUBLIC_ROOT.sub(ASSET_ROOT, '') - PATH_TO_URL = /\A#{Regexp.escape(ASSET_ROOT)}(\/?#{Regexp.escape(PATH_DIFF)})?/ - # Set force to false to allow packages to only be rebuilt when their source # files have changed since the last time their package was built. attr_accessor :force, :package_names @@ -37,7 +33,7 @@ def initialize # Unless forced, will only rebuild assets whose source files have been # changed since their last package build. def precache_all(output_dir=nil, base_url=nil) - output_dir ||= File.join(PUBLIC_ROOT, Jammit.package_path) + output_dir ||= File.join(Jammit.public_root, Jammit.package_path) cacheable(:js, output_dir).each {|p| cache(p, 'js', pack_javascripts(p), output_dir) } cacheable(:css, output_dir).each do |p| cache(p, 'css', pack_stylesheets(p), output_dir) @@ -89,6 +85,7 @@ def pack_javascripts(package) def pack_templates(package) @compressor.compile_jst(package_for(package, :js)[:paths]) end + private @@ -107,6 +104,11 @@ def glob_files(glob) Jammit.warn("No assets match '#{glob}'") if paths.empty? paths end + + # In Rails, the difference between a path and an asset URL is "public". + def path_to_url + @path_to_url ||= /\A#{Regexp.escape(ASSET_ROOT)}(\/?#{Regexp.escape(Jammit.public_root.sub(ASSET_ROOT, ''))})?/ + end # Get the latest mtime of a list of files (plus the config path). def latest_mtime(paths) @@ -125,8 +127,10 @@ def cacheable(extension, output_dir) return names.select do |name| pack = package_for(name, extension) cached = [Jammit.filename(name, extension)] - cached.push Jammit.filename(name, extension, :datauri) if Jammit.embed_assets - cached.push Jammit.filename(name, extension, :mhtml) if Jammit.mhtml_enabled + if extension == :css + cached.push Jammit.filename(name, extension, :datauri) if Jammit.embed_assets + cached.push Jammit.filename(name, extension, :mhtml) if Jammit.mhtml_enabled + end cached.map! {|file| File.join(output_dir, file) } if cached.any? {|file| !File.exists?(file) } true @@ -153,10 +157,10 @@ def create_packages(config) paths = globs.flatten.uniq.map {|glob| glob_files(glob) }.flatten.uniq packages[name][:paths] = paths if !paths.grep(Jammit.template_extension_matcher).empty? - packages[name][:urls] = paths.grep(JS_EXTENSION).map {|path| path.sub(PATH_TO_URL, '') } + packages[name][:urls] = paths.grep(JS_EXTENSION).map {|path| path.sub(path_to_url, '') } packages[name][:urls] += [Jammit.asset_url(name, Jammit.template_extension)] else - packages[name][:urls] = paths.map {|path| path.sub(PATH_TO_URL, '') } + packages[name][:urls] = paths.map {|path| path.sub(path_to_url, '') } end end packages diff --git a/test/config/assets-erb.yml b/test/config/assets-erb.yml index 2610e6c5..33b5ca08 100644 --- a/test/config/assets-erb.yml +++ b/test/config/assets-erb.yml @@ -1,4 +1,4 @@ -embed_assets: <%= RAILS_ENV == 'test' %> +embed_assets: <%= ENV['RAILS_ENV'] == 'test' %> javascripts: js_test: diff --git a/test/test_helper.rb b/test/test_helper.rb index be81ae82..b1fe3497 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -5,9 +5,7 @@ ASSET_ROOT = File.expand_path(File.dirname(__FILE__)) devnull = RUBY_PLATFORM =~ /mswin|mingw|bccwin|wince|emx/ ? 'nul' : '/dev/null' -RAILS_DEFAULT_LOGGER = Logger.new(devnull) -RAILS_ENV = "test" -RAILS_ROOT = File.expand_path(File.dirname(__FILE__)) +ENV['RAILS_ENV'] ||= "test" ENV["RAILS_ASSET_ID"] = "101" require './lib/jammit' diff --git a/test/unit/test_configuration.rb b/test/unit/test_configuration.rb index 088ba0bf..974a1006 100644 --- a/test/unit/test_configuration.rb +++ b/test/unit/test_configuration.rb @@ -24,42 +24,42 @@ def test_disabled_compression @compressor = Compressor.new # Should not compress js. packed = @compressor.compress_js(glob('test/fixtures/src/*.js')) - assert packed == File.read('test/fixtures/jammed/js_test-uncompressed.js') + assert_equal packed, File.read('test/fixtures/jammed/js_test-uncompressed.js') # Nothing should change with jst. packed = @compressor.compile_jst(glob('test/fixtures/src/*.jst')) - assert packed == File.read('test/fixtures/jammed/jst_test.js') + assert_equal packed, File.read('test/fixtures/jammed/jst_test.js') packed = @compressor.compress_css(glob('test/fixtures/src/*.css')) - assert packed == File.open('test/fixtures/jammed/css_test-uncompressed.css', 'rb') {|f| f.read } + assert_equal packed, File.open('test/fixtures/jammed/css_test-uncompressed.css', 'rb') {|f| f.read } end def test_css_compression assert Jammit.compress_assets assert Jammit.gzip_assets packed = @compressor.compress_css(glob('test/fixtures/src/*.css')) - assert packed == File.read('test/fixtures/jammed/css_test.css') + assert_equal packed, File.read('test/fixtures/jammed/css_test.css') end def test_erb_configuration Jammit.load_configuration('test/config/assets-erb.yml') assert Jammit.compress_assets packed = @compressor.compress_css(glob('test/fixtures/src/*.css')) - assert packed == File.read('test/fixtures/jammed/css_test.css') + assert_equal packed, File.read('test/fixtures/jammed/css_test.css') end def test_css_configuration Jammit.load_configuration('test/config/assets-css.yml') packed = Compressor.new.compress_css(glob('test/fixtures/src/*.css')) - assert packed == File.read('test/fixtures/jammed/css_test-line-break.css') + assert_equal packed, File.read('test/fixtures/jammed/css_test-line-break.css') end def test_javascript_compression packed = @compressor.compress_js(glob('test/fixtures/src/*.js')) - assert packed == File.read('test/fixtures/jammed/js_test.js') + assert_equal packed, File.read('test/fixtures/jammed/js_test.js') end def test_jst_compilation packed = @compressor.compile_jst(glob('test/fixtures/src/*.jst')) - assert packed == File.read('test/fixtures/jammed/jst_test.js') + assert_equal packed, File.read('test/fixtures/jammed/jst_test.js') end def test_environment_specific_configuration diff --git a/test/unit/test_uglifier.rb b/test/unit/test_uglifier.rb index f19a9b81..61ee4124 100644 --- a/test/unit/test_uglifier.rb +++ b/test/unit/test_uglifier.rb @@ -13,7 +13,7 @@ def teardown def test_javascript_compression packed = @compressor.compress_js(glob('test/fixtures/src/*.js')) - assert packed == File.read('test/fixtures/jammed/js_test-uglifier.js') + assert_equal packed, File.read('test/fixtures/jammed/js_test-uglifier.js') end def test_jst_compilation