front-end-blender 0.23 → 0.24
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/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
|