sprocketize 0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/LICENSE +20 -0
- data/README.md +45 -0
- data/bin/sprocketize +5 -0
- data/lib/sprocketize.rb +7 -0
- data/lib/sprocketize/cli.rb +265 -0
- data/lib/sprocketize/compiler.rb +61 -0
- data/lib/sprocketize/version.rb +3 -0
- metadata +87 -0
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
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.
|
data/README.md
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
# Sprocketize: Command-line utility for the [sprockets](http://getsprockets.com) gem [](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 <<info@matoilic.ch>>
|
43
|
+
|
44
|
+
Sprockets is distributed under an MIT-style license. See LICENSE for
|
45
|
+
details.
|
data/bin/sprocketize
ADDED
data/lib/sprocketize.rb
ADDED
@@ -0,0 +1,265 @@
|
|
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
|
@@ -0,0 +1,61 @@
|
|
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
|
metadata
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sprocketize
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: '0.1'
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Mato Ilic
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2011-12-11 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: sprockets
|
16
|
+
requirement: &70169800278780 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 2.1.2
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *70169800278780
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: rake
|
27
|
+
requirement: &70169800278220 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
33
|
+
type: :development
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *70169800278220
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: closure-compiler
|
38
|
+
requirement: &70169800277620 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
44
|
+
type: :development
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *70169800277620
|
47
|
+
description: Sprocketize provides a command-line utility for the sprockets gem so
|
48
|
+
it can be used without rails.
|
49
|
+
email:
|
50
|
+
- info@matoilic.ch
|
51
|
+
executables:
|
52
|
+
- sprocketize
|
53
|
+
extensions: []
|
54
|
+
extra_rdoc_files: []
|
55
|
+
files:
|
56
|
+
- README.md
|
57
|
+
- LICENSE
|
58
|
+
- lib/sprocketize/cli.rb
|
59
|
+
- lib/sprocketize/compiler.rb
|
60
|
+
- lib/sprocketize/version.rb
|
61
|
+
- lib/sprocketize.rb
|
62
|
+
- bin/sprocketize
|
63
|
+
homepage: http://github.com/matoilic/sprocketize
|
64
|
+
licenses: []
|
65
|
+
post_install_message:
|
66
|
+
rdoc_options: []
|
67
|
+
require_paths:
|
68
|
+
- lib
|
69
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
70
|
+
none: false
|
71
|
+
requirements:
|
72
|
+
- - ! '>='
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '0'
|
75
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
76
|
+
none: false
|
77
|
+
requirements:
|
78
|
+
- - ! '>='
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
version: '0'
|
81
|
+
requirements: []
|
82
|
+
rubyforge_project:
|
83
|
+
rubygems_version: 1.8.12
|
84
|
+
signing_key:
|
85
|
+
specification_version: 3
|
86
|
+
summary: Command-line utility for the Sprockets gem
|
87
|
+
test_files: []
|