# [Sinatra AssetPack](http://ricostacruz.com/sinatra-assetpack)
#### Asset packer for Sinatra
This is *the* most convenient way to set up your CSS/JS (and images) in a
[Sinatra](http://sinatrarb.com) app. Seriously. No need for crappy routes to
render Sass or whatever. No-siree!
1. Drop your assets into `/app` like so (you can configure directories don't worry):
* JavaScript/CoffeeScript files in `/app/js`
* CSS/Sass/Less/CSS files in `/app/css`
* Images into `/app/images`
3. Add `register Sinatra::AssetPack` and set up options to your app (see below)
4. Use `<%= css :application %>` to your layouts. Use this instead of
messy *script* and *link* tags
5. BOOM! You're in business baby!
Installation
------------
Sinatra AssetPack is a simple Ruby gem. You can install it via `gem install`.
``` console
$ gem install sinatra-assetpack
```
#### Bundler users
If you use Bundler, you will need to add it to your *Gemfile*.
``` ruby
gem 'sinatra-assetpack', :require => 'sinatra/assetpack'
```
Setup
-----
Install the plugin and add some options. (Feel free to omit the *Optional*
items, they're listed here for posterity):
``` ruby
require 'sinatra/assetpack'
class App < Sinatra::Base
set :root, File.dirname(__FILE__)
register Sinatra::AssetPack
assets {
serve '/js', from: 'app/js' # Optional
serve '/css', from: 'app/css' # Optional
serve '/images', from: 'app/images' # Optional
# The second parameter defines where the compressed version will be served.
# (Note: that parameter is optional, AssetPack will figure it out.)
js :app, '/js/app.js', [
'/js/vendor/**/*.js',
'/js/app/**/*.js'
]
css :application, '/css/application.css', [
'/css/screen.css'
]
js_compression :jsmin # Optional
css_compression :sass # Optional
}
end
```
#### Using in layouts
In your layouts, use the `css` and `js` helpers:
*(Use haml? Great! Use `!= css :youreawesome` instead.)*
``` erb
<%= css :application, :media => 'screen' %>
<%= js :app %>
```
And then what?
--------------
#### Development mode
If you're on **development** mode, it serves each of the files as so:
``` html
```
#### Production mode
If you're on **production** mode, it serves a compressed version in the URLs you specify:
``` html
```
Features
--------
* __CoffeeScript support__ Just add your coffee files in one of the paths
served (in the example, `app/js/hello.coffee`) and they will be available as JS
files (`http://localhost:4567/js/hello.js`).
* __Sass/Less/SCSS support__ Works the same way. Place your dynamic CSS files
in there (say, `app/css/screen.sass`) and they will be available as CSS files
(`http://localhost:4567/css/screen.css`).
* __Cache busting__ the `css` and `js` helpers automatically ensures the URL
is based on when the file was last modified. The URL `/js/jquery.js` may be
translated to `/js/jquery.8237898.js` to ensure visitors always get the latest
version.
* __Images support__ Image filenames in your CSS will automatically get a
cache-busting suffix (eg, `/images/icon.742958.png`).
* __Embedded images support__ You can embed images in your CSS files as
`data:` URIs by simply adding `?embed` to the end of your URL.
* __No intermediate files needed__ You don't need to generate compiled files.
You can, but it's optional. Keeps your source repo clean!
* __Auto minification (with caching)__ JS and CSS files will be compressed as
needed.
* __Heroku support__ Oh yes. That's right.
Compressors
-----------
By default, AssetPack uses [JSMin](http://rubygems.org/gems/jsmin) for JS
compression, and simple regexes for CSS compression. You can specify other
compressors in the `assets` block:
``` ruby
assets {
js_compression :jsmin # :jsmin | :yui | :closure
css_compression :simple # :simple | :sass | :yui | :sqwish
}
```
### YUI Compressor
This uses Yahoo's Java-powered YUI compressor. For YUI compression, you need the
YUI compressor gem (`gem install yui-compressor`).
``` ruby
assets {
js_compression :yui
js_compression :yui, :munge => true # Munge variable names
css_compression :yui
}
```
### SASS compression
For SASS compression, you need the Sass gem (`gem install sass`). This treats
the CSS files as Scss files and uses Sass's `output: :compressed`.
``` ruby
assets {
css_compression :sass
}
```
### Sqwish CSS compression
[Sqwish](http://github.com/ded/sqwish) is a NodeJS-based CSS compressor. To use
Sqwish with AssetPack, install it using `npm install -g sqwish`. You need NodeJS
and NPM installed.
``` ruby
assets {
css_compression :sqwish
css_compression :sqwish, :strict => true
}
```
### Google Closure compression
This uses the [Google closure compiler
service](http://closure-compiler.appspot.com/home)
to compress your JavaScript. Available levels are:
* `WHITESPACE_ONLY`
* `SIMPLE_OPTIMIZATIONS`
* `ADVANCED_OPTIMIZATIONS`
``` ruby
assets {
js_compression :closure
js_compression :closure, :level => "SIMPLE_OPTIMIZATIONS"
}
```
Images
------
To show images, use the `img` helper.
This automatically adds width, height, and a cache buster thingie.
ImageMagick is required to generate full image tags with width and height.
``` html
<%= img '/images/email.png' %>
```
#### URL translation
In your CSS files, `url()`'s will automatically be translated.
``` css
/* Original: */ .email { background: url(/images/email.png); }
/* Output: */ .email { background: url(/images/email.6783478.png); }
```
#### Image embedding
Want to embed images as `data:` URI's? Sure! Just add `?embed` at the end of the
URL.
``` css
/* Original: */ .email { background: url(/images/email.png?embed); }
/* Output: */ .email { background: url(data:image/png;base64,NF8dG3I...); }
```
Need to build the files?
------------------------
Actually, you don't need to—this is optional! But add this to your `Rakefile`:
``` ruby
# Rakefile
APP_FILE = 'app.rb'
APP_CLASS = 'App'
require 'sinatra/assetpack/rake'
```
#### Invoking
Now invoke the `assetpack:build` Rake task. This will create files in `/public`.
$ rake assetpack:build
API reference
-------------
#### Assets block
All configuration happens in the `assets` block. You may invoke it in 2 ways:
``` ruby
class App < Sinatra::Base
register Sinatra::AssetPack
# Style 1
assets do
css :hello, [ '/css/*.css' ]
js_compression :yui
end
# Style 2
assets do |a|
a.css :hello, ['/css/*.css' ]
a.js_compression :yui
end
end
```
#### Getting options
Invoking it without a block allows you to access the options. This works for
almost all the options, with the exception for `css`, `js` and `serve`.
``` ruby
App.assets
App.assets.js_compression #=> :yui
```
### assets.serve
Serves files from `LOCALPATH` in the URI path `PATH`. Both parameters are
required.
``` ruby
# Usage
serve 'PATH', :from => 'LOCALPATH'
```
#### Example
This makes `/app/javascripts/vendor/jquery.js`
available as `http://localhost:4567/js/vendor/jquery.js`.
``` ruby
serve '/js', from: '/app/javascripts'
```
### assets.js\_compression
assets.css\_compression
Sets the compression engine to use for JavaScript or CSS. This defaults to
`:jsmin` and `:simple`, respectively.
If `OPTIONS_HASH` is given as a hash, it sets options for the engine to use.
``` ruby
# Usage:
assets {
js_compression :ENGINE
js_compression :ENGINE, OPTIONS_HASH
css_compression :ENGINE
css_compression :ENGINE, OPTIONS_HASH
}
```
#### Examples
Yo seriously check this out: the first line uses Sqwish with it's defaults, and
the second line uses Sqwish with it's magic.
``` ruby
assets {
css_compression :sqwish
css_compression :sqwish, :strict => true
}
```
### assets.js\_compression\_options
assets.css\_compression\_options
Sets the options for the compression engine to use. This is usually not needed
as you can already set options using `js_compression` and `css_compression`.
``` ruby
# Usage:
assets {
js_compression_options HASH
css_compression_options HASH
}
```
#### Example
This sets the option for `:munge` for the CSS compression engine.
``` ruby
css_compression_options :munge => true
```
### assets.css
assets.js
Adds packages to be used.
The `NAME` is a symbol defines the ID for that given package that you can use
for the helpers. That is, If a CSS package was defined as `css :main, [ ... ]`,
then you will need to use `<%= css :main %>` to render it in views.
the `URI` is a string that defines where the compressed version will be served.
It is optional. If not provided, it will default to `"/assets/name.type"` (eg:
`/assets/main.css`).
the `PATHs` is an array that defines files that will be served. Take note that
this is an array of URI paths, not local paths.
If a `PATH` contains wildcards, it will be expanded in alphabetical order.
Redundancies will be taken care of.
``` ruby
# Usage:
assets {
css :NAME, [ PATH1, PATH2, ... ]
css :NAME, 'URI', [ PATH1, PATH2, ... ]
js:NAME, [ PATH1, PATH2, ... ]
js:NAME, 'URI', [ PATH1, PATH2, ... ]
}
```
#### Example
In this example, JavaScript files will be served compressed as
`/js/application.js` (default since no `URI` is given). The files will be taken
from `./app/javascripts/vendor/jquery*.js`.
``` ruby
class App < Sinatra::Base
serve '/js', from: '/app/javascripts'
assets {
js :application, [
'/js/vendor/jquery.*.js',
'/js/vendor/jquery.js'
]
}
end
# In views: <%= js :application %>
```
API reference: helpers
----------------------
These are helpers you can use in your views.
### <%= css %>
Shows a CSS package named `PACKAGE`. If `OPTIONS_HASH` is given, they will we
passed onto the `` tag to be generated as attributes.
You may specify as many packages as you need, as shown in the second usage line.
``` ruby
# Usage:
<%= css :PACKAGE %>
<%= css :PACKAGE_1, :PACKAGE_2, ... :PACKAGE_N, OPTIONS_HASH %>
<%= css :PACKAGE, OPTIONS_HASH %>
```
#### Example 1
This links to the `main` stylesheet for *screen* media.
``` erb
<%= css :main, media: 'screen' %>
```
#### Example 2
You may also invoke it with multiple packages.
``` erb
<%= css :base, :app, :main, media: 'screen' %>
```
### <%= js %>
Same as `css`, but obviously for JavaScript. You may also specify as many packages as you need, just with `css`.
``` erb
# Usage:
<%= js :PACKAGE %>
<%= js :PACKAGE_1, :PACKAGE_2, ... :PACKAGE_N, OPTIONS_HASH %>
<%= js :PACKAGE, OPTIONS_HASH %>
```
#### Example
This example embeds the *main* package with an ID.
``` erb
<%= js :main, id: 'main_script' %>
```
### <%= img %>
Shows an `` tag from the given `SRC`. If the images is found in the asset
directories (and ImageMagick is available), `width` and `height` attributes will
be added.
``` ruby
# Usage:
img 'SRC'
img 'SRC', OPTIONS_HASH
```
If `OPTIONS_HASH` is given, they will we passed onto the `` tag to be
generated as attributes.
#### Example
This example renders an image with an alt tag.
``` erb
<%= img '/images/icon.png', alt: 'Icon' %>
`
```
Need Compass support?
---------------------
No, AssetPack doesn't have built-in [Compass](http://compass-style.org) support,
but you can use [Sinatra Support](http://sinefunc.com/sinatra-support).
For an example of how to use AssetPack with Compass, including on how to use it
to generate image [sprites][compsprite], see the [Compass example
application.][compex]
[compex]: https://github.com/rstacruz/sinatra-assetpack/tree/master/examples/compass
[compsprite]: http://compass-style.org/reference/compass/utilities/sprites/
``` ruby
# gem install sinatra/support
Encoding.default_external = 'utf-8'
require 'sinatra/support'
class Main
register Sinatra::CompassSupport
end
```
To do
-----
AssetPack will eventually have:
* Nested packages
* Ignored files (to ignore included sass files and such)
* `rake assetpack:build` should be able to output to another folder
* Cache folder support (best if your app has many workers)
* Refactor *Compressor* module
* CDN (Cloudfront, S3) support
* Better support for Compass sprites
Acknowledgements
----------------
© 2011, Rico Sta. Cruz. Released under the [MIT
License](http://www.opensource.org/licenses/mit-license.php).
Sinatra-AssetPack is authored and maintained by [Rico Sta. Cruz][rsc] with help
from it's [contributors][c]. It is sponsored by my startup, [Sinefunc, Inc][sf].
* [My website](http://ricostacruz.com) (ricostacruz.com)
* [Sinefunc, Inc.](http://sinefunc.com) (sinefunc.com)
* [Github](http://github.com/rstacruz) (@rstacruz)
* [Twitter](http://twitter.com/rstacruz) (@rstacruz)
[rsc]: http://ricostacruz.com
[c]: http://github.com/rstacruz/sinatra-assetpack/contributors
[sf]: http://sinefunc.com