jammit-core 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +22 -0
- data/README +24 -0
- data/README.rdoc +17 -0
- data/Rakefile +59 -0
- data/VERSION +1 -0
- data/bin/jammit +13 -0
- data/lib/assets.example.yml +14 -0
- data/lib/jammit-core.rb +219 -0
- data/lib/jammit-core/cli.rb +87 -0
- data/lib/jammit-core/command_line.rb +79 -0
- data/lib/jammit-core/compressor.rb +214 -0
- data/lib/jammit-core/config.rb +82 -0
- data/lib/jammit-core/dependencies.rb +23 -0
- data/lib/jammit-core/helper.rb +77 -0
- data/lib/jammit-core/jst.js +1 -0
- data/lib/jammit-core/packager.rb +163 -0
- data/lib/jammit-core/routes.rb +16 -0
- data/lib/jammit-core/ui.rb +55 -0
- data/test/config/assets-broken.yml +16 -0
- data/test/config/assets-closure.yml +16 -0
- data/test/config/assets-compression-disabled.yml +16 -0
- data/test/config/assets-css.yml +6 -0
- data/test/config/assets-erb.yml +13 -0
- data/test/config/assets-no-java.yml +16 -0
- data/test/config/assets.yml +13 -0
- data/test/fixtures/jammed/test-closure.js +1 -0
- data/test/fixtures/jammed/test-datauri.css +1 -0
- data/test/fixtures/jammed/test-line-break.css +8 -0
- data/test/fixtures/jammed/test-mhtml.css +17 -0
- data/test/fixtures/jammed/test-uncompressed.css +36 -0
- data/test/fixtures/jammed/test-uncompressed.js +13 -0
- data/test/fixtures/jammed/test.css +1 -0
- data/test/fixtures/jammed/test.js +1 -0
- data/test/fixtures/jammed/test.jst +6 -0
- data/test/fixtures/jammed/test2.jst +6 -0
- data/test/fixtures/src/test1.css +11 -0
- data/test/fixtures/src/test1.js +8 -0
- data/test/fixtures/src/test1.jst +1 -0
- data/test/fixtures/src/test2.css +20 -0
- data/test/fixtures/src/test2.js +5 -0
- data/test/fixtures/src/test2.jst +5 -0
- data/test/fixtures/src/test_fonts.css +5 -0
- data/test/fixtures/tags/css_includes.html +6 -0
- data/test/fixtures/tags/css_individual_includes.html +3 -0
- data/test/fixtures/tags/css_plain_includes.html +1 -0
- data/test/fixtures/tags/css_print.html +6 -0
- data/test/public/embed/DroidSansMono.eot +0 -0
- data/test/public/embed/DroidSansMono.ttf +0 -0
- data/test/public/embed/asterisk_orange.png +0 -0
- data/test/public/embed/asterisk_yellow.png +0 -0
- data/test/test_helper.rb +44 -0
- data/test/unit/command_line_test.rb +28 -0
- data/test/unit/test_closure_compressor.rb +24 -0
- data/test/unit/test_compressor.rb +24 -0
- data/test/unit/test_configuration.rb +71 -0
- data/test/unit/test_in_the_wrong_directory.rb +40 -0
- data/test/unit/test_jammit_helpers.rb +44 -0
- data/test/unit/test_packager.rb +77 -0
- metadata +187 -0
@@ -0,0 +1,79 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
require File.expand_path(File.dirname(__FILE__) + '/../jammit')
|
3
|
+
|
4
|
+
module Jammit
|
5
|
+
|
6
|
+
# The @CommandLine@ is able to compress, pre-package, and pre-gzip all the
|
7
|
+
# assets specified in the configuration file, in order to avoid an initial
|
8
|
+
# round of slow requests after a fresh deployment.
|
9
|
+
class CommandLine
|
10
|
+
|
11
|
+
BANNER = <<-EOS
|
12
|
+
|
13
|
+
Usage: jammit OPTIONS
|
14
|
+
|
15
|
+
Run jammit inside a Rails application to compresses all JS, CSS,
|
16
|
+
and JST according to config/assets.yml, saving the packaged
|
17
|
+
files and corresponding gzipped versions.
|
18
|
+
|
19
|
+
If you're using "embed_assets", and you wish to precompile the
|
20
|
+
MHTML stylesheet variants, you must specify the "base-url".
|
21
|
+
|
22
|
+
Options:
|
23
|
+
EOS
|
24
|
+
|
25
|
+
# The @Jammit::CommandLine@ runs from the contents of @ARGV@.
|
26
|
+
def initialize
|
27
|
+
parse_options
|
28
|
+
ensure_configuration_file
|
29
|
+
Jammit.load_configuration(@options[:config_path])
|
30
|
+
Jammit.packager.force = @options[:force]
|
31
|
+
Jammit.packager.precache_all(@options[:output_folder], @options[:base_url])
|
32
|
+
end
|
33
|
+
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
# Make sure that we have a readable configuration file. The @jammit@
|
38
|
+
# command can't run without one.
|
39
|
+
def ensure_configuration_file
|
40
|
+
config = @options[:config_path]
|
41
|
+
return true if File.exists?(config) && File.readable?(config)
|
42
|
+
puts "Could not find the asset configuration file \"#{config}\""
|
43
|
+
exit(1)
|
44
|
+
end
|
45
|
+
|
46
|
+
# Uses @OptionParser@ to grab the options: *--output*, *--config*, and
|
47
|
+
# *--base-url*...
|
48
|
+
def parse_options
|
49
|
+
@options = {
|
50
|
+
:config_path => Jammit::DEFAULT_CONFIG_PATH,
|
51
|
+
:output_folder => nil,
|
52
|
+
:base_url => nil,
|
53
|
+
:force => false
|
54
|
+
}
|
55
|
+
@option_parser = OptionParser.new do |opts|
|
56
|
+
opts.on('-o', '--output PATH', 'output folder for packages (default: "public/assets")') do |output_folder|
|
57
|
+
@options[:output_folder] = output_folder
|
58
|
+
end
|
59
|
+
opts.on('-c', '--config PATH', 'path to assets.yml (default: "config/assets.yml")') do |config_path|
|
60
|
+
@options[:config_path] = config_path
|
61
|
+
end
|
62
|
+
opts.on('-u', '--base-url URL', 'base URL for MHTML (ex: "http://example.com")') do |base_url|
|
63
|
+
@options[:base_url] = base_url
|
64
|
+
end
|
65
|
+
opts.on('-f', '--force', 'force a rebuild of all assets') do |force|
|
66
|
+
@options[:force] = force
|
67
|
+
end
|
68
|
+
opts.on_tail('-v', '--version', 'display Jammit version') do
|
69
|
+
puts "Jammit version #{Jammit::VERSION}"
|
70
|
+
exit
|
71
|
+
end
|
72
|
+
end
|
73
|
+
@option_parser.banner = BANNER
|
74
|
+
@option_parser.parse!(ARGV)
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
@@ -0,0 +1,214 @@
|
|
1
|
+
module Jammit
|
2
|
+
|
3
|
+
# Uses the YUI Compressor or Closure Compiler to compress JavaScript.
|
4
|
+
# Always uses YUI to compress CSS (Which means that Java must be installed.)
|
5
|
+
# Also knows how to create a concatenated JST file.
|
6
|
+
# If "embed_assets" is turned on, creates "mhtml" and "datauri" versions of
|
7
|
+
# all stylesheets, with all enabled assets inlined into the css.
|
8
|
+
class Compressor
|
9
|
+
|
10
|
+
# Mapping from extension to mime-type of all embeddable assets.
|
11
|
+
EMBED_MIME_TYPES = {
|
12
|
+
'.png' => 'image/png',
|
13
|
+
'.jpg' => 'image/jpeg',
|
14
|
+
'.jpeg' => 'image/jpeg',
|
15
|
+
'.gif' => 'image/gif',
|
16
|
+
'.tif' => 'image/tiff',
|
17
|
+
'.tiff' => 'image/tiff',
|
18
|
+
'.ttf' => 'font/truetype',
|
19
|
+
'.otf' => 'font/opentype'
|
20
|
+
}
|
21
|
+
|
22
|
+
# Font extensions for which we allow embedding:
|
23
|
+
EMBED_EXTS = EMBED_MIME_TYPES.keys
|
24
|
+
EMBED_FONTS = ['.ttf', '.otf']
|
25
|
+
|
26
|
+
# Maximum size for embeddable images (an IE8 limitation).
|
27
|
+
MAX_IMAGE_SIZE = 32 * 1024
|
28
|
+
|
29
|
+
# CSS asset-embedding regexes for URL rewriting.
|
30
|
+
EMBED_DETECTOR = /url\(['"]?([^\s)]+\.[a-z]+)(\?\d+)?['"]?\)/
|
31
|
+
EMBEDDABLE = /[\A\/]embed\//
|
32
|
+
EMBED_REPLACER = /url\(__EMBED__([^\s)]+)(\?\d+)?\)/
|
33
|
+
|
34
|
+
# MHTML file constants.
|
35
|
+
MHTML_START = "/*\r\nContent-Type: multipart/related; boundary=\"JAMMIT_MHTML_SEPARATOR\"\r\n\r\n"
|
36
|
+
MHTML_SEPARATOR = "--JAMMIT_MHTML_SEPARATOR\r\n"
|
37
|
+
MHTML_END = "*/\r\n"
|
38
|
+
|
39
|
+
# JST file constants.
|
40
|
+
JST_START = "(function(){"
|
41
|
+
JST_END = "})();"
|
42
|
+
|
43
|
+
COMPRESSORS = {
|
44
|
+
:yui => YUI::JavaScriptCompressor,
|
45
|
+
:closure => Closure::Compiler
|
46
|
+
}
|
47
|
+
|
48
|
+
DEFAULT_OPTIONS = {
|
49
|
+
:yui => {:munge => true},
|
50
|
+
:closure => {}
|
51
|
+
}
|
52
|
+
|
53
|
+
# Creating a compressor initializes the internal YUI Compressor from
|
54
|
+
# the "yui-compressor" gem, or the internal Closure Compiler from the
|
55
|
+
# "closure-compiler" gem.
|
56
|
+
def initialize
|
57
|
+
@css_compressor = YUI::CssCompressor.new(Jammit.config[:css_compressor_options] || {})
|
58
|
+
flavor = Jammit.config[:javascript_compressor] || Jammit::DEFAULT_COMPRESSOR
|
59
|
+
@options = DEFAULT_OPTIONS[flavor].merge(Jammit.config[:compressor_options] || {})
|
60
|
+
@js_compressor = COMPRESSORS[flavor].new(@options)
|
61
|
+
end
|
62
|
+
|
63
|
+
# Concatenate together a list of JavaScript paths, and pass them through the
|
64
|
+
# YUI Compressor (with munging enabled).
|
65
|
+
def compress_js(paths)
|
66
|
+
js = concatenate(paths)
|
67
|
+
Jammit.config[:compress_assets] ? @js_compressor.compress(js) : js
|
68
|
+
end
|
69
|
+
|
70
|
+
# Concatenate and compress a list of CSS stylesheets. When compressing a
|
71
|
+
# :datauri or :mhtml variant, post-processes the result to embed
|
72
|
+
# referenced assets.
|
73
|
+
def compress_css(paths, variant=nil, asset_url=nil)
|
74
|
+
css = concatenate_and_tag_assets(paths, variant)
|
75
|
+
css = @css_compressor.compress(css) if Jammit.compress_assets
|
76
|
+
case variant
|
77
|
+
when nil then return css
|
78
|
+
when :datauri then return with_data_uris(css)
|
79
|
+
when :mhtml then return with_mhtml(css, asset_url)
|
80
|
+
else raise PackageNotFound, "\"#{variant}\" is not a valid stylesheet variant"
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
# Compiles a single JST file by writing out a javascript that adds
|
85
|
+
# template properties to a top-level template namespace object. Adds a
|
86
|
+
# JST-compilation function to the top of the package, unless you've
|
87
|
+
# specified your own preferred function, or turned it off.
|
88
|
+
# JST templates are named with the basename of their file.
|
89
|
+
def compile_jst(paths)
|
90
|
+
namespace = Jammit.template_namespace
|
91
|
+
compiled = paths.map do |path|
|
92
|
+
template_name = File.basename(path, File.extname(path))
|
93
|
+
contents = File.read(path).gsub(/\n/, '').gsub("'", '\\\\\'')
|
94
|
+
"#{namespace}.#{template_name} = #{Jammit.template_function}('#{contents}');"
|
95
|
+
end
|
96
|
+
compiler = Jammit.config[:include_jst_script] ? File.read(Jammit::DEFAULT_JST_SCRIPT) : '';
|
97
|
+
setup_namespace = "#{namespace} = #{namespace} || {};"
|
98
|
+
[JST_START, setup_namespace, compiler, compiled, JST_END].flatten.join("\n")
|
99
|
+
end
|
100
|
+
|
101
|
+
|
102
|
+
private
|
103
|
+
|
104
|
+
# In order to support embedded assets from relative paths, we need to
|
105
|
+
# expand the paths before contatenating the CSS together and losing the
|
106
|
+
# location of the original stylesheet path. Validate the assets while we're
|
107
|
+
# at it.
|
108
|
+
def concatenate_and_tag_assets(paths, variant=nil)
|
109
|
+
stylesheets = [paths].flatten.map do |css_path|
|
110
|
+
File.read(css_path).gsub(EMBED_DETECTOR) do |url|
|
111
|
+
ipath, cpath = Pathname.new($1), Pathname.new(File.expand_path(css_path))
|
112
|
+
is_url = URI.parse($1).absolute?
|
113
|
+
is_url ? url : "url(#{construct_asset_path(ipath, cpath, variant)})"
|
114
|
+
end
|
115
|
+
end
|
116
|
+
stylesheets.join("\n")
|
117
|
+
end
|
118
|
+
|
119
|
+
# Re-write all enabled asset URLs in a stylesheet with their corresponding
|
120
|
+
# Data-URI Base-64 encoded asset contents.
|
121
|
+
def with_data_uris(css)
|
122
|
+
css.gsub(EMBED_REPLACER) do |url|
|
123
|
+
"url(\"data:#{mime_type($1)};charset=utf-8;base64,#{encoded_contents($1)}\")"
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
# Re-write all enabled asset URLs in a stylesheet with the MHTML equivalent.
|
128
|
+
# The newlines ("\r\n") in the following method are critical. Without them
|
129
|
+
# your MHTML will look identical, but won't work.
|
130
|
+
def with_mhtml(css, asset_url)
|
131
|
+
paths, index = {}, 0
|
132
|
+
css = css.gsub(EMBED_REPLACER) do |url|
|
133
|
+
i = paths[$1] ||= "#{index += 1}-#{File.basename($1)}"
|
134
|
+
"url(mhtml:#{asset_url}!#{i})"
|
135
|
+
end
|
136
|
+
mhtml = paths.sort.map do |path, identifier|
|
137
|
+
mime, contents = mime_type(path), encoded_contents(path)
|
138
|
+
[MHTML_SEPARATOR, "Content-Location: #{identifier}\r\n", "Content-Type: #{mime}\r\n", "Content-Transfer-Encoding: base64\r\n\r\n", contents, "\r\n"]
|
139
|
+
end
|
140
|
+
[MHTML_START, mhtml, MHTML_END, css].flatten.join('')
|
141
|
+
end
|
142
|
+
|
143
|
+
# Return a rewritten asset URL for a new stylesheet -- the asset should
|
144
|
+
# be tagged for embedding if embeddable, and referenced at the correct level
|
145
|
+
# if relative.
|
146
|
+
def construct_asset_path(asset_path, css_path, variant)
|
147
|
+
public_path = absolute_path(asset_path, css_path)
|
148
|
+
return "__EMBED__#{public_path}" if embeddable?(public_path, variant)
|
149
|
+
source = asset_path.absolute? ? asset_path.to_s : relative_path(public_path)
|
150
|
+
rewrite_asset_path(source, public_path)
|
151
|
+
end
|
152
|
+
|
153
|
+
# Get the site-absolute public path for an asset file path that may or may
|
154
|
+
# not be relative, given the path of the stylesheet that contains it.
|
155
|
+
def absolute_path(asset_pathname, css_pathname)
|
156
|
+
(asset_pathname.absolute? ?
|
157
|
+
Pathname.new(File.join(PUBLIC_ROOT, asset_pathname)) :
|
158
|
+
css_pathname.dirname + asset_pathname).cleanpath
|
159
|
+
end
|
160
|
+
|
161
|
+
# CSS assets that are referenced by relative paths, and are *not* being
|
162
|
+
# embedded, must be rewritten relative to the newly-merged stylesheet path.
|
163
|
+
def relative_path(absolute_path)
|
164
|
+
File.join('../', absolute_path.sub(PUBLIC_ROOT, ''))
|
165
|
+
end
|
166
|
+
|
167
|
+
# Similar to the AssetTagHelper's method of the same name, this will
|
168
|
+
# append the RAILS_ASSET_ID cache-buster to URLs, if it's defined.
|
169
|
+
def rewrite_asset_path(path, file_path)
|
170
|
+
asset_id = rails_asset_id(file_path)
|
171
|
+
asset_id.blank? ? path : "#{path}?#{asset_id}"
|
172
|
+
end
|
173
|
+
|
174
|
+
# Similar to the AssetTagHelper's method of the same name, this will
|
175
|
+
# determine the correct asset id for a file.
|
176
|
+
def rails_asset_id(path)
|
177
|
+
asset_id = ENV["RAILS_ASSET_ID"]
|
178
|
+
return asset_id if asset_id
|
179
|
+
File.exists?(path) ? File.mtime(path).to_i.to_s : ''
|
180
|
+
end
|
181
|
+
|
182
|
+
# An asset is valid for embedding if it exists, is less than 32K, and is
|
183
|
+
# stored somewhere inside of a folder named "embed".
|
184
|
+
# IE does not support Data-URIs larger than 32K, and you probably shouldn't
|
185
|
+
# be embedding assets that large in any case.
|
186
|
+
def embeddable?(asset_path, variant)
|
187
|
+
font = EMBED_FONTS.include?(asset_path.extname)
|
188
|
+
return false unless variant
|
189
|
+
return false unless asset_path.to_s.match(EMBEDDABLE) && asset_path.exist?
|
190
|
+
return false unless EMBED_EXTS.include?(asset_path.extname)
|
191
|
+
return false unless font || asset_path.size < MAX_IMAGE_SIZE
|
192
|
+
return false if font && variant == :mhtml
|
193
|
+
true
|
194
|
+
end
|
195
|
+
|
196
|
+
# Return the Base64-encoded contents of an asset on a single line.
|
197
|
+
def encoded_contents(asset_path)
|
198
|
+
data = File.open(asset_path, 'rb'){|f| f.read }
|
199
|
+
Base64.encode64(data).gsub(/\n/, '')
|
200
|
+
end
|
201
|
+
|
202
|
+
# Grab the mime-type of an asset, by filename.
|
203
|
+
def mime_type(asset_path)
|
204
|
+
EMBED_MIME_TYPES[File.extname(asset_path)]
|
205
|
+
end
|
206
|
+
|
207
|
+
# Concatenate together a list of asset files.
|
208
|
+
def concatenate(paths)
|
209
|
+
[paths].flatten.map {|p| File.read(p) }.join("\n")
|
210
|
+
end
|
211
|
+
|
212
|
+
end
|
213
|
+
|
214
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
module Jammit
|
2
|
+
module Config
|
3
|
+
|
4
|
+
CONFIG_TEMPLATE = Jammit::ROOT + '/assets.example.yml'
|
5
|
+
|
6
|
+
class << self
|
7
|
+
|
8
|
+
def dispatch(command, *params)
|
9
|
+
case command
|
10
|
+
when :create
|
11
|
+
create
|
12
|
+
when :set
|
13
|
+
set(params.shift, params.shift)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
##
|
18
|
+
# load configuration file
|
19
|
+
# @param {String} path
|
20
|
+
# @param {Boolean} force reloading of config file
|
21
|
+
#
|
22
|
+
def load(force=false)
|
23
|
+
raise Jammit::ConfigurationNotFound, "could not find the \"#{Jammit.config_path}\" configuration file" unless File.exists?(Jammit.config_path) && File.readable?(Jammit.config_path)
|
24
|
+
if !@config || force == true
|
25
|
+
@config = YAML.load(ERB.new(File.read(Jammit.config_path)).result)
|
26
|
+
end
|
27
|
+
@config
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
##
|
33
|
+
# Write config to file
|
34
|
+
#
|
35
|
+
def write(config)
|
36
|
+
File.open(Jammit.config_path, "w") {|f|
|
37
|
+
f << config.to_yaml
|
38
|
+
}
|
39
|
+
end
|
40
|
+
|
41
|
+
##
|
42
|
+
# If a config path is given, use that as the root, otherwise use DEFAULT_CONFIG_PATH
|
43
|
+
#
|
44
|
+
def create
|
45
|
+
if File.exists?(Jammit.config_path)
|
46
|
+
raise Jammit::AlreadyConfigured.new(" Config file #{Jammit.config_path} already exists.")
|
47
|
+
end
|
48
|
+
FileUtils.mkdir_p(File.dirname(Jammit.config_path))
|
49
|
+
FileUtils.cp(CONFIG_TEMPLATE, Jammit.config_path)
|
50
|
+
|
51
|
+
parts = Jammit.config_path.split('/')
|
52
|
+
name = parts.pop
|
53
|
+
dir = parts.pop
|
54
|
+
Jammit.ui.confirm(" create #{dir}/#{name}")
|
55
|
+
end
|
56
|
+
|
57
|
+
##
|
58
|
+
# Set a config property in file
|
59
|
+
# @param {String} name
|
60
|
+
# @param {String} value
|
61
|
+
#
|
62
|
+
def set(name, value)
|
63
|
+
value = (value == "true") ? true : (value == "false") ? false : value
|
64
|
+
|
65
|
+
config = load(true)
|
66
|
+
option = config[name]
|
67
|
+
|
68
|
+
# careful not to clobber raexisting values if updating a hash
|
69
|
+
if value.kind_of?(Hash) && option.kind_of?(Hash)
|
70
|
+
value.keys.each do |k|
|
71
|
+
option[k] = value[k]
|
72
|
+
end
|
73
|
+
config.update(name => option)
|
74
|
+
else
|
75
|
+
config.update(name => value)
|
76
|
+
end
|
77
|
+
write(config)
|
78
|
+
Jammit.ui.confirm(" set #{name}")
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# Standard Library Dependencies:
|
2
|
+
require 'uri'
|
3
|
+
require 'erb'
|
4
|
+
require 'zlib'
|
5
|
+
require 'base64'
|
6
|
+
require 'pathname'
|
7
|
+
require 'fileutils'
|
8
|
+
require 'json'
|
9
|
+
|
10
|
+
# Pull in some extlib goodies
|
11
|
+
require 'extlib/class'
|
12
|
+
require 'extlib/hash'
|
13
|
+
require 'extlib/mash'
|
14
|
+
require 'extlib/inflection'
|
15
|
+
|
16
|
+
# Gem Dependencies:
|
17
|
+
require 'rubygems'
|
18
|
+
require 'yui/compressor'
|
19
|
+
require 'closure-compiler'
|
20
|
+
|
21
|
+
# Jammit Core:
|
22
|
+
require 'jammit-core/compressor'
|
23
|
+
require 'jammit-core/packager'
|
@@ -0,0 +1,77 @@
|
|
1
|
+
module Jammit
|
2
|
+
|
3
|
+
# The Jammit::Helper module, which is made available to every view, provides
|
4
|
+
# helpers for writing out HTML tags for asset packages. In development you
|
5
|
+
# get the ordered list of source files -- in any other environment, a link
|
6
|
+
# to the cached packages.
|
7
|
+
module Helper
|
8
|
+
|
9
|
+
DATA_URI_START = "<!--[if (!IE)|(gte IE 8)]><!-->"
|
10
|
+
DATA_URI_END = "<!--<![endif]-->"
|
11
|
+
MHTML_START = "<!--[if lte IE 7]>"
|
12
|
+
MHTML_END = "<![endif]-->"
|
13
|
+
|
14
|
+
# If embed_assets is turned on, writes out links to the Data-URI and MHTML
|
15
|
+
# versions of the stylesheet package, otherwise the package is regular
|
16
|
+
# compressed CSS, and in development the stylesheet URLs are passed verbatim.
|
17
|
+
def include_stylesheets(*packages)
|
18
|
+
options = packages.extract_options!
|
19
|
+
return individual_stylesheets(packages, options) unless Jammit.package_assets
|
20
|
+
disabled = (options.delete(:embed_assets) == false) || (options.delete(:embed_images) == false)
|
21
|
+
return packaged_stylesheets(packages, options) if disabled || !Jammit.embed_assets
|
22
|
+
return embedded_image_stylesheets(packages, options)
|
23
|
+
end
|
24
|
+
|
25
|
+
# Writes out the URL to the bundled and compressed javascript package,
|
26
|
+
# except in development, where it references the individual scripts.
|
27
|
+
def include_javascripts(*packages)
|
28
|
+
tags = packages.map do |pack|
|
29
|
+
Jammit.package_assets ? Jammit.asset_url(pack, :js) : Jammit.packager.individual_urls(pack.to_sym, :js)
|
30
|
+
end
|
31
|
+
javascript_include_tag(tags.flatten)
|
32
|
+
end
|
33
|
+
|
34
|
+
# Writes out the URL to the concatenated and compiled JST file -- we always
|
35
|
+
# have to pre-process it, even in development.
|
36
|
+
def include_templates(*packages)
|
37
|
+
javascript_include_tag(packages.map {|pack| Jammit.asset_url(pack, :jst) })
|
38
|
+
end
|
39
|
+
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
# HTML tags, in order, for all of the individual stylesheets.
|
44
|
+
def individual_stylesheets(packages, options)
|
45
|
+
tags_with_options(packages, options) {|p| Jammit.packager.individual_urls(p.to_sym, :css) }
|
46
|
+
end
|
47
|
+
|
48
|
+
# HTML tags for the stylesheet packages.
|
49
|
+
def packaged_stylesheets(packages, options)
|
50
|
+
tags_with_options(packages, options) {|p| Jammit.asset_url(p, :css) }
|
51
|
+
end
|
52
|
+
|
53
|
+
# HTML tags for the 'datauri', and 'mhtml' versions of the packaged
|
54
|
+
# stylesheets, using conditional comments to load the correct variant.
|
55
|
+
def embedded_image_stylesheets(packages, options)
|
56
|
+
datauri_tags = tags_with_options(packages, options) {|p| Jammit.asset_url(p, :css, :datauri) }
|
57
|
+
ie_tags = Jammit.mhtml_enabled ?
|
58
|
+
tags_with_options(packages, options) {|p| Jammit.asset_url(p, :css, :mhtml) } :
|
59
|
+
packaged_stylesheets(packages, options)
|
60
|
+
[DATA_URI_START, datauri_tags, DATA_URI_END, MHTML_START, ie_tags, MHTML_END].join("\n")
|
61
|
+
end
|
62
|
+
|
63
|
+
# Generate the stylesheet tags for a batch of packages, with options, by
|
64
|
+
# yielding each package to a block.
|
65
|
+
def tags_with_options(packages, options)
|
66
|
+
packages = packages.dup
|
67
|
+
packages.map! {|package| yield package }.flatten!
|
68
|
+
packages.push(options) unless options.empty?
|
69
|
+
stylesheet_link_tag(*packages)
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
|
76
|
+
# Include the Jammit asset helpers in all views, a-la ApplicationHelper.
|
77
|
+
::ActionView::Base.send(:include, Jammit::Helper)
|