├── .gitignore ├── test ├── fixtures │ ├── cli │ │ ├── cli1.js │ │ ├── cli2.js │ │ └── sprockets_file │ │ │ └── .sprocksrc │ ├── include │ │ └── foo.js │ └── compiler │ │ ├── file2.js │ │ ├── file3.js │ │ ├── file4.js │ │ └── file1.js ├── sprocketize_test.rb ├── test_compiler.rb └── test_cli.rb ├── Gemfile ├── .travis.yml ├── lib ├── sprocketize │ ├── version.rb │ ├── compiler.rb │ └── cli.rb └── sprocketize.rb ├── bin └── sprocketize ├── Rakefile ├── Gemfile.lock ├── sprocketize.gemspec ├── LICENSE └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | pkg 2 | -------------------------------------------------------------------------------- /test/fixtures/cli/cli1.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/fixtures/cli/cli2.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/fixtures/include/foo.js: -------------------------------------------------------------------------------- 1 | var foo; -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source :rubygems 2 | gemspec 3 | -------------------------------------------------------------------------------- /test/fixtures/compiler/file2.js: -------------------------------------------------------------------------------- 1 | var file2; -------------------------------------------------------------------------------- /test/fixtures/compiler/file3.js: -------------------------------------------------------------------------------- 1 | var file3; -------------------------------------------------------------------------------- /test/fixtures/compiler/file4.js: -------------------------------------------------------------------------------- 1 | var file4; -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | rvm: 2 | - 1.8.7 3 | - 1.9.2 4 | - 1.9.3 -------------------------------------------------------------------------------- /test/fixtures/compiler/file1.js: -------------------------------------------------------------------------------- 1 | //= require foo 2 | var file1; -------------------------------------------------------------------------------- /lib/sprocketize/version.rb: -------------------------------------------------------------------------------- 1 | module Sprocketize 2 | VERSION = "0.1" 3 | end -------------------------------------------------------------------------------- /bin/sprocketize: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | require 'sprocketize' 4 | 5 | Sprocketize::CLI.new(*ARGV).run 6 | -------------------------------------------------------------------------------- /lib/sprocketize.rb: -------------------------------------------------------------------------------- 1 | require 'sprockets' 2 | 3 | module Sprocketize 4 | autoload :CLI, "sprocketize/cli" 5 | autoload :Compiler, "sprocketize/compiler" 6 | autoload :VERSION, "sprocketize/version" 7 | end -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require "rake/testtask" 2 | require "bundler" 3 | Bundler::GemHelper.install_tasks 4 | 5 | task :default => :test 6 | 7 | Rake::TestTask.new do |t| 8 | t.libs << "test" 9 | t.warning = false 10 | end 11 | -------------------------------------------------------------------------------- /test/fixtures/cli/sprockets_file/.sprocksrc: -------------------------------------------------------------------------------- 1 | --- 2 | target: ../compiled 3 | paths: 4 | - .. 5 | assets: 6 | - cli_sprockets.js 7 | manifest: false 8 | manifest_path: 9 | digest: false 10 | gzip: false 11 | js_compressor: 12 | compress_css: true 13 | -------------------------------------------------------------------------------- /Gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: . 3 | specs: 4 | sprocketize (0.1) 5 | sprockets (~> 2.0.1) 6 | 7 | GEM 8 | remote: http://rubygems.org/ 9 | specs: 10 | closure-compiler (1.1.4) 11 | hike (1.2.1) 12 | rack (1.3.5) 13 | sprockets (2.0.3) 14 | hike (~> 1.2) 15 | rack (~> 1.0) 16 | tilt (~> 1.1, != 1.3.0) 17 | tilt (1.3.3) 18 | 19 | PLATFORMS 20 | ruby 21 | 22 | DEPENDENCIES 23 | closure-compiler 24 | sprocketize! 25 | -------------------------------------------------------------------------------- /sprocketize.gemspec: -------------------------------------------------------------------------------- 1 | $:.unshift File.expand_path("../lib", __FILE__) 2 | require "sprocketize/version" 3 | 4 | Gem::Specification.new do |s| 5 | s.name = "sprocketize" 6 | s.version = Sprocketize::VERSION 7 | s.summary = "Command-line utility for the Sprockets gem" 8 | s.description = "Sprocketize provides a command-line utility for the sprockets gem so it can be used without rails." 9 | 10 | s.files = Dir["README.md", "LICENSE", "lib/**/*.rb", "bin/*"] 11 | s.executables = ["sprocketize"] 12 | 13 | s.add_dependency "sprockets", ">= 2.1.2" 14 | 15 | s.add_development_dependency "rake" 16 | s.add_development_dependency "closure-compiler" 17 | 18 | s.authors = ["Mato Ilic"] 19 | s.email = ["info@matoilic.ch"] 20 | s.homepage = "http://github.com/matoilic/sprocketize" 21 | end 22 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2011 Mato Ilic 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /test/sprocketize_test.rb: -------------------------------------------------------------------------------- 1 | require "test/unit" 2 | require "sprocketize" 3 | require "fileutils" 4 | 5 | class Sprocketize::TestCase < Test::Unit::TestCase 6 | FIXTURE_ROOT = File.expand_path(File.join(File.dirname(__FILE__), "fixtures")) 7 | 8 | undef_method :default_test if method_defined? :default_test 9 | 10 | def self.test(name, &block) 11 | define_method("test #{name.inspect}", &block) 12 | end 13 | 14 | def fixture_path(path) 15 | File.join(FIXTURE_ROOT, path) 16 | end 17 | 18 | def rmdir(path) 19 | Dir[File.join(path, '*')].each {|p| File.file?(p) ? FileUtils.rm_rf(p) : rmdir(p)} 20 | Dir.rmdir(path) 21 | end 22 | 23 | def sandbox(*paths) 24 | backup_paths = paths.select { |path| File.exist?(path) } 25 | remove_paths = paths.select { |path| !File.exist?(path) } 26 | 27 | begin 28 | backup_paths.each do |path| 29 | FileUtils.cp(path, "#{path}.orig") 30 | end 31 | 32 | yield 33 | ensure 34 | backup_paths.each do |path| 35 | if File.exist?("#{path}.orig") 36 | FileUtils.mv("#{path}.orig", path) 37 | end 38 | 39 | assert !File.exist?("#{path}.orig") 40 | end 41 | 42 | remove_paths.each do |path| 43 | if File.exist?(path) 44 | File.file?(path) ? FileUtils.rm_rf(path) : rmdir(path) 45 | end 46 | 47 | assert !File.exist?(path) 48 | end 49 | end 50 | end 51 | end 52 | -------------------------------------------------------------------------------- /lib/sprocketize/compiler.rb: -------------------------------------------------------------------------------- 1 | require 'fileutils' 2 | 3 | module Sprocketize 4 | class Compiler 5 | attr_accessor :env, :target, :paths 6 | 7 | def initialize(env, target, paths, options = {}) 8 | @env = env 9 | @target = target 10 | @paths = paths 11 | @gzip = options.key?(:gzip) ? options.delete(:gzip) : false 12 | @digest = options.key?(:digest) ? options.delete(:digest) : false 13 | @manifest = options.key?(:manifest) ? options.delete(:manifest) : false 14 | @manifest_path = options.delete(:manifest_path) || target 15 | end 16 | 17 | def compile 18 | manifest = {} 19 | env.each_logical_path do |logical_path| 20 | asset = env.find_asset(logical_path) 21 | next if asset.nil? || !compile_asset?(asset) 22 | manifest[logical_path] = write_asset(asset) 23 | end 24 | write_manifest(manifest) if @manifest 25 | end 26 | 27 | def write_manifest(manifest) 28 | FileUtils.mkdir_p(@manifest_path) 29 | File.open("#{@manifest_path}/manifest.yml", 'wb') do |f| 30 | YAML.dump(manifest, f) 31 | end 32 | end 33 | 34 | def write_asset(asset) 35 | path_for(asset).tap do |path| 36 | filename = File.join(target, path) 37 | FileUtils.mkdir_p File.dirname(filename) 38 | asset.write_to(filename) 39 | asset.write_to("#{filename}.gz") if @gzip && filename.to_s =~ /\.(css|js)$/ 40 | end 41 | end 42 | 43 | def compile_asset?(asset) 44 | paths.each do |path| 45 | case path 46 | when Regexp 47 | return true if path.match(asset.pathname.to_s) 48 | when Proc 49 | return true if path.call(asset) 50 | else 51 | return true if File.fnmatch(path.to_s, asset.pathname.to_s) 52 | end 53 | end 54 | false 55 | end 56 | 57 | def path_for(asset) 58 | @digest ? asset.digest_path : asset.logical_path 59 | end 60 | end 61 | end 62 | -------------------------------------------------------------------------------- /test/test_compiler.rb: -------------------------------------------------------------------------------- 1 | require "sprocketize_test" 2 | require "sprockets" 3 | 4 | class TestCompiler < Sprocketize::TestCase 5 | def setup 6 | @target = fixture_path('compiler/compiled') 7 | @env = Sprockets::Environment.new(fixture_path('compiler')) 8 | @env.append_path('.') 9 | @env.append_path(fixture_path('include')) 10 | end 11 | 12 | test "only allowed assets get compiled" do 13 | paths = [ 14 | /file1\.js/, 15 | Proc.new {|a| a.pathname.to_s.end_with?('file2.js')}, 16 | fixture_path('compiler/file3.js') 17 | ] 18 | 19 | compiler = Sprocketize::Compiler.new(@env, @target, paths, {}) 20 | 21 | sandbox @target do 22 | compiler.compile 23 | 24 | assert File.exists?(File.join(@target, 'file1.js')) 25 | assert File.exists?(File.join(@target, 'file2.js')) 26 | assert File.exists?(File.join(@target, 'file3.js')) 27 | assert !File.exists?(File.join(@target, 'file4.js')) 28 | end 29 | end 30 | 31 | test "manifest gets written" do 32 | paths = [/file1\.js/] 33 | compiler = Sprocketize::Compiler.new(@env, @target, paths, {:manifest => true}) 34 | 35 | sandbox @target do 36 | compiler.compile 37 | 38 | assert File.exists?(File.join(@target, 'manifest.yml')) 39 | end 40 | end 41 | 42 | test "files get compressed" do 43 | paths = [/file1\.js/] 44 | compiler = Sprocketize::Compiler.new(@env, @target, paths, {:gzip => true}) 45 | 46 | sandbox @target do 47 | compiler.compile 48 | 49 | assert File.exists?(File.join(@target, 'file1.js.gz')) 50 | end 51 | end 52 | 53 | test "digest hash gets added to file names" do 54 | paths = [/file1\.js/] 55 | compiler1 = Sprocketize::Compiler.new(@env, @target, paths, {:digest => true}) 56 | compiler2 = Sprocketize::Compiler.new(@env, @target, paths, {:digest => false}) 57 | asset = @env.find_asset('file1.js') 58 | path1 = compiler1.path_for(asset) 59 | path2 = compiler2.path_for(asset) 60 | 61 | assert path1 != 'file1.js' 62 | assert path1.start_with?('file1-') 63 | assert path2 == 'file1.js' 64 | end 65 | end -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Sprocketize: Command-line utility for the [sprockets](http://getsprockets.com) gem [![Build Status](https://secure.travis-ci.org/matoilic/sprocketize.png)](http://travis-ci.org/matoilic/sprocketize) 2 | 3 | # Usage # 4 | 5 | Usage: sprocketize [options] output_directory filename [filename ...] 6 | -a, --asset-root=DIRECTORY Assets root path. 7 | -I, --include-dir=DIRECTORY Adds the directory to the Sprockets load path. 8 | -d, --digest Incorporates a MD5 digest into all filenames. 9 | -m, --manifest [=DIRECTORY] Writes a manifest for the assets. If no directory is 10 | specified the manifest will be written to the output directory. 11 | -g, --gzip Also create a compressed version of all Stylesheets and Javascripts. 12 | -s, --save Add given parameters to .sprocksrc 13 | -j [=COMPRESSOR], Compress all Javascript using either closure, yui or uglifier. If no 14 | compiler is specified closure will be used. 15 | --compress-javascripts 16 | -c, --compress-stylesheets Compress all Stylesheets with the YUI CSS compressor. 17 | -h, --help Show this help message. 18 | -v, --version Show version. 19 | 20 | The options can also be set through a local options file in the asset root or through a global file in your 21 | home directory. `target`, `assets` and `manifest_path` are ignored when set in the global file. 22 | 23 | #.sprocksrc 24 | --- 25 | target: target output directory 26 | paths: 27 | - include paths 28 | assets: 29 | - all files here will be compiled 30 | manifest: true or false 31 | manifest_path: output path for the manifest file 32 | digest: true or false 33 | gzip: true or false 34 | js_compressor: either closure, yui or uglifier 35 | compress_css: true or false 36 | 37 | Include paths should always be absolute. Asset paths are always relative to the asset root. The other paths can either 38 | be absolute or relative. Relative paths are always relative to the asset root. 39 | 40 | # License # 41 | 42 | Copyright © 2011 Mato Ilic <> 43 | 44 | Sprockets is distributed under an MIT-style license. See LICENSE for 45 | details. 46 | -------------------------------------------------------------------------------- /test/test_cli.rb: -------------------------------------------------------------------------------- 1 | require "sprocketize_test" 2 | require "yaml" 3 | 4 | class TestCLI < Sprocketize::TestCase 5 | test "options get saved" do 6 | sprockets_file = fixture_path('cli/' + Sprocketize::CLI::SPROCKETS_FILE) 7 | args = [ 8 | '-a', fixture_path('cli'), 9 | '-I', fixture_path('include'), 10 | '-I', fixture_path('compiler'), 11 | '-j', 'closure', 12 | '-c', 13 | '-d', 14 | '-g', 15 | '-m', fixture_path('.'), 16 | '-s', 17 | 'compiled', 18 | 'cli1.js', 19 | 'cli2.js' 20 | ] 21 | 22 | files = [ 23 | fixture_path('manifest.yml'), 24 | sprockets_file, 25 | fixture_path('cli/compiled') 26 | ] 27 | 28 | sandbox(*files) do 29 | cli = Sprocketize::CLI.new(*args) 30 | cli.run 31 | 32 | assert File.exists?(sprockets_file) 33 | 34 | options = YAML.load(File.open(sprockets_file)) 35 | 36 | assert_equal 2, options['paths'].length 37 | assert options['paths'].include?(fixture_path('include')) 38 | assert options['paths'].include?(fixture_path('compiler')) 39 | assert_equal :closure, options['js_compressor'] 40 | assert options['compress_css'] 41 | assert options['digest'] 42 | assert options['gzip'] 43 | assert options['manifest'] 44 | assert_equal fixture_path('.'), options['manifest_path'] 45 | assert_equal 'compiled', options['target'] 46 | assert_equal 2, options['assets'].length 47 | assert options['assets'].include?('cli1.js') 48 | assert options['assets'].include?('cli2.js') 49 | end 50 | end 51 | 52 | test "only given assets get compiled" do 53 | args = [ 54 | '-a', fixture_path('cli'), 55 | 'compiled', 56 | 'cli1.js' 57 | ] 58 | 59 | compiled_path = fixture_path('cli/compiled') 60 | 61 | sandbox compiled_path do 62 | cli = Sprocketize::CLI.new(*args) 63 | cli.run 64 | 65 | assert File.exists?(File.join(compiled_path, 'cli1.js')) 66 | assert !File.exists?(File.join(compiled_path, 'cli2.js')) 67 | end 68 | end 69 | 70 | test "local options file is loaded" do 71 | args = [ 72 | '-a', fixture_path('cli/sprockets_file') 73 | ] 74 | 75 | cli = Sprocketize::CLI.new(*args) 76 | 77 | assert cli.local_options[:assets].include?('cli_sprockets.js') 78 | assert_equal '../compiled', cli.local_options[:target] 79 | end 80 | 81 | test "global options file is loaded" do 82 | args = [ 83 | '-a', fixture_path('cli/sprockets_file') 84 | ] 85 | 86 | global_file = File.join(ENV['HOME'], Sprocketize::CLI::SPROCKETS_FILE) 87 | sandbox global_file do 88 | File.open(global_file, 'wb') do |f| 89 | YAML.dump({:paths => '/global/path'}, f) 90 | end 91 | 92 | cli = Sprocketize::CLI.new(*args) 93 | 94 | assert cli.global_options[:paths].include?('/global/path') 95 | end 96 | end 97 | end -------------------------------------------------------------------------------- /lib/sprocketize/cli.rb: -------------------------------------------------------------------------------- 1 | require 'optparse' 2 | require 'ostruct' 3 | require 'pathname' 4 | require 'set' 5 | require 'fileutils' 6 | require 'yaml' 7 | 8 | module Sprocketize 9 | class CLI 10 | SPROCKETS_FILE = '.sprocksrc' 11 | 12 | attr_accessor :local_options, :global_options 13 | 14 | def compile 15 | env = Sprockets::Environment.new(@root) 16 | env.js_compressor = expand_js_compressor(@local_options[:js_compressor]) 17 | env.css_compressor = expand_css_compressor(:yui) if @local_options[:compress_css] 18 | (@paths + (@global_options[:paths] || Set.new)).each {|p| env.append_path(p)} 19 | 20 | assets = local_options[:assets].map {|a| realpath(a).to_s} 21 | filter = Proc.new do |asset| 22 | assets.any? {|a| asset.pathname.to_s.start_with?(a)} 23 | end 24 | 25 | options = { 26 | :manifest => local_options[:manifest] || global_options[:manifest], 27 | :manifest_path => local_options[:manifest_path], 28 | :digest => local_options[:digest] || global_options[:digest], 29 | :gzip => local_options[:gzip] || global_options[:gzip] 30 | } 31 | 32 | compiler = Sprocketize::Compiler.new(env, realpath(@local_options[:target], true), [filter], options) 33 | compiler.compile 34 | end 35 | 36 | def initialize(*args) 37 | @assets = Set.new 38 | @local_paths = Set.new 39 | @global_options = load_global_options 40 | input = parse_input(args) 41 | @root = input.delete(:root) 42 | @save = input.delete(:save) 43 | @local_options = load_local_options(@root) 44 | @local_options = merge_options(load_local_options(@root), input) 45 | @local_options.freeze #to preserve exact user input 46 | end 47 | 48 | def merge_options(target, source) 49 | { 50 | :target => source[:target] || target[:target], 51 | :paths => (target[:paths] || Set.new).merge((source[:paths] || Set.new)), 52 | :assets => (target[:assets] || Set.new).merge((source[:assets] || Set.new)), 53 | :digest => (source[:digest].nil? ? target[:digest] : source[:digest]), 54 | :manifest => (source[:manifest].nil? ? target[:manifest] : source[:manifest]), 55 | :manifest_path => (source[:manifest_path] || target[:manifest_path]), 56 | :gzip => (source[:gzip].nil? ? target[:gzip] : source[:gzip]), 57 | :js_compressor => source[:js_compressor] || target[:js_compressor], 58 | :compress_css => source[:compress_css].nil? ? target[:compress_css] : source[:compress_css] 59 | } 60 | end 61 | 62 | def parser 63 | OptionParser.new do |opts| 64 | opts.banner = "Usage: sprocketize [options] output_directory filename [filename ...]" 65 | 66 | opts.on("-a DIRECTORY", "--asset-root=DIRECTORY", "Assets root path.") do |dir| 67 | exit_if_non_existent(dir) 68 | @input[:root] = realpath(dir) 69 | end 70 | 71 | opts.on("-I DIRECTORY", "--include-dir=DIRECTORY", "Adds the directory to the Sprockets load path.") do |dir| 72 | exit_if_non_existent(dir) 73 | @input[:paths] << dir 74 | end 75 | 76 | opts.on("-d", "--digest", "Incorporates a MD5 digest into all filenames.") do 77 | @input[:digest] = true 78 | end 79 | 80 | opts.on("-m [DIRECTORY]", "--manifest [=DIRECTORY]", "Writes a manifest for the assets. If no directory is specified the manifest will be written to the output directory.") do |dir| 81 | @input[:manifest] = true 82 | @input[:manifest_path] = dir 83 | end 84 | 85 | opts.on("-g", "--gzip", "Also create a compressed version of all Stylesheets and Javascripts.") do |dir| 86 | @input[:gzip] = true 87 | end 88 | 89 | opts.on("-s", "--save", "Add given parameters to #{SPROCKETS_FILE}") do |dir| 90 | @input[:save] = true 91 | end 92 | 93 | opts.on("-j [COMPRESSOR]", "--compress-javascripts [=COMPRESSOR]", "Compress all Javascript using either closure, yui or uglifier. If no compiler is specified closure will be used.") do |compressor| 94 | @input[:js_compressor] = (compressor || 'closure').to_sym 95 | end 96 | 97 | opts.on("-c", "--compress-stylesheets", "Compress all Stylesheets with the YUI CSS compressor.") do 98 | @input[:compress_css] = true 99 | end 100 | 101 | opts.on_tail("-h", "--help", "Show this help message.") do 102 | show_usage 103 | exit 104 | end 105 | 106 | opts.on_tail("-v", "--version", "Show version.") do 107 | show_version 108 | exit 109 | end 110 | end 111 | end 112 | 113 | def puts_error(message) 114 | puts "\e[31msprocketize: #{message}\e[0m" 115 | end 116 | 117 | def run 118 | if @local_options[:target].to_s.length == 0 119 | puts_error "no output directory provided" 120 | show_usage 121 | elsif @local_options[:assets].length == 0 122 | puts_error "no assets provided" 123 | show_usage 124 | elsif !([:closure, :uglifier, :yui, nil].include?(@local_options[:js_compressor])) 125 | puts_error "unsupported javascript processor #{@local_options[:js_compressor]}" 126 | show_usage 127 | else 128 | @paths = Set.new 129 | @local_options[:assets].each do |a| 130 | a = realpath(a) 131 | @paths << (a.file? ? a.dirname : a) 132 | end 133 | @local_options[:paths].each {|p| @paths << realpath(p)} 134 | 135 | compile 136 | save_local_options if @save 137 | end 138 | rescue OptionParser::InvalidOption => e 139 | puts_error e.message 140 | show_usage 141 | rescue Sprockets::FileNotFound => e 142 | puts_error e.message 143 | end 144 | 145 | def show_usage 146 | puts parser 147 | end 148 | 149 | def show_version 150 | puts Sprocketize::VERSION 151 | end 152 | 153 | private 154 | 155 | def exit_if_non_existent(path) 156 | return if File.exists?(path) 157 | puts_error "No such file or directory #{path}" 158 | exit 159 | end 160 | 161 | def expand_css_compressor(sym) 162 | case sym 163 | when :yui 164 | load_gem('yui/compressor', 'yui-compressor') 165 | YUI::CssCompressor.new 166 | else 167 | nil 168 | end 169 | end 170 | 171 | def expand_js_compressor(sym) 172 | case sym 173 | when :closure 174 | load_gem('closure-compiler') 175 | Closure::Compiler.new 176 | when :uglifier 177 | load_gem('uglifier') 178 | Uglifier.new 179 | when :yui 180 | load_gem('yui/compressor', 'yui-compressor') 181 | YUI::JavaScriptCompressor.new 182 | else 183 | nil 184 | end 185 | end 186 | 187 | def load_gem(require_path, gem_name = nil) 188 | begin 189 | require require_path 190 | rescue LoadError 191 | puts_error "required gem #{gem_name || require_path} not installed. please run `gem install #{gem_name || require_path}` to install it." 192 | exit 193 | end 194 | end 195 | 196 | def load_global_options 197 | return {} if ENV['HOME'].nil? 198 | file = Pathname.new(ENV['HOME']).join(SPROCKETS_FILE) 199 | 200 | load_options(file) 201 | end 202 | 203 | def load_local_options(root) 204 | file = root.join(SPROCKETS_FILE) 205 | 206 | load_options(file) 207 | end 208 | 209 | def load_options(file) 210 | return {} unless file.exist? 211 | 212 | raw = YAML.load(File.open(file)) 213 | 214 | options = {} 215 | raw.each_pair do |key, value| 216 | options[key.to_sym] = value 217 | end 218 | 219 | options[:assets] = options[:assets].to_set if options[:assets].respond_to?(:to_set) 220 | options[:paths] = options[:paths].to_set if options[:paths].respond_to?(:to_set) 221 | options[:js_compressor] = options[:js_compressor].to_sym unless options[:js_compressor].nil? 222 | 223 | options 224 | end 225 | 226 | def parse_input(args) 227 | @input = { 228 | :root => Pathname.new('.'), 229 | :paths => Set.new, 230 | :assets => [] 231 | } 232 | 233 | parser.order(args) {|a| @input[:assets] << a} 234 | @input[:target] = @input[:assets].shift 235 | @input[:assets] = @input[:assets].to_set 236 | 237 | @input 238 | end 239 | 240 | def realpath(path, create = false) 241 | path = Pathname.new(path) 242 | path = Pathname.new(@root).join(path) unless path.absolute? 243 | 244 | FileUtils.mkdir_p(path) if create 245 | 246 | path.realpath 247 | end 248 | 249 | def save_local_options 250 | File.open(@root.join(SPROCKETS_FILE), 'wb') do |f| 251 | YAML.dump({ 252 | 'target' => @local_options[:target], 253 | 'paths' => (@local_options[:paths] || Set.new).to_a.map {|p| p.to_s}, 254 | 'assets' => @local_options[:assets].to_a.map {|a| a.to_s}, 255 | 'manifest' => @local_options[:manifest] || false, 256 | 'manifest_path' => @local_options[:manifest_path], 257 | 'digest' => @local_options[:digest] || false, 258 | 'gzip' => @local_options[:gzip] || false, 259 | 'js_compressor' => @local_options[:js_compressor], 260 | 'compress_css' => @local_options[:compress_css] || false 261 | }, f) 262 | end 263 | end 264 | end 265 | end --------------------------------------------------------------------------------