$LOAD_PATH.push File.expand_path(File.dirname(__FILE__)) # @Jammit@ is the central namespace for all Jammit classes, and provides access # to all of the configuration options. module Jammit VERSION = "0.4.3" ROOT = File.expand_path(File.dirname(__FILE__)) ASSET_ROOT = File.expand_path(".") unless defined?(ASSET_ROOT) PUBLIC_ROOT = File.join(ASSET_ROOT, 'public') DEFAULT_CONFIG_PATH = File.join(ASSET_ROOT, 'config') DEFAULT_CONFIG_FILENAME = 'assets.yml' DEFAULT_PACKAGE_PATH = "assets" DEFAULT_JST_SCRIPT = File.join(ROOT, 'lib/jammit/jst.js') DEFAULT_JST_COMPILER = "template" DEFAULT_JST_NAMESPACE = "window.JST" AVAILABLE_COMPRESSORS = [:yui, :closure] DEFAULT_COMPRESSOR = :yui SUFFIX = 'all' DEBUG_SUFFIX = 'all-debug' autoload :UI, 'jammit-core/ui' autoload :Config, 'jammit-core/config' class Error < StandardError def self.status_code(code = nil) return @code unless code @code = code end def status_code self.class.status_code end end # Jammit raises @AppNotFound when trying to run outside of an application class AppNotFound < Error; status_code(1) ; end # Jammit raises a @PackageNotFound@ exception when a non-existent package is # requested by a browser -- rendering a 404. class PackageNotFound < Error; status_code(2) ; end # Jammit raises a ConfigurationNotFound exception when you try to load the # configuration of an assets.yml file that doesn't exist. class ConfigurationNotFound < Error; status_code(3) ; end # Jammit raises AlreadyConfigred if trying to over-write an existing configuration file class AlreadyConfigured < Error; status_code(4) ; end # Jammit raises an OutputNotWritable exception if the output directory for # cached packages is locked. class OutputNotWritable < Error; status_code(4) ; end class << self attr_reader :configuration attr_writer :ui attr_writer :options def configure @configured ||= begin ## # perform some config here? # #configure_gem_home_and_path true end end ## # Ensure we're running within a rails app unless generating a new app ($ xmvc generate app foo) # def ensure_in_app unless ARGV.empty? || ARGV.first == 'help' || (File.exists?('app') && File.exists?('config') && File.exists?('config/environment.json')) raise Jammit::AppNotFound.new("This command must be executed from the root of an extjs-mvc application") end end def ui @ui ||= UI.new end def options @options end def asset_root unless @asset_root if (options && options[:asset_root]) @asset_root = options[:asset_root] else @asset_root = ASSET_ROOT end end #@asset_root ||= (options && options[:asset_root]) ? options[:asset_root] : ASSET_ROOT @asset_root end def public_root @public_root ||= File.join(asset_root, 'public') end def config_path @config_path ||= File.join(asset_root, 'config', DEFAULT_CONFIG_FILENAME) end def package_path @package_path ||= (@options && @options[:package_path]) ? @options[:package_path] : config[:package_path] end # Load the complete asset configuration from the specified @config_path@. def config unless @config # Normalize config @config = Jammit::Config.load.to_mash @config[:output_folder] = (@config[:output_folder]) ? File.join(asset_root, @config[:output_folder]) : public_root @config[:package_path] = @config[:package_path] || Jammit::DEFAULT_PACKAGE_PATH @config[:embed_assets] = @config[:embed_assets] || @config[:embed_images] @config[:compress_assets] = !(@config[:compress_assets] == false) @config[:gzip_assets] = !(@config[:gzip_assets] == false) @config[:mhtml_enabled] = @config[:embed_assets] && @config[:embed_assets] != "datauri" @config[:compressor_options] = (@config[:compressor_options] || {}).to_mash @config[:css_compressor_options] = (@config[:css_compressor_options] || {}).to_mash @config[:javascript_compressor] = get_javascript_compressor(@config[:javascript_compressor].to_sym) @config[:package_assets] = get_package_assets(@config[:package_assets]) @config[:template_function] = get_template_function(@config[:template_function]) @config[:include_jst_script] = @config[:template_function] == Jammit::DEFAULT_JST_COMPILER @config[:template_namespace] = get_template_namespace(@config[:template_namespace]) @config[:suffix] = SUFFIX unless @config[:suffix] @config[:debug_suffix] = DEBUG_SUFFIX unless @config[:debug_suffix] end @config end def config=(config) @config = config end # The YUI Compressor requires Java > 1.4, and Closure requires Java > 1.6. def check_java_version java = @config[:compressor_options][:java] || 'java' @config[:css_compressor_options][:java] ||= java if @config[:compressor_options][:java] version = (`#{java} -version 2>&1`)[/\d+\.\d+/] disable_compression if !version || (@config[:javascript_compressor] == :closure && version < '1.6') || (@config[:javascript_compressor] == :yui && version < '1.4') end # If we don't have a working Java VM, then disable asset compression and # complain loudly. def disable_compression @config[:compress_assets] = false Jammit.ui.warn("Asset compression disabled -- Java unavailable.") end # Turn asset packaging on or off, depending on configuration and environment. def get_package_assets(value) package_env = !defined?(Rails) || !Rails.env.development? (value == true || value.nil?) ? package_env : (value == 'always') ? true : false end # Assign the JST template function, unless explicitly turned off. def get_template_function(value) (value == true || value.nil?) ? DEFAULT_JST_COMPILER : value == false ? '' : value end # Ensure that the JavaScript compressor is a valid choice. def get_javascript_compressor(value) Jammit::AVAILABLE_COMPRESSORS.include?(value) ? value : Jammit::DEFAULT_COMPRESSOR end # Set the root JS object in which to stash all compiled JST. def get_template_namespace(value) (value == true || value.nil?) ? Jammit::DEFAULT_JST_NAMESPACE : value.to_s end # Force a reload by resetting the Packager and reloading the configuration. # In development, this will be called as a before_filter before every request. def reload! Thread.current[:jammit_packager] = nil @config = Config.load(config[:config_path], true) end # Keep a global (thread-local) reference to a @Jammit::Packager@, to avoid # recomputing asset lists unnecessarily. def packager Thread.current[:jammit_packager] ||= Packager.new end # Generate the base filename for a version of a given package. def filename(package, extension, suffix=nil) suffix_part = suffix ? "-#{suffix}" : '' "#{package}#{suffix_part}.#{extension}" end # Generates the server-absolute URL to an asset package. def asset_url(package, extension, suffix=nil, mtime=nil) timestamp = mtime ? "?#{mtime.to_i}" : '' "/#{package_path}/#{filename(package, extension, suffix)}#{timestamp}" end end end require 'jammit-core/dependencies'