sundawg-sinatra-assetpack-fork 0.0.12.pre1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +4 -0
- data/Gemfile +2 -0
- data/HISTORY.md +131 -0
- data/README.md +656 -0
- data/Rakefile +31 -0
- data/docsrc/style.css +32 -0
- data/examples/basic/.gitignore +1 -0
- data/examples/basic/Rakefile +7 -0
- data/examples/basic/app/css/test.sass +11 -0
- data/examples/basic/app/images/icon.png +0 -0
- data/examples/basic/app/js/app.js +4 -0
- data/examples/basic/app/js/vendor/jquery.js +2 -0
- data/examples/basic/app/js/vendor/jquery.plugin.js +2 -0
- data/examples/basic/app/js/vendor/underscore.js +2 -0
- data/examples/basic/app.rb +39 -0
- data/examples/basic/views/index.erb +26 -0
- data/examples/classic/app.rb +24 -0
- data/examples/classic/css/screen.scss +1 -0
- data/examples/compass/.gitignore +1 -0
- data/examples/compass/Rakefile +7 -0
- data/examples/compass/app/css/main.scss +64 -0
- data/examples/compass/app/images/icon/mail.png +0 -0
- data/examples/compass/app/images/icon/refresh.png +0 -0
- data/examples/compass/app/images/icon-scfd8d7d404.png +0 -0
- data/examples/compass/app/images/junk/mail.png +0 -0
- data/examples/compass/app/images/junk/refresh.png +0 -0
- data/examples/compass/app/js/app.js +3 -0
- data/examples/compass/app/js/vendor/jquery.js +2 -0
- data/examples/compass/app/js/vendor/jquery.plugin.js +2 -0
- data/examples/compass/app/js/vendor/underscore.js +2 -0
- data/examples/compass/app.rb +45 -0
- data/examples/compass/config.ru +3 -0
- data/examples/compass/views/index.erb +15 -0
- data/lib/sinatra/assetpack/buster_helpers.rb +36 -0
- data/lib/sinatra/assetpack/class_methods.rb +82 -0
- data/lib/sinatra/assetpack/compressor.rb +54 -0
- data/lib/sinatra/assetpack/configurator.rb +21 -0
- data/lib/sinatra/assetpack/css.rb +36 -0
- data/lib/sinatra/assetpack/engine.rb +20 -0
- data/lib/sinatra/assetpack/engines/closure.rb +19 -0
- data/lib/sinatra/assetpack/engines/jsmin.rb +10 -0
- data/lib/sinatra/assetpack/engines/sass.rb +11 -0
- data/lib/sinatra/assetpack/engines/simple.rb +11 -0
- data/lib/sinatra/assetpack/engines/sqwish.rb +21 -0
- data/lib/sinatra/assetpack/engines/uglify.rb +12 -0
- data/lib/sinatra/assetpack/engines/yui.rb +22 -0
- data/lib/sinatra/assetpack/hasharray.rb +66 -0
- data/lib/sinatra/assetpack/helpers.rb +62 -0
- data/lib/sinatra/assetpack/html_helpers.rb +17 -0
- data/lib/sinatra/assetpack/image.rb +59 -0
- data/lib/sinatra/assetpack/options.rb +329 -0
- data/lib/sinatra/assetpack/package.rb +126 -0
- data/lib/sinatra/assetpack/rake.rb +29 -0
- data/lib/sinatra/assetpack/version.rb +7 -0
- data/lib/sinatra/assetpack.rb +61 -0
- data/sinatra-assetpack.gemspec +26 -0
- data/test/app/.gitignore +1 -0
- data/test/app/Rakefile +7 -0
- data/test/app/app/css/behavior.htc +1 -0
- data/test/app/app/css/js2c.css +494 -0
- data/test/app/app/css/screen.sass +9 -0
- data/test/app/app/css/sqwishable.css +7 -0
- data/test/app/app/css/style.css +3 -0
- data/test/app/app/css/stylus.styl +3 -0
- data/test/app/app/css_stylus/stylus.styl +3 -0
- data/test/app/app/images/background.jpg +1 -0
- data/test/app/app/images/email.png +0 -0
- data/test/app/app/js/_ignoreme.js +1 -0
- data/test/app/app/js/hello.2.js +1 -0
- data/test/app/app/js/hello.js +1 -0
- data/test/app/app/js/helloe.js +1 -0
- data/test/app/app/js/hi.coffee +2 -0
- data/test/app/app/js/ugly.js +7 -0
- data/test/app/app/js/yoe.coffee +2 -0
- data/test/app/app/js_glob/a/b/c1/hello.js +1 -0
- data/test/app/app/js_glob/a/b/c2/hi.js +1 -0
- data/test/app/app/js_glob/a/b/c2/hola.js +1 -0
- data/test/app/app/views/index.haml +1 -0
- data/test/app/app.rb +67 -0
- data/test/arity_test.rb +26 -0
- data/test/build_test.rb +31 -0
- data/test/cache_test.rb +9 -0
- data/test/combined_test.rb +8 -0
- data/test/compressed_test.rb +30 -0
- data/test/glob_test.rb +42 -0
- data/test/helpers_test.rb +30 -0
- data/test/ignore_test.rb +30 -0
- data/test/img_test.rb +31 -0
- data/test/local_file_test.rb +21 -0
- data/test/mime_type_test.rb +33 -0
- data/test/non_existent_test.rb +45 -0
- data/test/options_test.rb +21 -0
- data/test/order_test.rb +20 -0
- data/test/preproc_test.rb +28 -0
- data/test/redundant_test.rb +11 -0
- data/test/simplecss_test.rb +16 -0
- data/test/sqwish_test.rb +31 -0
- data/test/stylus_test.rb +23 -0
- data/test/template_cache_test.rb +29 -0
- data/test/test_helper.rb +46 -0
- data/test/tilt_test.rb +11 -0
- data/test/uglifier_test.rb +23 -0
- data/test/unit_test.rb +106 -0
- data/test/yui_test.rb +22 -0
- metadata +341 -0
Binary file
|
@@ -0,0 +1,39 @@
|
|
1
|
+
$:.unshift File.expand_path('../../../lib', __FILE__)
|
2
|
+
|
3
|
+
require 'sinatra/base'
|
4
|
+
require 'sinatra/assetpack'
|
5
|
+
|
6
|
+
class App < Sinatra::Base
|
7
|
+
set :root, File.dirname(__FILE__)
|
8
|
+
register Sinatra::AssetPack
|
9
|
+
|
10
|
+
assets do
|
11
|
+
#js_compression :closure
|
12
|
+
js_compression :uglify
|
13
|
+
|
14
|
+
js :main, '/js/main.js', [
|
15
|
+
'/js/vendor/*.js',
|
16
|
+
'/js/app.js'
|
17
|
+
]
|
18
|
+
|
19
|
+
css :main, [
|
20
|
+
'/css/*.css'
|
21
|
+
]
|
22
|
+
|
23
|
+
# The second parameter here is optional (see above).
|
24
|
+
# It will default to '/css/#{name}.css'.
|
25
|
+
css :more, '/css/more.css', [
|
26
|
+
'/css/more/*.css'
|
27
|
+
]
|
28
|
+
|
29
|
+
prebuild true
|
30
|
+
end
|
31
|
+
|
32
|
+
get '/' do
|
33
|
+
erb :index
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
if __FILE__ == $0
|
38
|
+
App.run!
|
39
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html lang="en">
|
3
|
+
<head>
|
4
|
+
<meta charset="UTF-8" />
|
5
|
+
<title></title>
|
6
|
+
|
7
|
+
<!-- These should include all the JS files defined in the app. -->
|
8
|
+
<%= js :main %>
|
9
|
+
<%= css :main %>
|
10
|
+
</head>
|
11
|
+
<body>
|
12
|
+
<h1>Hello!</h1>
|
13
|
+
<h4>View the source of this file to see the JS files as they were included.</h4>
|
14
|
+
|
15
|
+
<h3>Image test:</h3>
|
16
|
+
|
17
|
+
<!-- This should have width and height. -->
|
18
|
+
<%= img '/images/icon.png' %>
|
19
|
+
|
20
|
+
<h3>Image embedding test:</h3>
|
21
|
+
<div id="image_embedding_test">
|
22
|
+
<!-- This should have a CSS background that uses a data: URI. -->
|
23
|
+
<!-- Inspect that <div> to see. -->
|
24
|
+
</div>
|
25
|
+
</body>
|
26
|
+
</html>
|
@@ -0,0 +1,24 @@
|
|
1
|
+
$:.unshift File.expand_path('../../../lib', __FILE__)
|
2
|
+
|
3
|
+
require 'sinatra'
|
4
|
+
require 'sinatra/assetpack'
|
5
|
+
|
6
|
+
assets do
|
7
|
+
# By default, Sinatra::AssetPack looks at ./app/css/, ./app/js/ and
|
8
|
+
# ./app/images. Let's change this to look at ./css.
|
9
|
+
serve '/css', from: 'css'
|
10
|
+
|
11
|
+
css :main, [
|
12
|
+
'/css/*.css'
|
13
|
+
]
|
14
|
+
end
|
15
|
+
|
16
|
+
get "/" do
|
17
|
+
css :main
|
18
|
+
end
|
19
|
+
|
20
|
+
__END__
|
21
|
+
|
22
|
+
@@ index
|
23
|
+
<%= css :main %>
|
24
|
+
<h1>Hello!</h1>
|
@@ -0,0 +1 @@
|
|
1
|
+
body { color: red }
|
@@ -0,0 +1 @@
|
|
1
|
+
public
|
@@ -0,0 +1,64 @@
|
|
1
|
+
@import 'compass/css3';
|
2
|
+
@import 'compass/reset';
|
3
|
+
|
4
|
+
html, body {
|
5
|
+
font-family: sans-serif;
|
6
|
+
font-size: 11pt;
|
7
|
+
line-height: 1.5; }
|
8
|
+
|
9
|
+
body {
|
10
|
+
background: #c2c2cf; }
|
11
|
+
|
12
|
+
#all {
|
13
|
+
background: white;
|
14
|
+
color: #333;
|
15
|
+
padding: 10px;
|
16
|
+
width: 500px;
|
17
|
+
margin: 50px auto; }
|
18
|
+
|
19
|
+
// ### Optional sprite config
|
20
|
+
// You may put any of these before the `all-icon-sprites` line.
|
21
|
+
// These are completely optional.
|
22
|
+
|
23
|
+
// #### Sprite sets: (/icon/*.png)
|
24
|
+
$icon-spacing: 0; // How much blank space (in pixels) to put
|
25
|
+
$icon-dimensions: false; // Sets width/height in the classes
|
26
|
+
$icon-repeat: no-repeat;
|
27
|
+
$icon-position: 0;
|
28
|
+
|
29
|
+
// #### Individual images: (/icon/mail.png)
|
30
|
+
$icon-mail-spacing: 0;
|
31
|
+
$icon-mail-repeat: no-repeat;
|
32
|
+
$icon-mail-position: 0px;
|
33
|
+
|
34
|
+
// ### Sprite setup
|
35
|
+
// For "mail.png" and "refresh.png", this creates classes for .icon-mail and
|
36
|
+
// .icon-refresh that you can @extend from.
|
37
|
+
//
|
38
|
+
// See: http://compass-style.org/help/tutorials/configuration-reference/
|
39
|
+
//
|
40
|
+
@import "icon/*.png";
|
41
|
+
@include all-icon-sprites;
|
42
|
+
|
43
|
+
.image1, .image2 {
|
44
|
+
width: 16px; height: 16px;
|
45
|
+
display: inline-block; }
|
46
|
+
|
47
|
+
.image1 {
|
48
|
+
@extend .icon-mail; }
|
49
|
+
|
50
|
+
.image2 {
|
51
|
+
@extend .icon-refresh; }
|
52
|
+
|
53
|
+
// ### Advanced control
|
54
|
+
// The sprite map is available as $icon-sprites. You can then use
|
55
|
+
// `sprite()` on it.
|
56
|
+
|
57
|
+
.image3 {
|
58
|
+
background: sprite($icon-sprites, refresh); }
|
59
|
+
//background: url(...) 0 -16px;
|
60
|
+
|
61
|
+
.image3-with-offset {
|
62
|
+
background: sprite($icon-sprites, refresh, -2px, -9px); }
|
63
|
+
//background: url(...) -2px -19px;
|
64
|
+
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
@@ -0,0 +1,45 @@
|
|
1
|
+
$:.unshift File.expand_path('../../../lib', __FILE__)
|
2
|
+
|
3
|
+
require 'sinatra/base'
|
4
|
+
require 'sinatra/assetpack'
|
5
|
+
require 'compass'
|
6
|
+
require 'sinatra/support'
|
7
|
+
|
8
|
+
Encoding.default_external = 'utf-8' if defined?(::Encoding)
|
9
|
+
|
10
|
+
class App < Sinatra::Base
|
11
|
+
disable :show_exceptions
|
12
|
+
enable :raise_exceptions
|
13
|
+
|
14
|
+
set :root, File.dirname(__FILE__)
|
15
|
+
|
16
|
+
# This is a convenient way of setting up Compass in a Sinatra
|
17
|
+
# project without mucking around with load paths and such.
|
18
|
+
register Sinatra::CompassSupport
|
19
|
+
|
20
|
+
# ### Compass sprite configuration
|
21
|
+
# Skip this section if you don't need sprite images.
|
22
|
+
#
|
23
|
+
# Configure Compass so it knows where to look for sprites. This tells
|
24
|
+
# Compass to look for images in `app/images`, dump sprite images in the same
|
25
|
+
# folder, and link to it with HTTP images path.
|
26
|
+
#
|
27
|
+
c = Compass.configuration
|
28
|
+
c.project_path = root
|
29
|
+
c.images_dir = "app/images"
|
30
|
+
c.http_images_path = "/images"
|
31
|
+
|
32
|
+
# Asset Pack.
|
33
|
+
register Sinatra::AssetPack
|
34
|
+
assets do
|
35
|
+
css :main, ['/css/*.css']
|
36
|
+
end
|
37
|
+
|
38
|
+
get '/' do
|
39
|
+
erb :index
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
if __FILE__ == $0
|
44
|
+
App.run!
|
45
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html lang="en">
|
3
|
+
<head>
|
4
|
+
<meta charset="UTF-8" />
|
5
|
+
<title></title>
|
6
|
+
<%= css :main %>
|
7
|
+
</head>
|
8
|
+
<body>
|
9
|
+
<div id="all">
|
10
|
+
<h1>Here are some sprites:</h1>
|
11
|
+
<span class='image1'></span>
|
12
|
+
<span class='image2'></span>
|
13
|
+
</div>
|
14
|
+
</body>
|
15
|
+
</html>
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Sinatra
|
2
|
+
module AssetPack
|
3
|
+
module BusterHelpers
|
4
|
+
extend self
|
5
|
+
# Returns the cache buster suffix for given file(s).
|
6
|
+
# This implementation somewhat obfuscates the mtime to not reveal deployment dates.
|
7
|
+
def cache_buster_hash(*files)
|
8
|
+
i = mtime_for(files)
|
9
|
+
(i * 4567).to_s.reverse[0...6] if i
|
10
|
+
end
|
11
|
+
|
12
|
+
# Returns the maximum mtime for a given list of files.
|
13
|
+
# It will return nil if none of them are found.
|
14
|
+
def mtime_for(files)
|
15
|
+
files.map { |f| File.mtime(f).to_i if f.is_a?(String) && File.file?(f) }.compact.max
|
16
|
+
end
|
17
|
+
|
18
|
+
# Adds a cache buster for the given path.
|
19
|
+
#
|
20
|
+
# The 2nd parameter (and beyond) are the files to take mtime from.
|
21
|
+
# If the files are not found, the paths will be left as they are.
|
22
|
+
#
|
23
|
+
# add_cache_buster('/images/email.png', '/var/www/x/public/images/email.png')
|
24
|
+
#
|
25
|
+
def add_cache_buster(path, *files)
|
26
|
+
hash = cache_buster_hash *files
|
27
|
+
|
28
|
+
if hash
|
29
|
+
path.gsub(/(\.[^.]+)$/) { |ext| ".#{hash}#{ext}" }
|
30
|
+
else
|
31
|
+
path
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
module Sinatra
|
2
|
+
module AssetPack
|
3
|
+
# Class methods that will be given to the Sinatra application.
|
4
|
+
module ClassMethods
|
5
|
+
# Sets asset options, or gets them
|
6
|
+
def assets(&blk)
|
7
|
+
@options ||= Options.new(self, &blk)
|
8
|
+
self.assets_initialize! if block_given?
|
9
|
+
|
10
|
+
@options
|
11
|
+
end
|
12
|
+
|
13
|
+
def assets_initialize!
|
14
|
+
add_compressed_routes!
|
15
|
+
add_individual_routes!
|
16
|
+
|
17
|
+
# Cache the built files.
|
18
|
+
if assets.prebuild && !reload_templates
|
19
|
+
assets.cache! { |file| $stderr.write "** Building #{file}...\n" }
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# Add routes for the compressed versions
|
24
|
+
def add_compressed_routes!
|
25
|
+
assets.packages.each do |name, package|
|
26
|
+
get package.route_regex do
|
27
|
+
mtime, contents = @template_cache.fetch(package.path) {
|
28
|
+
[ package.mtime, package.minify ]
|
29
|
+
}
|
30
|
+
|
31
|
+
content_type package.type
|
32
|
+
last_modified mtime
|
33
|
+
contents
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# Add the routes for the individual files.
|
39
|
+
def add_individual_routes!
|
40
|
+
assets.served.each do |path, from|
|
41
|
+
get %r{#{"^/#{path}/".squeeze('/')}(.*)$} do |file|
|
42
|
+
fmt = File.extname(file)[1..-1]
|
43
|
+
|
44
|
+
# Sanity checks
|
45
|
+
pass unless AssetPack.supported_formats.include?(fmt)
|
46
|
+
fn = asset_path_for(file, from) or pass
|
47
|
+
|
48
|
+
pass if settings.assets.ignored?("#{path}/#{file}")
|
49
|
+
|
50
|
+
# Send headers
|
51
|
+
content_type fmt.to_sym
|
52
|
+
last_modified File.mtime(fn).to_i
|
53
|
+
expires 86400*30, :public
|
54
|
+
|
55
|
+
format = File.extname(fn)[1..-1]
|
56
|
+
|
57
|
+
if AssetPack.supported_formats.include?(format)
|
58
|
+
# It's a raw file, just send it
|
59
|
+
not_found unless format == fmt
|
60
|
+
|
61
|
+
if fmt == 'css'
|
62
|
+
@template_cache.fetch(fn) { asset_filter_css File.read(fn) }
|
63
|
+
else
|
64
|
+
send_file fn
|
65
|
+
end
|
66
|
+
else
|
67
|
+
# Dynamic file
|
68
|
+
not_found unless AssetPack.tilt_formats[format] == fmt
|
69
|
+
|
70
|
+
@template_cache.fetch(fn) {
|
71
|
+
out = render format.to_sym, File.read(fn)
|
72
|
+
out = asset_filter_css(out) if fmt == 'css'
|
73
|
+
out
|
74
|
+
}
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module Sinatra
|
2
|
+
module AssetPack
|
3
|
+
module Compressor
|
4
|
+
extend self
|
5
|
+
|
6
|
+
# Compresses a given string.
|
7
|
+
#
|
8
|
+
# compress File.read('x.js'), :js, :jsmin
|
9
|
+
#
|
10
|
+
def compress(str, type, engine=nil, options={})
|
11
|
+
# Use defaults if no engine is given.
|
12
|
+
return fallback(str, type, options) if engine.nil?
|
13
|
+
|
14
|
+
# Ensure that the engine exists.
|
15
|
+
klass = compressors[[type, engine]]
|
16
|
+
raise Error, "Engine #{engine} (#{type}) doesn't exist." unless klass
|
17
|
+
|
18
|
+
# Ensure that the engine can support that type.
|
19
|
+
engine = klass.new
|
20
|
+
raise Error, "#{klass} does not support #{type.upcase} compression." unless engine.respond_to?(type)
|
21
|
+
|
22
|
+
# Build it using the engine, and fallback to defaults if it fails.
|
23
|
+
output = engine.send type, str, options
|
24
|
+
output ||= fallback(str, type, options) unless options[:no_fallback]
|
25
|
+
output
|
26
|
+
end
|
27
|
+
|
28
|
+
# Compresses a given string using the default engines.
|
29
|
+
def fallback(str, type, options)
|
30
|
+
if type == :js
|
31
|
+
compress str, :js, :jsmin, :no_fallback => true
|
32
|
+
elsif type == :css
|
33
|
+
compress str, :css, :simple, :no_fallback => true
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def compressors
|
38
|
+
@compressors ||= Hash.new
|
39
|
+
end
|
40
|
+
|
41
|
+
def register(type, engine, meth)
|
42
|
+
compressors[[type, engine]] = meth
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
require "#{AssetPack::PREFIX}/assetpack/engines/simple"
|
47
|
+
require "#{AssetPack::PREFIX}/assetpack/engines/jsmin"
|
48
|
+
require "#{AssetPack::PREFIX}/assetpack/engines/yui"
|
49
|
+
require "#{AssetPack::PREFIX}/assetpack/engines/sass"
|
50
|
+
require "#{AssetPack::PREFIX}/assetpack/engines/sqwish"
|
51
|
+
require "#{AssetPack::PREFIX}/assetpack/engines/closure"
|
52
|
+
require "#{AssetPack::PREFIX}/assetpack/engines/uglify"
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Sinatra
|
2
|
+
module AssetPack
|
3
|
+
module Configurator
|
4
|
+
def self.included(klass)
|
5
|
+
klass.extend ClassMethods
|
6
|
+
end
|
7
|
+
|
8
|
+
module ClassMethods
|
9
|
+
def attrib(name)
|
10
|
+
define_method(:"#{name}") { |*a|
|
11
|
+
value = a.first
|
12
|
+
self.instance_variable_set :"@#{name}", value unless value.nil?
|
13
|
+
self.instance_variable_get :"@#{name}"
|
14
|
+
}
|
15
|
+
|
16
|
+
alias_method(:"#{name}=", :"#{name}")
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Sinatra
|
2
|
+
module AssetPack
|
3
|
+
module Css
|
4
|
+
def self.preproc(str, assets)
|
5
|
+
str.gsub(/url\(["']?(.*?)["']?\)/) { |url|
|
6
|
+
path = $1
|
7
|
+
file, options = path.split('?')
|
8
|
+
local = assets.local_file_for file
|
9
|
+
|
10
|
+
url = if local
|
11
|
+
if options.to_s.include?('embed')
|
12
|
+
to_data_uri(local)
|
13
|
+
else
|
14
|
+
BusterHelpers.add_cache_buster(file, local)
|
15
|
+
end
|
16
|
+
else
|
17
|
+
path
|
18
|
+
end
|
19
|
+
|
20
|
+
"url(#{url})"
|
21
|
+
}
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.to_data_uri(file)
|
25
|
+
require 'base64'
|
26
|
+
|
27
|
+
data = File.read(file)
|
28
|
+
ext = File.extname(file)
|
29
|
+
mime = Sinatra::Base.mime_type(ext)
|
30
|
+
b64 = Base64.encode64(data).gsub("\n", '')
|
31
|
+
|
32
|
+
"data:#{mime};base64,#{b64}"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Sinatra
|
2
|
+
module AssetPack
|
3
|
+
# The base class for all CSS/JS compression engines.
|
4
|
+
class Engine
|
5
|
+
# Helper for system files.
|
6
|
+
# Usage: sys('css', string, "sqwish %f")
|
7
|
+
# Returns stdout.
|
8
|
+
def sys(type, str, cmd)
|
9
|
+
t = Tempfile.new ['', ".#{type}"]
|
10
|
+
t.write(str)
|
11
|
+
t.close
|
12
|
+
|
13
|
+
output = `#{cmd.gsub('%f', t.path)}`
|
14
|
+
FileUtils.rm t
|
15
|
+
|
16
|
+
[output, t.path]
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Sinatra::AssetPack
|
2
|
+
class ClosureEngine < Engine
|
3
|
+
def js(str, options={})
|
4
|
+
require 'net/http'
|
5
|
+
require 'uri'
|
6
|
+
|
7
|
+
response = Net::HTTP.post_form(URI.parse('http://closure-compiler.appspot.com/compile'), {
|
8
|
+
'js_code' => str,
|
9
|
+
'compilation_level' => options[:level] || "ADVANCED_OPTIMIZATIONS",
|
10
|
+
'output_format' => 'text',
|
11
|
+
'output_info' => 'compiled_code'
|
12
|
+
})
|
13
|
+
|
14
|
+
response.body
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
Compressor.register :js, :closure, ClosureEngine
|
19
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Sinatra::AssetPack
|
2
|
+
class SqwishEngine < Engine
|
3
|
+
def css(str, options={})
|
4
|
+
cmd = "#{sqwish_bin} %f "
|
5
|
+
cmd += "--strict" if options[:strict]
|
6
|
+
|
7
|
+
_, input = sys :css, str, cmd
|
8
|
+
output = input.gsub(/\.css/, '.min.css')
|
9
|
+
|
10
|
+
File.read(output)
|
11
|
+
rescue => e
|
12
|
+
nil
|
13
|
+
end
|
14
|
+
|
15
|
+
def sqwish_bin
|
16
|
+
ENV['SQWISH_PATH'] || "sqwish"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
Compressor.register :css, :sqwish, SqwishEngine
|
21
|
+
end
|