front-end-blender 0.23 → 0.24
Sign up to get free protection for your applications and to get access to all the features.
- data/README.txt +17 -13
- data/bin/blend +21 -12
- data/lib/front_end_architect/blender.rb +77 -67
- metadata +2 -2
data/README.txt
CHANGED
@@ -35,18 +35,22 @@ source files are the hash values as an array. Here is a sample Blendfile:
|
|
35
35
|
== Usage
|
36
36
|
|
37
37
|
Usage: blend [options]
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
38
|
+
-g, --generate Generate a stub Blendfile
|
39
|
+
-f, --file FILE Use specified Blendfile
|
40
|
+
-r, --root ROOT Specify the path to the web root directory
|
41
|
+
-t, --type TYPE Select file type to blend (css, js)
|
42
|
+
-m, --min [MINIFIER] Select minifier to use (yui, none)
|
43
|
+
-c, --cache-buster [BUSTER] Add cache busters to URLs in CSS
|
44
|
+
--force Don't allow output files to be skipped
|
45
|
+
--yui=YUIOPTS Pass arguments to YUI Compressor
|
46
|
+
|
47
|
+
Experimental:
|
48
|
+
-d, --data Convert url(file.ext) to url(data:) in CSS
|
49
|
+
-z, --gzip Additionally generate gzipped output files
|
50
|
+
|
51
|
+
Meta:
|
52
|
+
-h, --help Show this message
|
53
|
+
-V, --version Show the version number
|
50
54
|
|
51
55
|
== Examples
|
52
56
|
|
@@ -65,7 +69,7 @@ Other examples:
|
|
65
69
|
To install the RubyGem, run the following at the command line (you may need to use a command such as su or sudo):
|
66
70
|
gem install blender
|
67
71
|
|
68
|
-
If you're using Windows, you'll also
|
72
|
+
If you're using Windows, you'll also want to run the following to get colored command line output:
|
69
73
|
gem install win32console
|
70
74
|
|
71
75
|
* Java[http://java.com/en/] v1.4 or greater is required
|
data/bin/blend
CHANGED
@@ -11,19 +11,28 @@ require 'front_end_architect/blender'
|
|
11
11
|
|
12
12
|
options = {}
|
13
13
|
|
14
|
+
def section(opts, title)
|
15
|
+
opts.separator ''
|
16
|
+
opts.separator title + ':'
|
17
|
+
end
|
18
|
+
|
14
19
|
opts = OptionParser.new do |opts|
|
15
|
-
|
16
|
-
|
17
|
-
opts.on('-g',
|
18
|
-
opts.on('-f FILE',
|
19
|
-
opts.on('-r ROOT',
|
20
|
-
opts.on('-t TYPE',
|
21
|
-
opts.on('-m [MINIFIER]',
|
22
|
-
opts.on('-c [BUSTER]',
|
23
|
-
opts.on(
|
24
|
-
opts.on(
|
25
|
-
opts
|
26
|
-
opts.on('-
|
20
|
+
version = "Front-End Blender v#{FrontEndArchitect::Blender::VERSION}"
|
21
|
+
|
22
|
+
opts.on('-g', '--generate', String, "Generate a stub Blendfile") { options[:generate] = true }
|
23
|
+
opts.on('-f FILE', '--file FILE', String, "Use specified Blendfile") {|f| options[:blendfile] = f; options[:root] = File.dirname(f) }
|
24
|
+
opts.on('-r ROOT', '--root ROOT', String, "Specify the path to the web root directory") {|r| options[:root] = r }
|
25
|
+
opts.on('-t TYPE', '--type TYPE', [:css, :js], "Select file type to blend (css, js)") {|t| options[:file_type] = t }
|
26
|
+
opts.on('-m [MINIFIER]', '--min [MINIFIER]', [:yui, :none], "Select minifier to use (yui, none)") {|m| options[:min] = m.nil? ? :none : m.to_sym }
|
27
|
+
opts.on('-c [BUSTER]', '--cache-buster [BUSTER]', String, "Add cache busters to URLs in CSS") {|b| options[:cache_buster] = b.nil? ? :mtime : b }
|
28
|
+
opts.on( '--force', String, "Don't allow output files to be skipped") { options[:force] = true }
|
29
|
+
opts.on( '--yui=YUIOPTS', String, "Pass arguments to YUI Compressor") {|o| options[:yuiopts] = o }
|
30
|
+
section opts, 'Experimental'
|
31
|
+
opts.on('-d', '--data', String, "Convert url(file.ext) to url(data:) in CSS") { options[:data] = true }
|
32
|
+
opts.on('-z', '--gzip', String, "Additionally generate gzipped output files") { options[:gzip] = true }
|
33
|
+
section opts, 'Meta'
|
34
|
+
opts.on('-h', '--help', "Show this message") { puts opts; exit 0 }
|
35
|
+
opts.on('-V', '--version', "Show the version number") { puts version; exit 0 }
|
27
36
|
|
28
37
|
opts.parse!(ARGV) rescue return false
|
29
38
|
end
|
@@ -6,29 +6,31 @@
|
|
6
6
|
$:.unshift File.join(File.dirname(File.symlink?(__FILE__) ? File.readlink(__FILE__) : __FILE__), *%w[..])
|
7
7
|
|
8
8
|
require 'rubygems'
|
9
|
-
|
9
|
+
|
10
10
|
require 'base64'
|
11
11
|
require 'benchmark'
|
12
12
|
require 'colored' unless PLATFORM =~ /win32/ && !Gem.available?('win32console')
|
13
|
-
require 'mime/types'
|
14
13
|
require 'find'
|
14
|
+
require 'mime/types'
|
15
15
|
require 'pathname'
|
16
16
|
require 'zlib'
|
17
|
+
require 'yaml'
|
18
|
+
|
17
19
|
require 'front_end_architect/hash'
|
18
20
|
|
19
21
|
module FrontEndArchitect
|
20
22
|
class Blender
|
21
|
-
VERSION = '0.
|
23
|
+
VERSION = '0.24'
|
22
24
|
|
23
|
-
|
24
|
-
IMPORT_REGEX = /@import(?: url\(| )(['"]?)([^\?'"\)\s]+)(\?(?:[^'"\)]+)?)?\1\)?(?:[^?;]+)?;/im
|
25
|
+
ALPHA_REGEX = /(-ms-)?filter:\s*(['"]?)progid:DXImageTransform\.Microsoft\.AlphaImageLoader\(\s*src=(['"])([^\?'"\)]+)(\?(?:[^'"\)]+)?)?\3,\s*sizingMethod=(['"])(image|scale|crop)\6\s*\)\2/im
|
26
|
+
IMPORT_REGEX = /@import(?: url\(| )(['"]?)([^\?'"\)\s]+)(\?(?:[^'"\)]+)?)?\1\)?(?:[^?;]+)?;/im # shouldn't the semicolon be optional?
|
25
27
|
URL_REGEX = /url\((['"]?)([^\?'"\)]+)(\?(?:[^'"\)]+)?)?\1?\)/im
|
26
28
|
|
27
29
|
DEFAULT_OPTIONS = {
|
28
30
|
:blendfile => 'Blendfile.yaml',
|
29
31
|
:data => false,
|
30
32
|
:force => false,
|
31
|
-
:root => File.dirname(
|
33
|
+
:root => File.dirname('Blendfile.yaml'),
|
32
34
|
:min => :yui,
|
33
35
|
:colored => (Object.const_defined? :Colored),
|
34
36
|
}
|
@@ -220,11 +222,14 @@ module FrontEndArchitect
|
|
220
222
|
if @options[:data]
|
221
223
|
if File.extname(output_name).downcase == '.css'
|
222
224
|
output = output.gsub(URL_REGEX) do
|
223
|
-
|
224
|
-
|
225
|
-
|
225
|
+
url = $2
|
226
|
+
query = $3
|
227
|
+
|
228
|
+
unless url.downcase.include?('.css')
|
229
|
+
mime_type = MIME::Types.type_for(url)
|
230
|
+
url_contents = make_data_uri(IO.read(url), mime_type[0])
|
226
231
|
else
|
227
|
-
url_contents =
|
232
|
+
url_contents = url
|
228
233
|
end
|
229
234
|
%Q!url(#{url_contents})!
|
230
235
|
end
|
@@ -257,45 +262,50 @@ module FrontEndArchitect
|
|
257
262
|
|
258
263
|
# Find filter statements and append cache busters to URLs
|
259
264
|
if @options[:cache_buster]
|
260
|
-
input = input.gsub(
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
265
|
+
input = input.gsub(ALPHA_REGEX) do |alpha|
|
266
|
+
prefix = $1
|
267
|
+
outter_quote = $2
|
268
|
+
inner_quote1 = $3
|
269
|
+
url = $4
|
270
|
+
query = $5
|
271
|
+
inner_quote2 = $6
|
272
|
+
sizing = $7
|
273
|
+
|
274
|
+
# TODO Rewrite to root relative (if :root specified?)
|
275
|
+
|
276
|
+
unless url.match(/^(https:\/\/|http:\/\/|\/\/)/i)
|
277
|
+
full_path = File.expand_path(url, File.dirname(input_file))
|
278
|
+
query = make_cache_buster(full_path, query)
|
271
279
|
end
|
280
|
+
|
281
|
+
"#{prefix}filter:#{outter_quote}progid:DXImageTransform.Microsoft.AlphaImageLoader(src=#{inner_quote1}#{url}#{query}#{inner_quote1},sizingMethod=#{inner_quote2}#{sizing}#{inner_quote2})#{outter_quote}"
|
272
282
|
end
|
273
283
|
end
|
274
284
|
|
275
285
|
# Handle @import statements URL rewrite and adding cache busters
|
276
286
|
input = input.gsub(IMPORT_REGEX) do |import|
|
277
|
-
|
278
|
-
|
287
|
+
url = $2
|
288
|
+
query = $3
|
289
|
+
asset_path = Pathname.new(File.expand_path(url, input_path))
|
279
290
|
|
280
|
-
if
|
281
|
-
asset_path = Pathname.new(File.join(File.expand_path(@options[:root]),
|
291
|
+
if url.match(/^(\/[^\/]+.+)$/)
|
292
|
+
asset_path = Pathname.new(File.join(File.expand_path(@options[:root]), url))
|
282
293
|
end
|
283
294
|
|
284
|
-
unless
|
295
|
+
unless url.match(/^(https:\/\/|http:\/\/|\/\/)/i)
|
285
296
|
if (output_path != input_path)
|
286
|
-
|
287
297
|
new_path = asset_path.relative_path_from(output_path)
|
288
298
|
|
289
299
|
if @options[:cache_buster]
|
290
|
-
buster = make_cache_buster(asset_path,
|
291
|
-
import.gsub!(
|
300
|
+
buster = make_cache_buster(asset_path, query)
|
301
|
+
import.gsub!(url, new_path.to_s + buster)
|
292
302
|
else
|
293
|
-
import.gsub!(
|
303
|
+
import.gsub!(url, new_path)
|
294
304
|
end
|
295
305
|
else
|
296
306
|
if @options[:cache_buster]
|
297
|
-
buster = make_cache_buster(asset_path,
|
298
|
-
import.gsub!(
|
307
|
+
buster = make_cache_buster(asset_path, query)
|
308
|
+
import.gsub!(url, asset_path.to_s + buster)
|
299
309
|
end
|
300
310
|
end
|
301
311
|
end
|
@@ -308,39 +318,39 @@ module FrontEndArchitect
|
|
308
318
|
if output_path == input_path
|
309
319
|
if @options[:data]
|
310
320
|
input = input.gsub(URL_REGEX) do
|
311
|
-
|
312
|
-
|
321
|
+
url = $2
|
322
|
+
query = $3
|
313
323
|
|
314
|
-
unless
|
315
|
-
new_path = File.expand_path(
|
324
|
+
unless url.match(/^(https:\/\/|http:\/\/|\/\/)/i)
|
325
|
+
new_path = File.expand_path(url, File.dirname(input_file))
|
316
326
|
|
317
|
-
if
|
318
|
-
new_path = Pathname.new(File.join(File.expand_path(@options[:root]),
|
327
|
+
if url.match(/^(\/[^\/]+.+)$/)
|
328
|
+
new_path = Pathname.new(File.join(File.expand_path(@options[:root]), url))
|
319
329
|
end
|
320
330
|
|
321
331
|
%Q!url(#{new_path})!
|
322
332
|
else
|
323
|
-
%Q!url(#{
|
333
|
+
%Q!url(#{url}#{query})!
|
324
334
|
end
|
325
335
|
end
|
326
336
|
elsif @options[:cache_buster]
|
327
337
|
input = input.gsub(URL_REGEX) do
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
if
|
333
|
-
|
338
|
+
url = $2
|
339
|
+
query = $3
|
340
|
+
|
341
|
+
unless url.match(/^(https:\/\/|http:\/\/|\/\/)/i)
|
342
|
+
if url.match(/^(\/[^\/]+.+)$/)
|
343
|
+
url = Pathname.new(File.join(File.expand_path(@options[:root]), url))
|
334
344
|
end
|
335
345
|
|
336
346
|
if @options[:cache_buster]
|
337
|
-
buster = make_cache_buster(
|
338
|
-
new_path =
|
347
|
+
buster = make_cache_buster(url, query)
|
348
|
+
new_path = url.to_s + buster
|
339
349
|
end
|
340
350
|
|
341
351
|
%Q!url(#{new_path})!
|
342
352
|
else
|
343
|
-
%Q!url(#{
|
353
|
+
%Q!url(#{url}#{query})!
|
344
354
|
end
|
345
355
|
end
|
346
356
|
end
|
@@ -349,37 +359,37 @@ module FrontEndArchitect
|
|
349
359
|
else
|
350
360
|
# Find all url(.ext) in file and rewrite relative url from output directory.
|
351
361
|
input = input.gsub(URL_REGEX) do
|
352
|
-
|
353
|
-
|
362
|
+
url = $2
|
363
|
+
query = $3
|
354
364
|
|
355
|
-
unless
|
365
|
+
unless url.match(/^(https:\/\/|http:\/\/|\/\/)/i)
|
356
366
|
if @options[:data]
|
357
367
|
# if doing data conversion rewrite url as an absolute path
|
358
|
-
new_path = File.expand_path(
|
368
|
+
new_path = File.expand_path(url, File.dirname(input_file))
|
359
369
|
|
360
|
-
if
|
361
|
-
new_path = Pathname.new(File.join(File.expand_path(@options[:root]),
|
370
|
+
if url.match(/^(\/[^\/]+.+)$/)
|
371
|
+
new_path = Pathname.new(File.join(File.expand_path(@options[:root]), url))
|
362
372
|
end
|
363
373
|
else
|
364
|
-
asset_path = Pathname.new(File.expand_path(
|
374
|
+
asset_path = Pathname.new(File.expand_path(url, File.dirname(input_file)))
|
365
375
|
|
366
|
-
if
|
367
|
-
asset_path = Pathname.new(File.join(File.expand_path(@options[:root]),
|
376
|
+
if url.match(/^(\/[^\/]+.+)$/)
|
377
|
+
asset_path = Pathname.new(File.join(File.expand_path(@options[:root]), url))
|
368
378
|
end
|
369
379
|
|
370
380
|
new_path = asset_path.relative_path_from(output_path)
|
371
381
|
|
372
382
|
if @options[:cache_buster]
|
373
|
-
buster = make_cache_buster(asset_path,
|
374
|
-
new_path = new_path.to_s+buster
|
383
|
+
buster = make_cache_buster(asset_path, query)
|
384
|
+
new_path = new_path.to_s + buster
|
375
385
|
else
|
376
|
-
new_path = new_path.to_s
|
386
|
+
new_path = new_path.to_s + query unless query.nil?
|
377
387
|
end
|
378
388
|
end
|
379
389
|
|
380
390
|
%Q!url(#{new_path})!
|
381
391
|
else
|
382
|
-
%Q!url(#{
|
392
|
+
%Q!url(#{url}#{query})!
|
383
393
|
end
|
384
394
|
end
|
385
395
|
|
@@ -387,18 +397,18 @@ module FrontEndArchitect
|
|
387
397
|
end
|
388
398
|
end
|
389
399
|
|
390
|
-
def make_cache_buster(asset_path,
|
391
|
-
unless
|
392
|
-
|
400
|
+
def make_cache_buster(asset_path, query)
|
401
|
+
unless query.nil?
|
402
|
+
query += '&'
|
393
403
|
else
|
394
|
-
|
404
|
+
query = '?'
|
395
405
|
end
|
396
406
|
|
397
407
|
if @options[:cache_buster] == :mtime
|
398
408
|
file_mtime = File.mtime(asset_path).to_i
|
399
|
-
buster =
|
409
|
+
buster = query + file_mtime.to_s
|
400
410
|
else
|
401
|
-
buster =
|
411
|
+
buster = query + @options[:cache_buster]
|
402
412
|
end
|
403
413
|
|
404
414
|
return buster
|
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.24"
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Blake Elshire
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2008-
|
13
|
+
date: 2008-12-08 00:00:00 -08:00
|
14
14
|
default_executable: blend
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|