Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
source :rubygems
gemspec

group :development do
gem "rake"
gem "activesupport"
end
20 changes: 20 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
PATH
remote: .
specs:
assemblage (0.0.3)

GEM
remote: http://rubygems.org/
specs:
activesupport (3.1.1)
multi_json (~> 1.0)
multi_json (1.0.3)
rake (0.9.2)

PLATFORMS
ruby

DEPENDENCIES
activesupport
assemblage!
rake
18 changes: 17 additions & 1 deletion README.rdoc
Original file line number Diff line number Diff line change
Expand Up @@ -59,18 +59,34 @@ You can handle these tasks on deployment by doing the following:
namespace :deploy do
desc "Assemble JavaScript and CSS files"
task :assemble, :roles => :web, :except => { :no_release => true } do
run "cd #{current_path}; rake assemble:all"
run "cd #{release_path}; rake assemble:all"
end
end

after "deploy:update_code", "deploy:assemble"

== Assemblage Configuration and Ordering Files within a Bundle

To order the files within each bundle you may create a file config/assemblage.rb within your Rails application that provides the specific list of files and their order. For example:


bundle :widget, :js, 'jquery-1.4.4.min.js', 'jquery-ui-1.8.7.custom.min.js', 'jquery.maskedinput.js', 'raphael-1.5.2.min.js', 'jquery.ba-postmessage.0.5.min.js'
bundle :app, :js, 'jquery-1.4.4.min.js', 'jquery-ui-1.8.7.custom.min.js', 'farbtastic'
bundle :app, :css, 'site', 'jquery-ui-1.8.7.custom.css', 'farbtastic'

Defines 3 bundles. The first named 'widget' that is a JavaScript bundle that includes 5 files in the order specified, the second 'app' another JavaScript bundle including 3 files in the given order and the last one 'app' a CSS bundle providing 3 css files in the given order.
Any bundle not listed in the configuration file will order the included files in alphabetical order.

== Issues & Contributions

For all issues and bug/feature requests, please use the GitHub issue tracker:

http://github.com/voxxit/assemblage

== Additional documentation

Very helpful article: {Static Asset Bundling with Ruby on Rails By: Todd Fisher}[http://captico.com/static-asset-bundling-with-ruby-on-rails/2011/02].

== Props

Thanks to {Kyle Neath}[http://github.com/kneath] for the inspiration to turn his idea into a useful plugin for all!
Expand Down
22 changes: 22 additions & 0 deletions assemblage.gemspec
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
$:.unshift File.expand_path(File.dirname(__FILE__) + "/lib")
require "assemblage/version"

Gem::Specification.new do |spec|
spec.name = "assemblage"
spec.version = Assemblage::VERSION
spec.author = "Josh Delsman"
spec.email = "assaf@labnotes.org"
spec.homepage = "https://github.com/voxxit/assemblage"
spec.summary = "Rails plugin to allow for compressing and bundling JavaScript & CSS files for production"
spec.description = "Rails plugin to allow for compressing and bundling JavaScript & CSS files for production"
spec.post_install_message = ""
spec.require_paths = ['lib']

spec.files = Dir["{lib,bin}/**/*", "MIT-LICENSE", "README.rdoc", "Rakefile", "*.gemspec"]

spec.extra_rdoc_files = "README.rdoc"
spec.rdoc_options = "--title", "Assemblage #{spec.version}", "--main", "README.rdoc", "--webcvs", spec.homepage

spec.required_ruby_version = '>= 1.8.7'
spec.add_development_dependency "activesupport"
end
Binary file modified bin/compiler.jar
Binary file not shown.
2 changes: 1 addition & 1 deletion init.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
require 'assemblage'

ActionView::Base.send(:include, Assemblage::ViewHelpers)
ActionView::Base.send(:include, Assemblage::ViewHelpers)
27 changes: 10 additions & 17 deletions lib/assemblage.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
require 'find'
require 'assemblage/config'
require 'assemblage/packager'
require 'assemblage/version'
require 'assemblage/railtie' if defined?(Rails) && defined?(Rails::Railtie)

module Assemblage

module ViewHelpers
def bundle_files?
Rails.env.production? || Rails.env.staging? || params[:bundle] || cookies[:bundle] == "yes"
Expand Down Expand Up @@ -78,22 +82,11 @@ def stylesheet_include_files(bundles)
end

def recursive_file_list(basedir, extname)
files = []
basedir = Rails.root.join("public", basedir)

Find.find(basedir) do |path|
if FileTest.directory?(path)
if File.basename(path)[0] == ?.
Find.prune
else
next
end
end

files << path.gsub(Rails.root.to_s, '') if File.extname(path) == extname
Config.recursive_file_list(basedir, extname) do|path|
path.gsub(Rails.root.to_s, '')
end

files.sort
end


end
end
end
173 changes: 173 additions & 0 deletions lib/assemblage/config.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
require 'find'
require 'assemblage/rails2-compat'

module Assemblage

class Config
attr_reader :basedir, :bundles, :level, :logging, :java

VALID_TYPES = [:js,:css]

class Error < Exception ; end
class MissingFile < Error
attr_accessor :filepath, :bundle
end

def initialize(assemblage_config_path=nil)
@bundles = {} # named bundles
@level = "SIMPLE_OPTIMIZATIONS"
@logging = "DEFAULT"
@java = "/usr/bin/java"
assemblage_config_path=File.join(Rails.root,'config/assemblage.rb') if assemblage_config_path.nil?
@basedir = File.expand_path(File.join(Rails.root,"public"))
#puts "load config file at: #{assemblage_config_path.inspect}"
evaluate assemblage_config_path
end

#
# change default base dir from public/ to something different e.g. public/foo/
# if path is relative it will be assumed relative from Rails.root
#
def basedir(basedir)
@basedir = basedir
@basedir = File.expand_path(File.join(Rails.root, @basedir)) if !@basedir.match(/^\//)
end

def base_path
@basedir
end

#
# configure the bundle to be explicit
#
def bundle(bundle_name, type, *filelist)
raise Error.new("Invalid bundle type, must be one of #{VALID_TYPES.inspect}") unless VALID_TYPES.include?(type)
# verify ordered files exist
basedir = type_to_path(type)
filelist.each do|name|
path = File.join(basedir, bundle_name.to_s, name)
path << ".#{type.to_s}" unless path.match(/\.#{type.to_s}$/)
unless File.exist?(path)
error = MissingFile.new("Missing reference to file: #{name} at #{path}")
error.filepath = path
error.bundle = bundle_name
raise error
end

# add a reference
@bundles[type] ||= {}
@bundles[type][bundle_name] ||= []
@bundles[type][bundle_name] << {:name => name, :path => path}
end
end

# valid levels, :simple, :whitespace, :advanced
def closure(level, logging=:default)
@level = {:simple => "SIMPLE_OPTIMIZATIONS",
:whitespace => "WHITESPACE_ONLY",
:advanced => "ADVANCED_OPTIMIZATIONS"}[level]
raise "Unknown closure runtime level, should be one of :simple, :whitespace, or :advanced" if @level.blank?

@logging = { :quiet => "QUIET",
:default => 'DEFAULT',
:verbose => 'VERBOSE'}[logging]
raise "Unknown logging level, should be one of :quiet, :default, or :verbose" if @logging.blank?
end

def java(path_to_java="/usr/bin/java")
@java = path_to_java
end

def has_order?(bundle_name, type)
@bundles.key?(type.to_sym) && @bundles[type.to_sym].key?(bundle_name.to_sym)
end

def bundled_list(bundle_name, type)
raise Error.new("#{bundle_name} not ordered") unless has_order? bundle_name, type
@bundles[type][bundle_name]
end

def recursive_file_list(basedir, extname, load_config=true)
files = []
basedir = Rails.root.join("public", basedir)
config = Config.load_config_instance if load_config

extname.sub!(/^\./,'') # remove any leading .

bundle_name = File.basename(basedir)
if config && config.has_order?(bundle_name, extname.to_sym)

config.bundled_list(bundle_name.to_sym, extname.to_sym).each do|ref|
path = ref[:path]
if block_given?
files << yield(path)
else
files << path
end
end

else

Find.find(basedir) do |path|
if FileTest.directory?(path)
if File.basename(path)[0] == ?.
Find.prune
else
next
end
end

if File.extname(path).sub(/^\./,'') == extname
if block_given?
files << yield(path)
else
files << path
end
end
end

files.sort

end

files

end

def self.load_config_instance
return nil if ENV["ASSEMBLAGE_NO_CONFIG"] == "1"
config_path = ENV["ASSEMBLAGE_CONFIG_PATH"] if ENV["ASSEMBLAGE_CONFIG_PATH"].present?
config_path = File.join(Rails.root,'config','assemblage.rb') if config_path.blank?
#puts "Using config_path: #{config_path.inspect}"
if File.exist?(config_path)
if Rails.env == 'development'
@assemblage_config = Config.new(config_path)
else
@assemblage_config ||= Config.new(config_path)
end
else
raise "#{config_path.inspect} not found"
end
end

private

def type_to_path(type)
basedir = @basedir
case type
when :js
File.join(basedir,"javascripts")
when :css
File.join(basedir,"stylesheets")
end
end

def evaluate(assemblage_path)
self.instance_eval(File.read(assemblage_path), assemblage_path, 0)
rescue => e
raise Error.new("Config error: '#{e.message}' at #{e.backtrace[0].gsub(/:in `run'/,'')}")
end

end

end
Loading