public
Rubygem
Description: Rails Plugin - a Ruby way to manage your stylesheets and javascripts. Don't put all your assets in your layout; define what you need where you need them.
Homepage: http://6brand.com
Clone URL: git://github.com/JackDanger/sweet_assets.git
Search Repo:
Complete rewrite.  Now supports multi-media css files.

Extracted from http://adpickles.com/
JackDanger (author)
Mon May 26 22:51:39 -0700 2008
commit  e45ce958b5c4729d3e0e43bc8a3e948fe0338e15
tree    5796330140f24e26d889d462268f3453e01473e7
parent  daa4c3bde17622d6c6ae26b9f88ac312355a54de
...
1
2
3
4
 
 
 
 
 
 
 
 
5
...
1
2
 
 
3
4
5
6
7
8
9
10
11
0
@@ -1,5 +1,11 @@
0
 require 'sweet_assets'
0
 
0
-ActionController::Base.send :include, SweetAssets
0
-ActionView::Base.send :include, SweetAssets::AssignmentMethods
0
+
0
+ActionController::Base.class_eval do
0
+ include SweetAssets::ActionController
0
+end
0
+
0
+ActionView::Base.class_eval do
0
+ include SweetAssets::ActionView::Helpers
0
+end
0
 
...
1
2
3
 
4
5
6
7
8
9
10
 
 
 
 
 
11
12
 
 
 
 
 
 
13
14
15
16
 
 
17
18
19
20
21
 
22
23
24
25
 
 
 
 
 
 
26
27
28
29
30
 
 
 
 
 
31
32
33
34
35
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
36
37
38
39
40
41
42
 
 
 
 
 
43
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
44
45
46
47
48
49
50
51
52
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
53
54
55
56
57
58
59
60
61
 
 
 
 
 
 
 
 
62
63
64
 
 
 
65
66
67
 
 
 
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
 
 
99
 
100
101
102
103
104
 
 
 
 
105
106
107
108
109
110
111
112
 
 
 
 
113
114
115
116
117
118
 
 
119
120
121
122
123
124
125
126
127
 
 
128
129
130
131
132
133
134
135
136
137
 
 
 
 
 
138
139
140
141
142
143
144
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
145
146
147
148
149
150
 
 
 
 
 
 
 
 
 
 
 
151
152
 
 
 
 
 
 
 
 
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
 
 
169
170
171
172
173
 
...
1
2
3
4
5
 
 
 
 
 
 
6
7
8
9
10
11
 
12
13
14
15
16
17
18
 
 
 
19
20
21
 
 
 
 
22
23
24
 
25
26
27
28
29
30
31
32
 
 
 
 
33
34
35
36
37
38
39
 
 
 
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
 
 
 
 
 
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
 
 
 
 
 
 
 
 
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
 
 
126
 
 
 
127
128
129
130
131
132
133
134
135
 
 
136
137
138
139
 
 
140
141
142
143
144
145
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
146
 
147
 
 
 
 
 
 
 
 
148
149
150
151
152
 
 
 
 
153
154
155
156
157
 
 
 
 
 
 
 
158
159
160
161
162
163
 
 
 
 
164
165
166
 
 
 
 
 
 
 
 
167
168
169
 
 
 
 
 
 
 
 
 
170
171
172
173
174
175
 
 
 
 
 
 
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
 
 
 
 
 
195
196
197
198
199
200
201
202
203
204
205
206
 
207
208
209
210
211
212
213
214
215
216
217
218
 
 
 
 
 
 
 
 
 
 
 
 
219
220
221
222
223
 
224
225
0
@@ -1,172 +1,224 @@
0
 require 'cgi'
0
 require 'action_view/helpers/url_helper'
0
 require 'action_view/helpers/tag_helper'
0
+require 'digest/md5'
0
 
0
-module SweetAssets
0
- RAILS_DEFAULT_JAVASCRIPTS = [:prototype, :effects, :dragdrop, :controls]
0
-
0
- class << self
0
-
0
- attr_accessor :use_rails_default_javascripts
0
+# USAGE:
0
+# style_like :dolphins # assumes :media => 'all'
0
+# style_like :home, :media => 'print'
0
+# style_like :users, :media => ['print', 'screen']
0
+# script_like :boats
0
 
0
- def included(base)
0
+module SweetAssets
0
+ DEFAULT_JAVASCRIPTS = ['prototype', 'effects', 'dragdrop', 'controls']
0
+ SCRIPT_PLACEHOLDER = '<!--SWEET_JAVASCRIPTS-->'
0
+ STYLE_PLACEHOLDER = '<!--SWEET_STYLESHEETS-->'
0
+ module ActionController
0
+ def self.included(base)
0
       base.class_eval do
0
- include AssignmentMethods
0
- include ClassMethods
0
- extend SweetAssetsShortcuts
0
+ extend ClassMethods
0
+ include InstanceMethods
0
         include AppendAssetsAfterRescue
0
- before_filter :initialize_assets_accessor
0
- before_filter :apply_default_styles
0
- before_filter :apply_default_scripts
0
- after_filter :apply_sweet_assets
0
+ after_filter :apply_sweet_assets
0
       end
0
     end
0
- end
0
 
0
+ module ClassMethods
0
+ def style_like(*assets)
0
+ before_filter do |controller|
0
+ controller.send :style_like, *assets
0
+ end
0
+ end
0
 
0
- module SweetAssetsShortcuts
0
- def style_like(*assets)
0
- options = assets.extract_options!
0
- before_filter Proc.new {|controller| controller.style_like *assets }, options
0
+ def script_like(*assets)
0
+ before_filter do |controller|
0
+ controller.send :script_like, *assets
0
+ end
0
+ end
0
     end
0
 
0
- def script_like(*assets)
0
- options = assets.extract_options!
0
- before_filter Proc.new {|controller| controller.script_like *assets }, options
0
+ module InstanceMethods
0
+ protected
0
+ def style_like(*assets)
0
+ sweet_assets.style_like(*assets)
0
+ end
0
+
0
+ def script_like(*assets)
0
+ sweet_assets.script_like(*assets)
0
+ end
0
+
0
+ def sweet_assets
0
+ @sweet_assets ||= SweetAssets::Request.new(self)
0
+ end
0
+
0
+ def apply_sweet_assets
0
+ if response.body.respond_to?(:gsub!)
0
+ response.body.gsub! SweetAssets::STYLE_PLACEHOLDER, sweet_assets.tags.stylesheets
0
+ response.body.gsub! SweetAssets::SCRIPT_PLACEHOLDER, sweet_assets.tags.javascripts
0
+ end
0
+ end
0
     end
0
   end
0
-
0
- module AssignmentMethods
0
- def style_like(*styles)
0
- styles.each do |style|
0
- add_sweet_asset(style.to_s, :stylesheets)
0
+
0
+ module ActionView
0
+ module Helpers
0
+ def style_like(*assets)
0
+ sweet_assets.style_like(*assets)
0
       end
0
+
0
+ def script_like(*assets)
0
+ sweet_assets.script_like(*assets)
0
+ end
0
+
0
+ def sweet_stylesheets
0
+ SweetAssets::STYLE_PLACEHOLDER
0
+ end
0
+
0
+ def sweet_javascripts
0
+ SweetAssets::SCRIPT_PLACEHOLDER
0
+ end
0
+
0
+ protected
0
+
0
+ def sweet_assets
0
+ controller.send :sweet_assets
0
+ end
0
     end
0
-
0
- def script_like(*scripts)
0
- scripts.each do |script|
0
- script = script.to_s
0
- if 'defaults' == script
0
- SweetAssets.use_rails_default_javascripts = true
0
- else
0
- add_sweet_asset(script, :javascripts)
0
+ end
0
+
0
+ class Request
0
+ def initialize(controller)
0
+ @stylesheets = Array.new
0
+ @javascripts = Array.new
0
+ @controller = controller
0
+
0
+ # use the assets named 'application'
0
+ style_like :application
0
+ script_like :application
0
+
0
+ # use the assets named after the controller at higher priority
0
+ style_like "#{@controller.class.controller_name}!"
0
+ script_like "#{@controller.class.controller_name}!"
0
+ end
0
+
0
+ def style_like(*assets)
0
+ options = HashWithIndifferentAccess.new(assets.extract_options!)
0
+ media = [options[:media]].flatten.compact
0
+ media = ['all'] if media.blank?
0
+ media.each do |medium|
0
+ medium = medium.to_s
0
+ assets.each do |asset|
0
+ asset = asset.to_s
0
+ if asset.ends_with?('!')
0
+ asset.gsub!(/!$/, '')
0
+ # remove a lower-priority entry if it exists for this medium
0
+ @stylesheets.delete({:file => asset, :medium => medium, :priority => 'low'})
0
+ @stylesheets << {:file => asset, :medium => medium, :priority => 'high'}
0
+ else
0
+ # don't add this entry if it's already set to high-priority
0
+ unless @stylesheets.include?({:file => asset, :medium => medium, :priority => 'high'})
0
+ @stylesheets << {:file => asset, :medium => medium, :priority => 'low'}
0
+ end
0
+ end
0
         end
0
       end
0
     end
0
-
0
- protected
0
 
0
- def add_sweet_asset(asset, collection)
0
- collection = sweet_assets[collection]
0
- if asset.ends_with?('!')
0
+ def script_like(*assets)
0
+ assets.each do |asset|
0
+ asset = asset.to_s
0
+ if 'defaults' == asset
0
+ DEFAULT_JAVASCRIPTS.each do |default|
0
+ @javascripts << {:file => default, :priority => 'first' }
0
+ end
0
+ elsif asset.ends_with?('!')
0
           asset.gsub!(/!$/, '')
0
- collection[:top].delete(asset)
0
- collection[:bottom] << asset
0
+ # remove a lower-priority entry if it exists
0
+ @javascripts.delete({:file => asset, :priority => 'low'})
0
+ @javascripts << {:file => asset, :priority => 'high'}
0
         else
0
- unless collection[:bottom].include?(asset)
0
- collection[:top] << asset
0
+ # don't add this entry if it's already set to high-priority
0
+ unless @javascripts.include?({:file => asset, :priority => 'high'})
0
+ @javascripts << {:file => asset, :priority => 'low'}
0
           end
0
         end
0
       end
0
-
0
- def sweet_assets
0
- self.is_a?(ActionView::Base) ?
0
- controller.instance_variable_get("@sweet_assets") :
0
- @sweet_assets
0
- end
0
- end
0
-
0
- module ClassMethods
0
-
0
- def method_missing_with_sweet_assets(method_name, *args, &block)
0
-
0
- if match = method_name.to_s.match(/^(style_like|script_like)_(\w+!?)$/)
0
- send match[1], match[2]
0
- else
0
- method_missing_without_sweet_assets(method_name, *args, &block)
0
- end
0
     end
0
- alias_method_chain :method_missing, :sweet_assets
0
     
0
- def initialize_assets_accessor
0
- @sweet_assets = { :javascripts => {:top => [], :bottom => []},
0
- :stylesheets => {:top => [], :bottom => []} }
0
- end
0
-
0
- def apply_default_styles
0
- style_like :application
0
- style_like "#{controller_name}!"
0
+ def tags
0
+ @tag_generator ||= TagGenerator.new(@stylesheets, @javascripts, @controller)
0
     end
0
+ end
0
 
0
- def apply_default_scripts
0
- # we don't apply application.js by default because Rails already knows how to do that.
0
- script_like "#{controller_name}!"
0
- end
0
+ class TagGenerator
0
+
0
+ include ::ActionView::Helpers::TagHelper
0
+ include ::ActionView::Helpers::AssetTagHelper
0
 
0
- def apply_sweet_assets
0
- return true unless @sweet_assets.any? {|asset_type, assets| assets.any? {|placement, files| !files.blank? } }
0
- generator = SweetAssetsGenerator.new(@sweet_assets, self)
0
- response.body.gsub! '<head>', "<head>\n#{generator.tags(:top)}\n" if response.body.respond_to?(:gsub!)
0
- response.body.gsub! '</head>', "\n#{generator.tags(:bottom)}\n</head>" if response.body.respond_to?(:gsub!)
0
- SweetAssets.use_rails_default_javascripts = false
0
- @sweet_assets = {}
0
+ def initialize(stylesheets, javascripts, controller)
0
+ @stylesheets = stylesheets
0
+ @javascripts = javascripts
0
+ @controller = controller
0
     end
0
     
0
- class SweetAssetsGenerator
0
-
0
- include ActionView::Helpers::TagHelper
0
- include ActionView::Helpers::AssetTagHelper
0
+ def stylesheets
0
+ media = @stylesheets.map {|asset| asset[:medium] }.uniq
0
 
0
- def initialize(assets, controller)
0
- @assets = assets
0
- @controller = controller
0
- end
0
-
0
- def tags(placement)
0
- javascript_tags(placement) + "\n" + stylesheet_tags(placement)
0
- end
0
+ media.map do |medium|
0
+ files_in_order = ['low', 'high'].map do |priority|
0
 
0
- def stylesheet_tags(placement)
0
- files = @assets[:stylesheets][placement].dup
0
- files.uniq!
0
- files.map! {|file| file =~ /\.css$/ ? file : "#{file}.css" }
0
- files = files.select {|file| File.exists?("#{STYLESHEETS_DIR}/#{file}") } unless RAILS_ENV.eql?('test')
0
- return '' if files.blank?
0
- files << {:cache => "sweet_stylesheets_#{files.join(',')}" } if ActionController::Base.perform_caching
0
- stylesheet_link_tag *files
0
- end
0
+ files = @stylesheets.select do |asset|
0
+ asset[:medium] == medium && asset[:priority] == priority
0
+ end
0
+ files.map! {|asset| asset[:file] }
0
+ files.map! {|file| file =~ /\.css$/ ? file : "#{file}.css" }
0
 
0
- def javascript_tags(placement)
0
- files = @assets[:javascripts][placement].dup
0
- if SweetAssets.use_rails_default_javascripts
0
- files = SweetAssets::PRIMARY_JAVASCRIPTS + files
0
- end
0
- files.uniq!
0
+ # check that the files exist
0
+ unless RAILS_ENV.eql?('test')
0
+ files = files.select {|file| File.exists?("#{STYLESHEETS_DIR}/#{file}") }
0
+ end
0
+
0
+ files
0
+ end.flatten.uniq.compact
0
+
0
+ stylesheet_link_tag(*(files_in_order << {:media => medium, :cache => cached_file_name(files_in_order)}))
0
+
0
+ end.join("\n")
0
+ end
0
+
0
+ def javascripts
0
+ files_in_order = ['first', 'low', 'high'].map do |priority|
0
+
0
+ files = @javascripts.select {|asset| asset[:priority] == priority }
0
+ files.map! {|asset| asset[:file] }
0
         files.map! {|file| file =~ /\.js$/ ? file : "#{file}.js" }
0
- files = files.select {|file| File.exists?("#{JAVASCRIPTS_DIR}/#{file}") } unless RAILS_ENV.eql?('test')
0
- return '' if files.blank?
0
- files << {:cache => "sweet_javascripts_#{files.join(',')}" } if ActionController::Base.perform_caching
0
- javascript_include_tag *files
0
- end
0
+
0
+ # check that the files exist
0
+ unless RAILS_ENV.eql?('test')
0
+ files = files.select {|file| File.exists?("#{JAVASCRIPTS_DIR}/#{file}") }
0
+ end
0
+ files
0
+ end.flatten.uniq.compact
0
+
0
+ files_in_order << {:cache => cached_file_name(files_in_order)}
0
+
0
+ javascript_include_tag *files_in_order
0
     end
0
- end
0
+
0
+ protected
0
+
0
+ def cached_file_name(filenames)
0
+ "sweet_assets_#{Digest::MD5.hexdigest(filenames.join('_'))}"
0
+ end
0
+end
0
+
0
 
0
   # we're going to wrap our rescue_action around the top-level rescue_action method chain
0
   # this ensures that we can apply the stylesheets even if the after filter was aborted due to an exception
0
   module AppendAssetsAfterRescue
0
- def self.included(base)
0
- base.class_eval do
0
- def initialize_with_append_sweet_assets_rescue_action(*args)
0
- initialize_without_append_sweet_assets_rescue_action(*args)
0
- self.class.send :alias_method_chain, :rescue_action, :append_sweet_assets unless respond_to?(:rescue_action_without_append_sweet_assets)
0
- end
0
- alias_method_chain :initialize, :append_sweet_assets_rescue_action
0
- end
0
- end
0
-
0
- def rescue_action_with_append_sweet_assets(*args)
0
- rescue_action_without_append_sweet_assets(*args)
0
+ def rescue_action(*args)
0
+ super
0
       apply_sweet_assets
0
     end
0
   end
0
-end
0
\ No newline at end of file
0
+end
...
1
2
 
3
 
4
5
6
 
 
 
7
 
8
9
10
11
12
13
14
15
16
17
18
19
 
 
 
 
 
 
20
21
22
...
55
56
57
58
 
 
 
 
 
59
60
61
...
71
72
73
74
75
76
77
78
79
80
81
82
83
 
84
85
86
...
96
97
98
99
100
101
102
103
104
105
106
107
108
 
109
110
111
...
1
 
2
3
4
5
 
 
6
7
8
9
10
11
12
13
 
 
 
 
 
 
 
 
 
14
15
16
17
18
19
20
21
22
...
55
56
57
 
58
59
60
61
62
63
64
65
...
75
76
77
 
 
 
 
 
 
 
 
 
 
78
79
80
81
...
91
92
93
 
 
 
 
 
 
 
 
 
 
94
95
96
97
0
@@ -1,22 +1,22 @@
0
 
0
-RAILS_ENV='test'
0
+RAILS_ENV = 'test'
0
 
0
+require File.dirname(__FILE__) + '/../../../../config/environment'
0
 require 'test/unit'
0
-require File.expand_path(File.dirname(__FILE__) + '/../../../../config/environment')
0
-require File.expand_path(File.dirname(__FILE__) + '/../../../../test/test_helper')
0
+require 'rubygems'
0
+require 'action_controller/test_process'
0
+require File.dirname(__FILE__) + '/../init'
0
 
0
+ActionController::Base.view_paths = [File.dirname(__FILE__) + '/views/']
0
 
0
 # Re-raise errors caught by the controller.
0
 class WebController < ActionController::Base
0
- before_filter :style_like_home
0
- before_filter :style_like_users!
0
- before_filter :style_like_extra
0
- before_filter :script_like_home
0
- before_filter :script_like_users!
0
- before_filter :script_like_extra
0
- def index
0
- render :text => '<html><head><title>SweetAssets</title></head><body></body></html>'
0
- end
0
+ style_like :home
0
+ style_like :users!
0
+ style_like :extra
0
+ script_like :home
0
+ script_like :users!
0
+ script_like :extra
0
 end
0
 
0
 class ShortcutController < ActionController::Base
0
@@ -55,7 +55,11 @@ class SweetAssetsTest < Test::Unit::TestCase
0
   def test_bottom_stylesheets_should_appear_last
0
     get :index
0
     assert_response :success
0
- assert @response.body =~ /<link href="\/stylesheets\/users.css(\?\d*)?" media="screen" rel="stylesheet" type="text\/css" \/>\n*?<\/head>/
0
+ location_of_extra_css = @response.body =~ /<link href="\/stylesheets\/extra.css/
0
+ location_of_home_css = @response.body =~ /<link href="\/stylesheets\/home.css/
0
+ location_of_users_css = @response.body =~ /<link href="\/stylesheets\/users.css/
0
+ assert location_of_home_css < location_of_extra_css
0
+ assert location_of_extra_css < location_of_users_css
0
   end
0
 
0
   def test_caching_stylesheets
0
@@ -71,16 +75,7 @@ class SweetAssetsTest < Test::Unit::TestCase
0
     assert_no_tag :link, :attributes => {:href => /stylesheets\/home.css/, :rel => 'stylesheet'}
0
     assert_no_tag :link, :attributes => {:href => /stylesheets\/extra.css/, :rel => 'stylesheet'}
0
     assert_no_tag :link, :attributes => {:href => /stylesheets\/users.css/, :rel => 'stylesheet'}
0
- assert_tag :link, :attributes => {:href => /sweet_stylesheets_application.css,home.css,extra.css(\?\d*)?/, :rel => 'stylesheet'}
0
- assert_tag :link, :attributes => {:href => /sweet_stylesheets_web.css,users.css(\?\d*)?/, :rel => 'stylesheet'}
0
- # and check the placement
0
- location_of_head = @response.body =~ /<head>/
0
- location_of_title = @response.body =~ /<title>/
0
- location_of_home_extra_css = @response.body =~ /<link href="\/stylesheets\/sweet_stylesheets_application.css,home.css,extra.css/
0
- location_of_web_users_css = @response.body =~ /<link href="\/stylesheets\/sweet_stylesheets_web.css,users.css/
0
- assert location_of_head < location_of_home_extra_css
0
- assert location_of_home_extra_css < location_of_title
0
- assert location_of_title < location_of_web_users_css
0
+ assert_tag :link, :attributes => {:href => /sweet_assets_([\w\d]{32}).css/, :rel => 'stylesheet'}
0
     ActionController::Base.perform_caching = false
0
   end
0
 
0
@@ -96,16 +91,7 @@ class SweetAssetsTest < Test::Unit::TestCase
0
     assert_no_tag :script, :attributes => {:src => /javascripts\/home.js/}
0
     assert_no_tag :script, :attributes => {:src => /javascripts\/extra.js/}
0
     assert_no_tag :script, :attributes => {:src => /javascripts\/users.js/}
0
- assert_tag :script, :attributes => {:src => /sweet_javascripts_home.js,extra.js(\?\d*)?/}
0
- assert_tag :script, :attributes => {:src => /sweet_javascripts_web.js,users.js(\?\d*)?/}
0
- # and check the placement
0
- location_of_head = @response.body =~ /<head>/
0
- location_of_title = @response.body =~ /<title>/
0
- location_of_home_extra_js = @response.body =~ /<script src="\/javascripts\/sweet_javascripts_home.js,extra.js/
0
- location_of_web_users_js = @response.body =~ /<script src="\/javascripts\/sweet_javascripts_web.js,users.js/
0
- assert location_of_head < location_of_home_extra_js
0
- assert location_of_home_extra_js < location_of_title
0
- assert location_of_title < location_of_web_users_js
0
+ assert_tag :script, :attributes => {:src => /sweet_assets_([\w\d]{32}).js/}
0
     ActionController::Base.perform_caching = false
0
   end
0
   

Comments

    No one has commented yet.