merb-assets 0.9.2
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/LICENSE +20 -0
- data/README +4 -0
- data/Rakefile +44 -0
- data/TODO +5 -0
- data/lib/merb-assets.rb +14 -0
- data/lib/merb-assets/assets.rb +198 -0
- data/lib/merb-assets/assets_mixin.rb +562 -0
- metadata +70 -0
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2008 YOUR NAME
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake/gempackagetask'
|
3
|
+
|
4
|
+
PLUGIN = "merb-assets"
|
5
|
+
NAME = "merb-assets"
|
6
|
+
VERSION = "0.9.2"
|
7
|
+
AUTHOR = "Ezra Zygmuntowicz"
|
8
|
+
EMAIL = "ez@engineyard.com"
|
9
|
+
HOMEPAGE = "http://merb-plugins.rubyforge.org/merb-assets/"
|
10
|
+
SUMMARY = "Merb plugin that provides the helpers for assets and asset bundling"
|
11
|
+
|
12
|
+
spec = Gem::Specification.new do |s|
|
13
|
+
s.name = NAME
|
14
|
+
s.version = VERSION
|
15
|
+
s.platform = Gem::Platform::RUBY
|
16
|
+
s.has_rdoc = true
|
17
|
+
s.extra_rdoc_files = ["README", "LICENSE", 'TODO']
|
18
|
+
s.summary = SUMMARY
|
19
|
+
s.description = s.summary
|
20
|
+
s.author = AUTHOR
|
21
|
+
s.email = EMAIL
|
22
|
+
s.homepage = HOMEPAGE
|
23
|
+
s.add_dependency('merb-core', '>= 0.9.2')
|
24
|
+
s.require_path = 'lib'
|
25
|
+
s.autorequire = PLUGIN
|
26
|
+
s.files = %w(LICENSE README Rakefile TODO) + Dir.glob("{lib,specs}/**/*")
|
27
|
+
end
|
28
|
+
|
29
|
+
Rake::GemPackageTask.new(spec) do |pkg|
|
30
|
+
pkg.gem_spec = spec
|
31
|
+
end
|
32
|
+
|
33
|
+
task :install => [:package] do
|
34
|
+
sh %{sudo gem install pkg/#{NAME}-#{VERSION} --no-update-sources --no-update-sources}
|
35
|
+
end
|
36
|
+
|
37
|
+
namespace :jruby do
|
38
|
+
|
39
|
+
desc "Run :package and install the resulting .gem with jruby"
|
40
|
+
task :install => :package do
|
41
|
+
sh %{#{SUDO} jruby -S gem install pkg/#{NAME}-#{Merb::VERSION}.gem --no-rdoc --no-ri}
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
data/TODO
ADDED
data/lib/merb-assets.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'merb-assets/assets'
|
2
|
+
require 'merb-assets/assets_mixin'
|
3
|
+
|
4
|
+
Merb::BootLoader.before_app_loads do
|
5
|
+
Merb::Controller.send(:include, Merb::AssetsMixin)
|
6
|
+
end
|
7
|
+
|
8
|
+
|
9
|
+
Merb::Plugins.config[:asset_helpers] = {
|
10
|
+
:max_hosts => 4,
|
11
|
+
:asset_domain => "assets%s",
|
12
|
+
:domain => "my-awesome-domain.com",
|
13
|
+
:use_ssl => false
|
14
|
+
} if Merb::Plugins.config[:asset_helpers].nil?
|
@@ -0,0 +1,198 @@
|
|
1
|
+
module Merb
|
2
|
+
module Assets
|
3
|
+
|
4
|
+
# Check whether the assets should be bundled.
|
5
|
+
#
|
6
|
+
# ==== Returns
|
7
|
+
# Boolean::
|
8
|
+
# True if the assets should be bundled (e.g., production mode or
|
9
|
+
# :bundle_assets is explicitly enabled).
|
10
|
+
def self.bundle?
|
11
|
+
(Merb.environment == 'production') ||
|
12
|
+
(!!Merb::Config[:bundle_assets])
|
13
|
+
end
|
14
|
+
|
15
|
+
# Helpers for handling asset files.
|
16
|
+
module AssetHelpers
|
17
|
+
# :nodoc:
|
18
|
+
ASSET_FILE_EXTENSIONS = {
|
19
|
+
:javascript => ".js",
|
20
|
+
:stylesheet => ".css"
|
21
|
+
}
|
22
|
+
|
23
|
+
# Returns the URI path to a particular asset file. If +local_path+ is
|
24
|
+
# true, returns the path relative to the Merb.root, not the public
|
25
|
+
# directory. Uses the path_prefix, if any is configured.
|
26
|
+
#
|
27
|
+
# ==== Parameters
|
28
|
+
# asset_type<Symbol>:: Type of the asset (e.g. :javascript).
|
29
|
+
# filename<~to_s>:: The path to the file.
|
30
|
+
# local_path<Boolean>::
|
31
|
+
# If true, the returned path will be relative to the Merb.root,
|
32
|
+
# otherwise it will be the public URI path. Defaults to false.
|
33
|
+
#
|
34
|
+
# ==== Returns
|
35
|
+
# String:: The path to the asset.
|
36
|
+
#
|
37
|
+
# ==== Examples
|
38
|
+
# asset_path(:javascript, :dingo)
|
39
|
+
# # => "/javascripts/dingo.js"
|
40
|
+
#
|
41
|
+
# asset_path(:javascript, :dingo, true)
|
42
|
+
# # => "public/javascripts/dingo.js"
|
43
|
+
def asset_path(asset_type, filename, local_path = false)
|
44
|
+
filename = filename.to_s
|
45
|
+
if filename !~ /#{'\\' + ASSET_FILE_EXTENSIONS[asset_type]}\Z/
|
46
|
+
filename << ASSET_FILE_EXTENSIONS[asset_type]
|
47
|
+
end
|
48
|
+
filename = "/#{asset_type}s/#{filename}"
|
49
|
+
if local_path
|
50
|
+
return "public#{filename}"
|
51
|
+
else
|
52
|
+
return "#{Merb::Config[:path_prefix]}#{filename}"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# Helper for creating unique paths to a file name
|
58
|
+
# Can increase speend for browsers that are limited to a certain number of connections per host
|
59
|
+
# for downloading static files (css, js, images...)
|
60
|
+
class UniqueAssetPath
|
61
|
+
class << self
|
62
|
+
@@config = Merb::Plugins.config[:asset_helpers]
|
63
|
+
|
64
|
+
# Builds the path to the file based on the name
|
65
|
+
#
|
66
|
+
# ==== Parameters
|
67
|
+
# filename<String>:: Name of file to generate path for
|
68
|
+
#
|
69
|
+
# ==== Returns
|
70
|
+
# String:: The path to the asset.
|
71
|
+
#
|
72
|
+
# ==== Examples
|
73
|
+
# build("/javascripts/my_fancy_script.js")
|
74
|
+
# # => "https://assets5.my-awesome-domain.com/javascripts/my_fancy_script.js"
|
75
|
+
#
|
76
|
+
def build(filename)
|
77
|
+
#%{#{(USE_SSL ? 'https' : 'http')}://#{sprintf(@@config[:asset_domain],self.calculate_host_id(file))}.#{@@config[:domain]}/#{filename}}
|
78
|
+
path = @@config[:use_ssl] ? 'https://' : 'http://'
|
79
|
+
path << sprintf(@@config[:asset_domain],self.calculate_host_id(filename)) << ".#{@@config[:domain]}"
|
80
|
+
path << "/" if filename.index('/') != 0
|
81
|
+
path << filename
|
82
|
+
end
|
83
|
+
|
84
|
+
protected
|
85
|
+
|
86
|
+
# Calculates the id for the host
|
87
|
+
def calculate_host_id(filename)
|
88
|
+
ascii_total = 0
|
89
|
+
filename.each_byte {|byte|
|
90
|
+
ascii_total += byte
|
91
|
+
}
|
92
|
+
(ascii_total % @@config[:max_hosts] + 1)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
# An abstract class for bundling text assets into single files.
|
98
|
+
class AbstractAssetBundler
|
99
|
+
class << self
|
100
|
+
|
101
|
+
# ==== Parameters
|
102
|
+
# &block:: A block to add as a post-bundle callback.
|
103
|
+
#
|
104
|
+
# ==== Examples
|
105
|
+
# add_callback { |filename| `yuicompressor #{filename}` }
|
106
|
+
def add_callback(&block)
|
107
|
+
callbacks << block
|
108
|
+
end
|
109
|
+
alias_method :after_bundling, :add_callback
|
110
|
+
|
111
|
+
# Retrieve existing callbacks.
|
112
|
+
#
|
113
|
+
# ==== Returns
|
114
|
+
# Array[Proc]:: An array of existing callbacks.
|
115
|
+
def callbacks
|
116
|
+
@callbacks ||= []
|
117
|
+
return @callbacks
|
118
|
+
end
|
119
|
+
|
120
|
+
# The type of asset for which the bundler is responsible. Override
|
121
|
+
# this method in your bundler code.
|
122
|
+
#
|
123
|
+
# ==== Raises
|
124
|
+
# NotImplementedError:: This method is implemented by the bundler.
|
125
|
+
#
|
126
|
+
# ==== Returns
|
127
|
+
# Symbol:: The type of the asset
|
128
|
+
def asset_type
|
129
|
+
raise NotImplementedError, "should return a symbol for the first argument to be passed to asset_path"
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
# ==== Parameters
|
134
|
+
# name<~to_s>::
|
135
|
+
# Name of the bundle. If name is true, it will be converted to :all.
|
136
|
+
# *files<String>:: Names of the files to bundle.
|
137
|
+
def initialize(name, *files)
|
138
|
+
@bundle_name = name == true ? :all : name
|
139
|
+
@bundle_filename = asset_path(self.class.asset_type, @bundle_name, true)
|
140
|
+
@files = files.map { |f| asset_path(self.class.asset_type, f, true) }
|
141
|
+
end
|
142
|
+
|
143
|
+
# Creates the new bundled file, executing all the callbacks.
|
144
|
+
#
|
145
|
+
# ==== Returns
|
146
|
+
# Symbol:: Name of the bundle.
|
147
|
+
def bundle!
|
148
|
+
# TODO: Move this file check out into an in-memory cache. Also, push it out to the helper level so we don't have to create the helper object.
|
149
|
+
unless File.exist?(@bundle_filename)
|
150
|
+
bundle_files(@bundle_filename, *@files)
|
151
|
+
self.class.callbacks.each { |c| c.call(@bundle_filename) }
|
152
|
+
end
|
153
|
+
return @bundle_name
|
154
|
+
end
|
155
|
+
|
156
|
+
protected
|
157
|
+
|
158
|
+
include Merb::Assets::AssetHelpers # for asset_path
|
159
|
+
|
160
|
+
# Bundle all the files into one.
|
161
|
+
#
|
162
|
+
# ==== Parameters
|
163
|
+
# filename<String>:: Name of the bundle file.
|
164
|
+
# *files<String>:: Filenames to be bundled.
|
165
|
+
def bundle_files(filename, *files)
|
166
|
+
File.open(filename, "w") do |f|
|
167
|
+
files.each { |file| f.puts(File.read(file)) }
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
end
|
172
|
+
|
173
|
+
# Bundles javascripts into a single file:
|
174
|
+
#
|
175
|
+
# javascripts/#{name}.js
|
176
|
+
class JavascriptAssetBundler < AbstractAssetBundler
|
177
|
+
|
178
|
+
# ==== Returns
|
179
|
+
# Symbol:: The asset type, i.e. :javascript.
|
180
|
+
def self.asset_type
|
181
|
+
:javascript
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
# Bundles stylesheets into a single file:
|
186
|
+
#
|
187
|
+
# stylesheets/#{name}.css
|
188
|
+
class StylesheetAssetBundler < AbstractAssetBundler
|
189
|
+
|
190
|
+
# ==== Returns
|
191
|
+
# Symbol:: The asset type, i.e. :stylesheet.
|
192
|
+
def self.asset_type
|
193
|
+
:stylesheet
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
end
|
198
|
+
end
|
@@ -0,0 +1,562 @@
|
|
1
|
+
module Merb
|
2
|
+
# The AssetsMixin module provides a number of helper methods to views for
|
3
|
+
# linking to assets and other pages, dealing with JavaScript and CSS.
|
4
|
+
module AssetsMixin
|
5
|
+
include Merb::Assets::AssetHelpers
|
6
|
+
# :section: Accessing Assets
|
7
|
+
# Merb provides views with convenience methods for links images and other
|
8
|
+
# assets.
|
9
|
+
|
10
|
+
# ==== Parameters
|
11
|
+
# name<~to_s>:: The text of the link.
|
12
|
+
# url<~to_s>:: The URL to link to. Defaults to an empty string.
|
13
|
+
# opts<Hash>:: Additional HTML options for the link.
|
14
|
+
#
|
15
|
+
# ==== Examples
|
16
|
+
# link_to("The Merb home page", "http://www.merbivore.com/")
|
17
|
+
# # => <a href="http://www.merbivore.com/">The Merb home page</a>
|
18
|
+
#
|
19
|
+
# link_to("The Ruby home page", "http://www.ruby-lang.org", {'class' => 'special', 'target' => 'blank'})
|
20
|
+
# # => <a href="http://www.ruby-lang.org" class="special" target="blank">The Ruby home page</a>
|
21
|
+
#
|
22
|
+
# link_to p.title, "/blog/show/#{p.id}"
|
23
|
+
# # => <a href="blog/show/13">The Entry Title</a>
|
24
|
+
#
|
25
|
+
def link_to(name, url='', opts={})
|
26
|
+
opts[:href] ||= url
|
27
|
+
%{<a #{ opts.to_xml_attributes }>#{name}</a>}
|
28
|
+
end
|
29
|
+
|
30
|
+
# ==== Parameters
|
31
|
+
# img<~to_s>:: The image path.
|
32
|
+
# opts<Hash>:: Additional options for the image tag (see below).
|
33
|
+
#
|
34
|
+
# ==== Options (opts)
|
35
|
+
# :path<String>::
|
36
|
+
# Sets the path prefix for the image. Defaults to "/images/" or whatever
|
37
|
+
# is specified in Merb::Config. This is ignored if img is an absolute
|
38
|
+
# path or full URL.
|
39
|
+
#
|
40
|
+
# All other options set HTML attributes on the tag.
|
41
|
+
#
|
42
|
+
# ==== Examples
|
43
|
+
# image_tag('foo.gif')
|
44
|
+
# # => <img src='/images/foo.gif' />
|
45
|
+
#
|
46
|
+
# image_tag('foo.gif', :class => 'bar')
|
47
|
+
# # => <img src='/images/foo.gif' class='bar' />
|
48
|
+
#
|
49
|
+
# image_tag('foo.gif', :path => '/files/')
|
50
|
+
# # => <img src='/files/foo.gif' />
|
51
|
+
#
|
52
|
+
# image_tag('http://test.com/foo.gif')
|
53
|
+
# # => <img src="http://test.com/foo.gif">
|
54
|
+
#
|
55
|
+
# image_tag('charts', :path => '/dynamic/')
|
56
|
+
# or
|
57
|
+
# image_tag('/dynamic/charts')
|
58
|
+
# # => <img src="/dynamic/charts">
|
59
|
+
def image_tag(img, opts={})
|
60
|
+
if img[0].chr == '/'
|
61
|
+
opts[:src] = img
|
62
|
+
else
|
63
|
+
opts[:path] ||=
|
64
|
+
if img =~ %r{^https?://}
|
65
|
+
''
|
66
|
+
else
|
67
|
+
if Merb::Config[:path_prefix]
|
68
|
+
Merb::Config[:path_prefix] + '/images/'
|
69
|
+
else
|
70
|
+
'/images/'
|
71
|
+
end
|
72
|
+
end
|
73
|
+
opts[:src] ||= opts.delete(:path) + img
|
74
|
+
end
|
75
|
+
%{<img #{ opts.to_xml_attributes } />}
|
76
|
+
end
|
77
|
+
|
78
|
+
# :section: JavaScript related functions
|
79
|
+
#
|
80
|
+
|
81
|
+
# ==== Parameters
|
82
|
+
# javascript<String>:: Text to escape for use in JavaScript.
|
83
|
+
#
|
84
|
+
# ==== Examples
|
85
|
+
# escape_js("'Lorem ipsum!' -- Some guy")
|
86
|
+
# # => "\\'Lorem ipsum!\\' -- Some guy"
|
87
|
+
#
|
88
|
+
# escape_js("Please keep text\nlines as skinny\nas possible.")
|
89
|
+
# # => "Please keep text\\nlines as skinny\\nas possible."
|
90
|
+
def escape_js(javascript)
|
91
|
+
(javascript || '').gsub('\\','\0\0').gsub(/\r\n|\n|\r/, "\\n").gsub(/["']/) { |m| "\\#{m}" }
|
92
|
+
end
|
93
|
+
|
94
|
+
# ==== Parameters
|
95
|
+
# name<~to_s>:: The text in the link.
|
96
|
+
# function<~to_s>:: The onClick event in JavaScript.
|
97
|
+
#
|
98
|
+
# ==== Examples
|
99
|
+
# link_to_function('Click me', "alert('hi!')")
|
100
|
+
# # => <a href="#" onclick="alert('hi!'); return false;">Click me</a>
|
101
|
+
#
|
102
|
+
# link_to_function('Add to cart', "item_total += 1; alert('Item added!');")
|
103
|
+
# # => <a href="#" onclick="item_total += 1; alert('Item added!'); return false;">Add to cart</a>
|
104
|
+
def link_to_function(name, function)
|
105
|
+
%{<a href="#" onclick="#{function}; return false;">#{name}</a>}
|
106
|
+
end
|
107
|
+
|
108
|
+
# ==== Parameters
|
109
|
+
# data<Object>::
|
110
|
+
# Object to translate into JSON. If the object does not respond to
|
111
|
+
# :to_json, then data.inspect.to_json is returned instead.
|
112
|
+
#
|
113
|
+
# ==== Examples
|
114
|
+
# js({'user' => 'Lewis', 'page' => 'home'})
|
115
|
+
# # => "{\"user\":\"Lewis\",\"page\":\"home\"}"
|
116
|
+
#
|
117
|
+
# js([ 1, 2, {"a"=>3.141}, false, true, nil, 4..10 ])
|
118
|
+
# # => "[1,2,{\"a\":3.141},false,true,null,\"4..10\"]"
|
119
|
+
def js(data)
|
120
|
+
if data.respond_to? :to_json
|
121
|
+
data.to_json
|
122
|
+
else
|
123
|
+
data.inspect.to_json
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
# :section: External JavaScript and Stylesheets
|
128
|
+
#
|
129
|
+
# You can use require_js(:prototype) or require_css(:shinystyles)
|
130
|
+
# from any view or layout, and the scripts will only be included once
|
131
|
+
# in the head of the final page. To get this effect, the head of your
|
132
|
+
# layout you will need to include a call to include_required_js and
|
133
|
+
# include_required_css.
|
134
|
+
#
|
135
|
+
# ==== Examples
|
136
|
+
# # File: app/views/layouts/application.html.erb
|
137
|
+
#
|
138
|
+
# <html>
|
139
|
+
# <head>
|
140
|
+
# <%= include_required_js %>
|
141
|
+
# <%= include_required_css %>
|
142
|
+
# </head>
|
143
|
+
# <body>
|
144
|
+
# <%= catch_content :layout %>
|
145
|
+
# </body>
|
146
|
+
# </html>
|
147
|
+
#
|
148
|
+
# # File: app/views/whatever/_part1.herb
|
149
|
+
#
|
150
|
+
# <% require_js 'this' -%>
|
151
|
+
# <% require_css 'that', 'another_one' -%>
|
152
|
+
#
|
153
|
+
# # File: app/views/whatever/_part2.herb
|
154
|
+
#
|
155
|
+
# <% require_js 'this', 'something_else' -%>
|
156
|
+
# <% require_css 'that' -%>
|
157
|
+
#
|
158
|
+
# # File: app/views/whatever/index.herb
|
159
|
+
#
|
160
|
+
# <%= partial(:part1) %>
|
161
|
+
# <%= partial(:part2) %>
|
162
|
+
#
|
163
|
+
# # Will generate the following in the final page...
|
164
|
+
# <html>
|
165
|
+
# <head>
|
166
|
+
# <script src="/javascripts/this.js" type="text/javascript"></script>
|
167
|
+
# <script src="/javascripts/something_else.js" type="text/javascript"></script>
|
168
|
+
# <link href="/stylesheets/that.css" media="all" rel="Stylesheet" type="text/css"/>
|
169
|
+
# <link href="/stylesheets/another_one.css" media="all" rel="Stylesheet" type="text/css"/>
|
170
|
+
# </head>
|
171
|
+
# .
|
172
|
+
# .
|
173
|
+
# .
|
174
|
+
# </html>
|
175
|
+
#
|
176
|
+
# See each method's documentation for more information.
|
177
|
+
|
178
|
+
# :section: Bundling Asset Files
|
179
|
+
#
|
180
|
+
# The key to making a fast web application is to reduce both the amount of
|
181
|
+
# data transfered and the number of client-server interactions. While having
|
182
|
+
# many small, module Javascript or stylesheet files aids in the development
|
183
|
+
# process, your web application will benefit from bundling those assets in
|
184
|
+
# the production environment.
|
185
|
+
#
|
186
|
+
# An asset bundle is a set of asset files which are combined into a single
|
187
|
+
# file. This reduces the number of requests required to render a page, and
|
188
|
+
# can reduce the amount of data transfer required if you're using gzip
|
189
|
+
# encoding.
|
190
|
+
#
|
191
|
+
# Asset bundling is always enabled in production mode, and can be optionally
|
192
|
+
# enabled in all environments by setting the <tt>:bundle_assets</tt> value
|
193
|
+
# in <tt>config/merb.yml</tt> to +true+.
|
194
|
+
#
|
195
|
+
# ==== Examples
|
196
|
+
#
|
197
|
+
# In the development environment, this:
|
198
|
+
#
|
199
|
+
# js_include_tag :prototype, :lowpro, :bundle => true
|
200
|
+
#
|
201
|
+
# will produce two <script> elements. In the production mode, however, the
|
202
|
+
# two files will be concatenated in the order given into a single file,
|
203
|
+
# <tt>all.js</tt>, in the <tt>public/javascripts</tt> directory.
|
204
|
+
#
|
205
|
+
# To specify a different bundle name:
|
206
|
+
#
|
207
|
+
# css_include_tag :typography, :whitespace, :bundle => :base
|
208
|
+
# css_include_tag :header, :footer, :bundle => "content"
|
209
|
+
# css_include_tag :lightbox, :images, :bundle => "lb.css"
|
210
|
+
#
|
211
|
+
# (<tt>base.css</tt>, <tt>content.css</tt>, and <tt>lb.css</tt> will all be
|
212
|
+
# created in the <tt>public/stylesheets</tt> directory.)
|
213
|
+
#
|
214
|
+
# == Callbacks
|
215
|
+
#
|
216
|
+
# To use a Javascript or CSS compressor, like JSMin or YUI Compressor:
|
217
|
+
#
|
218
|
+
# Merb::Assets::JavascriptAssetBundler.add_callback do |filename|
|
219
|
+
# system("/usr/local/bin/yui-compress #{filename}")
|
220
|
+
# end
|
221
|
+
#
|
222
|
+
# Merb::Assets::StylesheetAssetBundler.add_callback do |filename|
|
223
|
+
# system("/usr/local/bin/css-min #{filename}")
|
224
|
+
# end
|
225
|
+
#
|
226
|
+
# These blocks will be run after a bundle is created.
|
227
|
+
#
|
228
|
+
# == Bundling Required Assets
|
229
|
+
#
|
230
|
+
# Combining the +require_css+ and +require_js+ helpers with bundling can be
|
231
|
+
# problematic. You may want to separate out the common assets for your
|
232
|
+
# application -- Javascript frameworks, common CSS, etc. -- and bundle those
|
233
|
+
# in a "base" bundle. Then, for each section of your site, bundle the
|
234
|
+
# required assets into a section-specific bundle.
|
235
|
+
#
|
236
|
+
# <b>N.B.: If you bundle an inconsistent set of assets with the same name,
|
237
|
+
# you will have inconsistent results. Be thorough and test often.</b>
|
238
|
+
#
|
239
|
+
# ==== Example
|
240
|
+
#
|
241
|
+
# In your application layout:
|
242
|
+
#
|
243
|
+
# js_include_tag :prototype, :lowpro, :bundle => :base
|
244
|
+
#
|
245
|
+
# In your controller layout:
|
246
|
+
#
|
247
|
+
# require_js :bundle => :posts
|
248
|
+
|
249
|
+
# The require_js method can be used to require any JavaScript file anywhere
|
250
|
+
# in your templates. Regardless of how many times a single script is
|
251
|
+
# included with require_js, Merb will only include it once in the header.
|
252
|
+
#
|
253
|
+
# ==== Parameters
|
254
|
+
# *js<~to_s>:: JavaScript files to include.
|
255
|
+
#
|
256
|
+
# ==== Examples
|
257
|
+
# <% require_js 'jquery' %>
|
258
|
+
# # A subsequent call to include_required_js will render...
|
259
|
+
# # => <script src="/javascripts/jquery.js" type="text/javascript"></script>
|
260
|
+
#
|
261
|
+
# <% require_js 'jquery', 'effects' %>
|
262
|
+
# # A subsequent call to include_required_js will render...
|
263
|
+
# # => <script src="/javascripts/jquery.js" type="text/javascript"></script>
|
264
|
+
# # <script src="/javascripts/effects.js" type="text/javascript"></script>
|
265
|
+
#
|
266
|
+
def require_js(*js)
|
267
|
+
@required_js ||= []
|
268
|
+
@required_js |= js
|
269
|
+
end
|
270
|
+
|
271
|
+
# The require_css method can be used to require any CSS file anywhere in
|
272
|
+
# your templates. Regardless of how many times a single stylesheet is
|
273
|
+
# included with require_css, Merb will only include it once in the header.
|
274
|
+
#
|
275
|
+
# ==== Parameters
|
276
|
+
# *css<~to_s>:: CSS files to include.
|
277
|
+
#
|
278
|
+
# ==== Examples
|
279
|
+
# <% require_css('style') %>
|
280
|
+
# # A subsequent call to include_required_css will render...
|
281
|
+
# # => <link href="/stylesheets/style.css" media="all" rel="Stylesheet" type="text/css"/>
|
282
|
+
#
|
283
|
+
# <% require_css('style', 'ie-specific') %>
|
284
|
+
# # A subsequent call to include_required_css will render...
|
285
|
+
# # => <link href="/stylesheets/style.css" media="all" rel="Stylesheet" type="text/css"/>
|
286
|
+
# # <link href="/stylesheets/ie-specific.css" media="all" rel="Stylesheet" type="text/css"/>
|
287
|
+
#
|
288
|
+
def require_css(*css)
|
289
|
+
@required_css ||= []
|
290
|
+
@required_css |= css
|
291
|
+
end
|
292
|
+
|
293
|
+
# A method used in the layout of an application to create +<script>+ tags
|
294
|
+
# to include JavaScripts required in in templates and subtemplates using
|
295
|
+
# require_js.
|
296
|
+
#
|
297
|
+
# ==== Parameters
|
298
|
+
# options<Hash>:: Options to pass to js_include_tag.
|
299
|
+
#
|
300
|
+
# ==== Returns
|
301
|
+
# String:: The JavaScript tag.
|
302
|
+
#
|
303
|
+
# ==== Examples
|
304
|
+
# # my_action.herb has a call to require_js 'jquery'
|
305
|
+
# # File: layout/application.html.erb
|
306
|
+
# include_required_js
|
307
|
+
# # => <script src="/javascripts/jquery.js" type="text/javascript"></script>
|
308
|
+
#
|
309
|
+
# # my_action.herb has a call to require_js 'jquery', 'effects', 'validation'
|
310
|
+
# # File: layout/application.html.erb
|
311
|
+
# include_required_js
|
312
|
+
# # => <script src="/javascripts/jquery.js" type="text/javascript"></script>
|
313
|
+
# # <script src="/javascripts/effects.js" type="text/javascript"></script>
|
314
|
+
# # <script src="/javascripts/validation.js" type="text/javascript"></script>
|
315
|
+
#
|
316
|
+
def include_required_js(options = {})
|
317
|
+
return '' if @required_js.nil?
|
318
|
+
js_include_tag(*(@required_js + [options]))
|
319
|
+
end
|
320
|
+
|
321
|
+
# A method used in the layout of an application to create +<link>+ tags for
|
322
|
+
# CSS stylesheets required in in templates and subtemplates using
|
323
|
+
# require_css.
|
324
|
+
#
|
325
|
+
# ==== Parameters
|
326
|
+
# options<Hash>:: Options to pass to css_include_tag.
|
327
|
+
#
|
328
|
+
# ==== Returns
|
329
|
+
# String:: The CSS tag.
|
330
|
+
#
|
331
|
+
# ==== Examples
|
332
|
+
# # my_action.herb has a call to require_css 'style'
|
333
|
+
# # File: layout/application.html.erb
|
334
|
+
# include_required_css
|
335
|
+
# # => <link href="/stylesheets/style.css" media="all" rel="Stylesheet" type="text/css"/>
|
336
|
+
#
|
337
|
+
# # my_action.herb has a call to require_js 'style', 'ie-specific'
|
338
|
+
# # File: layout/application.html.erb
|
339
|
+
# include_required_css
|
340
|
+
# # => <link href="/stylesheets/style.css" media="all" rel="Stylesheet" type="text/css"/>
|
341
|
+
# # <link href="/stylesheets/ie-specific.css" media="all" rel="Stylesheet" type="text/css"/>
|
342
|
+
#
|
343
|
+
def include_required_css(options = {})
|
344
|
+
return '' if @required_css.nil?
|
345
|
+
css_include_tag(*(@required_css + [options]))
|
346
|
+
end
|
347
|
+
|
348
|
+
# ==== Parameters
|
349
|
+
# *scripts::
|
350
|
+
# The scripts to include. If the last element is a Hash, it will be used
|
351
|
+
# as options (see below). If ".js" is left out from the script names, it
|
352
|
+
# will be added to them.
|
353
|
+
#
|
354
|
+
# ==== Options
|
355
|
+
# :bundle<~to_s>::
|
356
|
+
# The name of the bundle the scripts should be combined into.
|
357
|
+
#
|
358
|
+
# ==== Returns
|
359
|
+
# String:: The JavaScript include tag(s).
|
360
|
+
#
|
361
|
+
# ==== Examples
|
362
|
+
# js_include_tag 'jquery'
|
363
|
+
# # => <script src="/javascripts/jquery.js" type="text/javascript"></script>
|
364
|
+
#
|
365
|
+
# js_include_tag 'moofx.js', 'upload'
|
366
|
+
# # => <script src="/javascripts/moofx.js" type="text/javascript"></script>
|
367
|
+
# # <script src="/javascripts/upload.js" type="text/javascript"></script>
|
368
|
+
#
|
369
|
+
# js_include_tag :effects
|
370
|
+
# # => <script src="/javascripts/effects.js" type="text/javascript"></script>
|
371
|
+
#
|
372
|
+
# js_include_tag :jquery, :validation
|
373
|
+
# # => <script src="/javascripts/jquery.js" type="text/javascript"></script>
|
374
|
+
# # <script src="/javascripts/validation.js" type="text/javascript"></script>
|
375
|
+
#
|
376
|
+
def js_include_tag(*scripts)
|
377
|
+
options = scripts.last.is_a?(Hash) ? scripts.pop : {}
|
378
|
+
return nil if scripts.empty?
|
379
|
+
|
380
|
+
if (bundle_name = options[:bundle]) && Merb::Assets.bundle? && scripts.size > 1
|
381
|
+
bundler = Merb::Assets::JavascriptAssetBundler.new(bundle_name, *scripts)
|
382
|
+
bundled_asset = bundler.bundle!
|
383
|
+
return js_include_tag(bundled_asset)
|
384
|
+
end
|
385
|
+
|
386
|
+
tags = ""
|
387
|
+
|
388
|
+
for script in scripts
|
389
|
+
attrs = {
|
390
|
+
:src => asset_path(:javascript, script),
|
391
|
+
:type => "text/javascript"
|
392
|
+
}
|
393
|
+
tags << %Q{<script #{attrs.to_xml_attributes}></script>}
|
394
|
+
end
|
395
|
+
|
396
|
+
return tags
|
397
|
+
end
|
398
|
+
|
399
|
+
# ==== Parameters
|
400
|
+
# *stylesheets::
|
401
|
+
# The stylesheets to include. If the last element is a Hash, it will be
|
402
|
+
# used as options (see below). If ".css" is left out from the stylesheet
|
403
|
+
# names, it will be added to them.
|
404
|
+
#
|
405
|
+
# ==== Options
|
406
|
+
# :bundle<~to_s>::
|
407
|
+
# The name of the bundle the stylesheets should be combined into.
|
408
|
+
# :media<~to_s>::
|
409
|
+
# The media attribute for the generated link element. Defaults to :all.
|
410
|
+
#
|
411
|
+
# ==== Returns
|
412
|
+
# String:: The CSS include tag(s).
|
413
|
+
#
|
414
|
+
# ==== Examples
|
415
|
+
# css_include_tag 'style'
|
416
|
+
# # => <link href="/stylesheets/style.css" media="all" rel="Stylesheet" type="text/css" charset="utf-8" />
|
417
|
+
#
|
418
|
+
# css_include_tag 'style.css', 'layout'
|
419
|
+
# # => <link href="/stylesheets/style.css" media="all" rel="Stylesheet" type="text/css" charset="utf-8" />
|
420
|
+
# # <link href="/stylesheets/layout.css" media="all" rel="Stylesheet" type="text/css" charset="utf-8" />
|
421
|
+
#
|
422
|
+
# css_include_tag :menu
|
423
|
+
# # => <link href="/stylesheets/menu.css" media="all" rel="Stylesheet" type="text/css" charset="utf-8" />
|
424
|
+
#
|
425
|
+
# css_include_tag :style, :screen
|
426
|
+
# # => <link href="/stylesheets/style.css" media="all" rel="Stylesheet" type="text/css" charset="utf-8" />
|
427
|
+
# # <link href="/stylesheets/screen.css" media="all" rel="Stylesheet" type="text/css" charset="utf-8" />
|
428
|
+
#
|
429
|
+
# css_include_tag :style, :media => :print
|
430
|
+
# # => <link href="/stylesheets/style.css" media="print" rel="Stylesheet" type="text/css" charset="utf-8" />
|
431
|
+
#
|
432
|
+
# css_include_tag :style, :charset => 'iso-8859-1'
|
433
|
+
# # => <link href="/stylesheets/style.css" media="print" rel="Stylesheet" type="text/css" charset="iso-8859-1" />
|
434
|
+
def css_include_tag(*stylesheets)
|
435
|
+
options = stylesheets.last.is_a?(Hash) ? stylesheets.pop : {}
|
436
|
+
return nil if stylesheets.empty?
|
437
|
+
|
438
|
+
if (bundle_name = options[:bundle]) && Merb::Assets.bundle? && stylesheets.size > 1
|
439
|
+
bundler = Merb::Assets::StylesheetAssetBundler.new(bundle_name, *stylesheets)
|
440
|
+
bundled_asset = bundler.bundle!
|
441
|
+
return css_include_tag(bundled_asset)
|
442
|
+
end
|
443
|
+
|
444
|
+
tags = ""
|
445
|
+
|
446
|
+
for stylesheet in stylesheets
|
447
|
+
attrs = {
|
448
|
+
:href => asset_path(:stylesheet, stylesheet),
|
449
|
+
:type => "text/css",
|
450
|
+
:rel => "Stylesheet",
|
451
|
+
:charset => options[:charset] || 'utf-8',
|
452
|
+
:media => options[:media] || :all
|
453
|
+
}
|
454
|
+
tags << %Q{<link #{attrs.to_xml_attributes} />}
|
455
|
+
end
|
456
|
+
|
457
|
+
return tags
|
458
|
+
end
|
459
|
+
|
460
|
+
# ==== Parameters
|
461
|
+
# *assets::
|
462
|
+
# The assets to include. These should be the full paths to any static served file
|
463
|
+
#
|
464
|
+
# ==== Returns
|
465
|
+
# Array:: Full unique paths to assets OR
|
466
|
+
# String:: if only a single path is requested
|
467
|
+
# ==== Examples
|
468
|
+
# uniq_path("/javascripts/my.js","/javascripts/my.css")
|
469
|
+
# #=> ["http://assets2.my-awesome-domain.com/javascripts/my.js", "http://assets2.my-awesome-domain.com/javascripts/my.css"]
|
470
|
+
#
|
471
|
+
# uniq_path(["/javascripts/my.js","/stylesheets/my.css"])
|
472
|
+
# #=> ["http://assets2.my-awesome-domain.com/javascripts/my.js", "http://assets1.my-awesome-domain.com/stylesheets/my.css"]
|
473
|
+
#
|
474
|
+
# uniq_path(%w(/javascripts/my.js /stylesheets/my.css))
|
475
|
+
# #=> ["http://assets2.my-awesome-domain.com/javascripts/my.js", "http://assets1.my-awesome-domain.com/stylesheets/my.css"]
|
476
|
+
#
|
477
|
+
# uniq_path('/stylesheets/somearbitrary.css')
|
478
|
+
# #=> "http://assets3.my-awesome-domain.com/stylesheets/somearbitrary.css"
|
479
|
+
#
|
480
|
+
# uniq_path('/images/hostsexypicture.jpg')
|
481
|
+
# #=>"http://assets1.my-awesome-domain.com/images/hostsexypicture.jpg"
|
482
|
+
def uniq_path(*assets)
|
483
|
+
paths = []
|
484
|
+
assets.collect.flatten.each do |filename|
|
485
|
+
paths.push(UniqueAssetPath.build(filename))
|
486
|
+
end
|
487
|
+
paths.length > 1 ? paths : paths.first
|
488
|
+
end
|
489
|
+
|
490
|
+
# ==== Parameters
|
491
|
+
# *assets::
|
492
|
+
# Creates unique paths for javascript files (prepends "/javascripts" and appends ".js")
|
493
|
+
#
|
494
|
+
# ==== Returns
|
495
|
+
# Array:: Full unique paths to assets OR
|
496
|
+
# String:: if only a single path is requested
|
497
|
+
# ==== Examples
|
498
|
+
# uniq_js_path("my")
|
499
|
+
# #=> "http://assets2.my-awesome-domain.com/javascripts/my.js"
|
500
|
+
#
|
501
|
+
# uniq_js_path(["admin/secrets","home/signup"])
|
502
|
+
# #=> ["http://assets2.my-awesome-domain.com/javascripts/admin/secrets.js",
|
503
|
+
# "http://assets1.my-awesome-domain.com/javascripts/home/signup.js"]
|
504
|
+
def uniq_js_path(*assets)
|
505
|
+
paths = []
|
506
|
+
assets.collect.flatten.each do |filename|
|
507
|
+
paths.push(UniqueAssetPath.build(asset_path(:javascript,filename,true)))
|
508
|
+
end
|
509
|
+
paths.length > 1 ? paths : paths.first
|
510
|
+
end
|
511
|
+
|
512
|
+
# ==== Parameters
|
513
|
+
# *assets::
|
514
|
+
# Creates unique paths for stylesheet files (prepends "/stylesheets" and appends ".css")
|
515
|
+
#
|
516
|
+
# ==== Returns
|
517
|
+
# Array:: Full unique paths to assets OR
|
518
|
+
# String:: if only a single path is requested
|
519
|
+
# ==== Examples
|
520
|
+
# uniq_css_path("my")
|
521
|
+
# #=> "http://assets2.my-awesome-domain.com/stylesheets/my.css"
|
522
|
+
#
|
523
|
+
# uniq_css_path(["admin/secrets","home/signup"])
|
524
|
+
# #=> ["http://assets2.my-awesome-domain.com/stylesheets/admin/secrets.css",
|
525
|
+
# "http://assets1.my-awesome-domain.com/stylesheets/home/signup.css"]
|
526
|
+
def uniq_css_path(*assets)
|
527
|
+
paths = []
|
528
|
+
assets.collect.flatten.each do |filename|
|
529
|
+
paths.push(UniqueAssetPath.build(asset_path(:stylesheet,filename,true)))
|
530
|
+
end
|
531
|
+
paths.length > 1 ? paths : paths.first
|
532
|
+
end
|
533
|
+
|
534
|
+
# ==== Parameters
|
535
|
+
# *assets::
|
536
|
+
# As js_include_tag but has unique path
|
537
|
+
#
|
538
|
+
# ==== Returns
|
539
|
+
# Array:: Full unique paths to assets OR
|
540
|
+
# String:: if only a single path is requested
|
541
|
+
# ==== Examples
|
542
|
+
# uniq_js_tag("my")
|
543
|
+
# #=> <script type="text/javascript" src="http://assets2.my-awesome-domain.com/javascripts/my.js"></script>
|
544
|
+
def uniq_js_tag(*assets)
|
545
|
+
js_include_tag(uniq_js_path(assets))
|
546
|
+
end
|
547
|
+
|
548
|
+
# ==== Parameters
|
549
|
+
# *assets::
|
550
|
+
# As uniq_css_tag but has unique path
|
551
|
+
#
|
552
|
+
# ==== Returns
|
553
|
+
# Array:: Full unique paths to assets OR
|
554
|
+
# String:: if only a single path is requested
|
555
|
+
# ==== Examples
|
556
|
+
# uniq_css_tag("my")
|
557
|
+
# #=> <link href="http://assets2.my-awesome-domain.com/stylesheets/my.css" type="text/css" />
|
558
|
+
def uniq_css_tag(*assets)
|
559
|
+
css_include_tag(uniq_css_path(assets))
|
560
|
+
end
|
561
|
+
end
|
562
|
+
end
|
metadata
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: merb-assets
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.9.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Ezra Zygmuntowicz
|
8
|
+
autorequire: merb-assets
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2008-03-24 00:00:00 -05:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: merb-core
|
17
|
+
version_requirement:
|
18
|
+
version_requirements: !ruby/object:Gem::Requirement
|
19
|
+
requirements:
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 0.9.2
|
23
|
+
version:
|
24
|
+
description: Merb plugin that provides the helpers for assets and asset bundling
|
25
|
+
email: ez@engineyard.com
|
26
|
+
executables: []
|
27
|
+
|
28
|
+
extensions: []
|
29
|
+
|
30
|
+
extra_rdoc_files:
|
31
|
+
- README
|
32
|
+
- LICENSE
|
33
|
+
- TODO
|
34
|
+
files:
|
35
|
+
- LICENSE
|
36
|
+
- README
|
37
|
+
- Rakefile
|
38
|
+
- TODO
|
39
|
+
- lib/merb-assets
|
40
|
+
- lib/merb-assets/assets.rb
|
41
|
+
- lib/merb-assets/assets_mixin.rb
|
42
|
+
- lib/merb-assets.rb
|
43
|
+
has_rdoc: true
|
44
|
+
homepage: http://merb-plugins.rubyforge.org/merb-assets/
|
45
|
+
post_install_message:
|
46
|
+
rdoc_options: []
|
47
|
+
|
48
|
+
require_paths:
|
49
|
+
- lib
|
50
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: "0"
|
55
|
+
version:
|
56
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: "0"
|
61
|
+
version:
|
62
|
+
requirements: []
|
63
|
+
|
64
|
+
rubyforge_project:
|
65
|
+
rubygems_version: 1.0.1
|
66
|
+
signing_key:
|
67
|
+
specification_version: 2
|
68
|
+
summary: Merb plugin that provides the helpers for assets and asset bundling
|
69
|
+
test_files: []
|
70
|
+
|