front-end-blender 0.14 → 0.16
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +1 -0
- data/bin/blend +12 -11
- data/lib/front_end_architect/blender.rb +54 -35
- metadata +12 -3
data/README.rdoc
CHANGED
@@ -41,6 +41,7 @@ source files are the hash values as an array. Here is a sample Blendfile:
|
|
41
41
|
-f, --file FILE Use given Blendfile
|
42
42
|
-r, --root ROOT Specify the path to the web root directory
|
43
43
|
-t, --type TYPE Select file type to blend (css, js)
|
44
|
+
-m, --min [MINIFIER] Select minifier to use (yui, none)
|
44
45
|
-c, --cache-buster [BUSTER] Append cache busters to URLs in CSS, defaults to timestamps
|
45
46
|
--force Force blending when source files aren't newer than output files
|
46
47
|
--yui=YUIOPTS Pass arguments to YUI Compressor
|
data/bin/blend
CHANGED
@@ -13,17 +13,18 @@ require 'front_end_architect/blender'
|
|
13
13
|
options = {}
|
14
14
|
|
15
15
|
opts = OptionParser.new do |opts|
|
16
|
-
opts.on('-h', '--help',
|
17
|
-
opts.on('-V', '--version',
|
18
|
-
opts.on('-g', '--generate', String,
|
19
|
-
opts.on('-f FILE', '--file FILE', String,
|
20
|
-
opts.on('-r ROOT', '--root ROOT', String,
|
21
|
-
opts.on('-t TYPE', '--type TYPE', [:css, :js],
|
22
|
-
opts.on('-
|
23
|
-
opts.on(
|
24
|
-
opts.on( '--
|
25
|
-
opts.on('
|
26
|
-
opts.on('-
|
16
|
+
opts.on('-h', '--help', "Show this message") { puts opts; exit 0 }
|
17
|
+
opts.on('-V', '--version', "Show the version number") { puts "Front-End Blender v#{Blender::VERSION}"; exit 0 }
|
18
|
+
opts.on('-g', '--generate', String, "Generate a stub Blendfile") { options[:generate] = true }
|
19
|
+
opts.on('-f FILE', '--file FILE', String, "Use given Blendfile") {|f| options[:blendfile] = f }
|
20
|
+
opts.on('-r ROOT', '--root ROOT', String, "Set the path to the web root directory") {|r| options[:root] = r }
|
21
|
+
opts.on('-t TYPE', '--type TYPE', [:css, :js], "Select file type to blend (css, js)") {|t| options[:file_type] = t }
|
22
|
+
opts.on('-m [MINIFIER]', '--min [MINIFIER]', [:yui, :none], "Select minifier to use (yui, none)") {|m| options[:min] = m.nil? ? :none : m.to_sym }
|
23
|
+
opts.on('-c [BUSTER]', '--cache-buster [BUSTER]', String, "Append cache busters to URLs in CSS, defaults to timestamps") {|b| options[:cache_buster] = b.nil? ? :mtime : b }
|
24
|
+
opts.on( '--force', String, "Force blending when source files aren't newer than output files") { options[:force] = true }
|
25
|
+
opts.on( '--yui=YUIOPTS', String, "Pass arguments to YUI Compressor") {|o| options[:yuiopts] = o }
|
26
|
+
opts.on('-d', '--data', String, "EXPERIMENTAL Convert url(file.ext) to url(data:) in CSS files") { options[:data] = true }
|
27
|
+
opts.on('-z', '--gzip', String, "EXPERIMENTAL Also create gzip output files") { options[:gzip] = true }
|
27
28
|
|
28
29
|
opts.parse!(ARGV) rescue return false
|
29
30
|
end
|
@@ -12,6 +12,7 @@ require 'rubygems'
|
|
12
12
|
require 'yaml'
|
13
13
|
require 'base64'
|
14
14
|
require 'benchmark'
|
15
|
+
require 'colored'
|
15
16
|
require 'mime/types'
|
16
17
|
require 'find'
|
17
18
|
require 'pathname'
|
@@ -20,7 +21,7 @@ require 'front_end_architect/hash'
|
|
20
21
|
|
21
22
|
module FrontEndArchitect
|
22
23
|
class Blender
|
23
|
-
VERSION = '0.
|
24
|
+
VERSION = '0.16'
|
24
25
|
|
25
26
|
FILTER_REGEX = /filter: ?[^?]+\(src=(['"])([^\?'"]+)(\?(?:[^'"]+)?)?\1,[^?]+\1\);/im
|
26
27
|
IMPORT_REGEX = /@import(?: url\(| )(['"]?)([^\?'"\)\s]+)(\?(?:[^'"\)]+)?)?\1\)?(?:[^?;]+)?;/im
|
@@ -31,6 +32,7 @@ module FrontEndArchitect
|
|
31
32
|
:data => false,
|
32
33
|
:force => false,
|
33
34
|
:root => File.dirname(:blendfile.to_s),
|
35
|
+
:min => :yui,
|
34
36
|
}
|
35
37
|
|
36
38
|
def initialize(opts)
|
@@ -75,10 +77,15 @@ module FrontEndArchitect
|
|
75
77
|
end
|
76
78
|
|
77
79
|
if output_new || @options[:force]
|
78
|
-
|
80
|
+
if File.writable?(output_name) && !(@options[:gzip] && !File.writable?(gzip_output_name))
|
81
|
+
create_output(output_name, sources, file_type)
|
82
|
+
else
|
83
|
+
puts "Permission Denied:".white_on_red + " " + output_name.red
|
84
|
+
puts "Permission Denied:".white_on_red + " " + gzip_output_name.red if @options[:gzip]
|
85
|
+
end
|
79
86
|
else
|
80
|
-
puts "Skipping:
|
81
|
-
puts "Skipping:
|
87
|
+
puts "Skipping: ".yellow + output_name.yellow
|
88
|
+
puts "Skipping: ".yellow + gzip_output_name.yellow if @options[:gzip]
|
82
89
|
end
|
83
90
|
else
|
84
91
|
create_output(output_name, sources, file_type)
|
@@ -144,7 +151,11 @@ module FrontEndArchitect
|
|
144
151
|
prefix += File::SEPARATOR unless context.empty?
|
145
152
|
|
146
153
|
value.each_index do |i|
|
147
|
-
value[i]
|
154
|
+
unless value[i].match(/^(\/[^\/]+.+)$/)
|
155
|
+
value[i] = prefix + value[i]
|
156
|
+
else
|
157
|
+
value[i] = @options[:root] + value[i]
|
158
|
+
end
|
148
159
|
end
|
149
160
|
|
150
161
|
return { (prefix + key) => value }
|
@@ -175,40 +186,45 @@ module FrontEndArchitect
|
|
175
186
|
end
|
176
187
|
|
177
188
|
# Compress
|
178
|
-
|
179
|
-
|
180
|
-
IO.popen("java -jar #{libdir}/yui/yuicompressor.jar #{@options[:yuiopts]} --type #{type}", 'r+') do |io|
|
181
|
-
io.write output
|
182
|
-
io.close_write
|
183
|
-
|
184
|
-
output = io.read
|
189
|
+
if @options[:min] == :yui
|
190
|
+
libdir = File.join(File.dirname(File.symlink?(__FILE__) ? File.readlink(__FILE__) : __FILE__), *%w[.. .. lib])
|
185
191
|
|
186
|
-
|
187
|
-
|
188
|
-
|
192
|
+
IO.popen("java -jar #{libdir}/yui/yuicompressor.jar #{@options[:yuiopts]} --type #{type}", 'r+') do |io|
|
193
|
+
io.write output
|
194
|
+
io.close_write
|
189
195
|
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
else
|
196
|
-
url_contents = $2
|
197
|
-
end
|
198
|
-
%Q!url(#{url_contents})!
|
199
|
-
end
|
196
|
+
output = io.read
|
197
|
+
|
198
|
+
if File.extname(output_name) == '.css'
|
199
|
+
output.gsub! ' and(', ' and (' # Workaround for YUI Compressor Bug #1938329
|
200
|
+
output.gsub! '*/;}', '*/}' # Workaround for YUI Compressor Bug #1961175
|
200
201
|
end
|
201
202
|
end
|
202
203
|
|
203
|
-
|
204
|
+
if $? == 32512 # command not found
|
205
|
+
raise "\nBlender requires Java, v1.4 or greater, to be installed for YUI Compressor"
|
206
|
+
end
|
204
207
|
end
|
205
208
|
|
206
|
-
|
207
|
-
|
209
|
+
# Data
|
210
|
+
if @options[:data]
|
211
|
+
if File.extname(output_name) == '.css'
|
212
|
+
output = output.gsub(URL_REGEX) do
|
213
|
+
unless $2.include?('.css')
|
214
|
+
mime_type = MIME::Types.type_for($2)
|
215
|
+
url_contents = make_data_uri(IO.read($2), mime_type[0])
|
216
|
+
else
|
217
|
+
url_contents = $2
|
218
|
+
end
|
219
|
+
%Q!url(#{url_contents})!
|
220
|
+
end
|
221
|
+
end
|
208
222
|
end
|
223
|
+
|
224
|
+
output_file << output
|
209
225
|
end
|
210
226
|
|
211
|
-
puts output_name
|
227
|
+
puts output_name.green
|
212
228
|
|
213
229
|
if @options[:gzip]
|
214
230
|
output_gzip = output_name + '.gz'
|
@@ -217,7 +233,7 @@ module FrontEndArchitect
|
|
217
233
|
gz.write(output)
|
218
234
|
end
|
219
235
|
|
220
|
-
puts output_gzip
|
236
|
+
puts output_gzip.green
|
221
237
|
end
|
222
238
|
end
|
223
239
|
|
@@ -232,6 +248,7 @@ module FrontEndArchitect
|
|
232
248
|
if @options[:cache_buster]
|
233
249
|
input = input.gsub(FILTER_REGEX) do |filter|
|
234
250
|
uri = $2
|
251
|
+
cbuster = $3
|
235
252
|
unless uri.match(/^(https:\/\/|http:\/\/|\/\/)/)
|
236
253
|
full_path = File.expand_path($2, File.dirname(input_file))
|
237
254
|
buster = make_cache_buster(full_path, $3)
|
@@ -239,7 +256,7 @@ module FrontEndArchitect
|
|
239
256
|
|
240
257
|
%Q!filter='#{new_path}'!
|
241
258
|
else
|
242
|
-
%Q!filter='#{
|
259
|
+
%Q!filter='#{uri}#{cbuster}'!
|
243
260
|
end
|
244
261
|
end
|
245
262
|
end
|
@@ -281,6 +298,7 @@ module FrontEndArchitect
|
|
281
298
|
if @options[:data]
|
282
299
|
input = input.gsub(URL_REGEX) do
|
283
300
|
uri = $2
|
301
|
+
cbuster = $3
|
284
302
|
|
285
303
|
unless uri.match(/^(https:\/\/|http:\/\/|\/\/)/)
|
286
304
|
new_path = File.expand_path($2, File.dirname(input_file))
|
@@ -290,13 +308,14 @@ module FrontEndArchitect
|
|
290
308
|
|
291
309
|
%Q!url(#{new_path})!
|
292
310
|
else
|
293
|
-
%Q!url(#{
|
311
|
+
%Q!url(#{uri}#{cbuster})!
|
294
312
|
end
|
295
313
|
end
|
296
314
|
elsif @options[:cache_buster]
|
297
315
|
input = input.gsub(URL_REGEX) do
|
298
316
|
unless uri.match(/^(https:\/\/|http:\/\/|\/\/)/)
|
299
317
|
uri = $2
|
318
|
+
cbuster = $3
|
300
319
|
|
301
320
|
if uri.match(/^(\/[^\/]+.+)$/)
|
302
321
|
uri = Pathname.new(File.join(File.expand_path(@options[:root]), uri))
|
@@ -309,7 +328,7 @@ module FrontEndArchitect
|
|
309
328
|
|
310
329
|
%Q!url(#{new_path})!
|
311
330
|
else
|
312
|
-
%Q!url(#{
|
331
|
+
%Q!url(#{uri}#{cbuster})!
|
313
332
|
end
|
314
333
|
end
|
315
334
|
end
|
@@ -319,7 +338,7 @@ module FrontEndArchitect
|
|
319
338
|
# Find all url(.ext) in file and rewrite relative url from output directory.
|
320
339
|
input = input.gsub(URL_REGEX) do
|
321
340
|
uri = $2
|
322
|
-
|
341
|
+
cbuster = $3
|
323
342
|
unless uri.match(/^(https:\/\/|http:\/\/|\/\/)/)
|
324
343
|
if @options[:data]
|
325
344
|
# if doing data conversion rewrite url as an absolute path.
|
@@ -347,7 +366,7 @@ module FrontEndArchitect
|
|
347
366
|
|
348
367
|
%Q!url(#{new_path})!
|
349
368
|
else
|
350
|
-
%Q!url(#{
|
369
|
+
%Q!url(#{uri}#{cbuster})!
|
351
370
|
end
|
352
371
|
end
|
353
372
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: front-end-blender
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: "0.
|
4
|
+
version: "0.16"
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Blake Elshire & Chris Griego
|
@@ -9,7 +9,7 @@ autorequire: front_end_architect/blend
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2008-
|
12
|
+
date: 2008-09-17 00:00:00 -07:00
|
13
13
|
default_executable: blend
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -21,6 +21,15 @@ dependencies:
|
|
21
21
|
- !ruby/object:Gem::Version
|
22
22
|
version: "1.15"
|
23
23
|
version:
|
24
|
+
- !ruby/object:Gem::Dependency
|
25
|
+
name: colored
|
26
|
+
version_requirement:
|
27
|
+
version_requirements: !ruby/object:Gem::Requirement
|
28
|
+
requirements:
|
29
|
+
- - ">="
|
30
|
+
- !ruby/object:Gem::Version
|
31
|
+
version: "1.1"
|
32
|
+
version:
|
24
33
|
description: Blender is like ant or make for the front-end. It aggregates and compresses CSS and/or JavaScript assets for a site into efficient, production-ready files.
|
25
34
|
email: belshire@gmail.com
|
26
35
|
executables:
|
@@ -59,7 +68,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
59
68
|
requirements:
|
60
69
|
- Java, v1.4 or greater
|
61
70
|
rubyforge_project: frontendblender
|
62
|
-
rubygems_version: 1.0
|
71
|
+
rubygems_version: 1.2.0
|
63
72
|
signing_key:
|
64
73
|
specification_version: 2
|
65
74
|
summary: Blender gives you efficient, production-ready CSS and/or JavaScript assets.
|