thorero-assets 0.9.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,635 @@
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
+
11
+ # ==== Parameters
12
+ # none
13
+ #
14
+ # ==== Returns
15
+ # html<String>
16
+ #
17
+ # ==== Examples
18
+ # We want all possible matches in the FileSys up to the action name
19
+ # Given: controller_name = "namespace/controller"
20
+ # action_name = "action"
21
+ # If all files are present should generate link/script tags for:
22
+ # namespace.(css|js)
23
+ # namespace/controller.(css|js)
24
+ # namespace/controller/action.(css|js)
25
+ #
26
+ def auto_link
27
+ html = ""
28
+ prefix = ""
29
+ (controller_name / action_name).split("/").each do |path|
30
+ path = prefix + path
31
+
32
+ css_path = path + ".css"
33
+ if File.exists? Merb.root / "public" / "stylesheets" / css_path
34
+ html << %{<link rel="stylesheet" type="text/css" href="/stylesheets/#{css_path}" /> }
35
+ end
36
+
37
+ js_path = path + ".js"
38
+ if File.exists? Merb.root / "public" / "javascripts" / js_path
39
+ html << %{<script type="text/javascript" language="javascript" src="/javascripts/#{js_path}"></script>}
40
+ end
41
+
42
+ #Update the prefix for the next iteration
43
+ prefix += path / ""
44
+ end
45
+
46
+ #Return the generated HTML
47
+ html
48
+ end
49
+
50
+
51
+ # ==== Parameters
52
+ # name<~to_s>:: The text of the link.
53
+ # url<~to_s>:: The URL to link to. Defaults to an empty string.
54
+ # opts<Hash>:: Additional HTML options for the link.
55
+ #
56
+ # ==== Examples
57
+ # link_to("The Merb home page", "http://www.merbivore.com/")
58
+ # # => <a href="http://www.merbivore.com/">The Merb home page</a>
59
+ #
60
+ # link_to("The Ruby home page", "http://www.ruby-lang.org", {'class' => 'special', 'target' => 'blank'})
61
+ # # => <a href="http://www.ruby-lang.org" class="special" target="blank">The Ruby home page</a>
62
+ #
63
+ # link_to p.title, "/blog/show/#{p.id}"
64
+ # # => <a href="/blog/show/13">The Entry Title</a>
65
+ #
66
+ def link_to(name, url='', opts={})
67
+ opts[:href] ||= url
68
+ %{<a #{ opts.to_xml_attributes }>#{name}</a>}
69
+ end
70
+
71
+ # ==== Parameters
72
+ # img<~to_s>:: The image path.
73
+ # opts<Hash>:: Additional options for the image tag (see below).
74
+ #
75
+ # ==== Options (opts)
76
+ # :path<String>::
77
+ # Sets the path prefix for the image. Defaults to "/images/" or whatever
78
+ # is specified in Merb::Config. This is ignored if img is an absolute
79
+ # path or full URL.
80
+ #
81
+ # All other options set HTML attributes on the tag.
82
+ #
83
+ # ==== Examples
84
+ # image_tag('foo.gif')
85
+ # # => <img src='/images/foo.gif' />
86
+ #
87
+ # image_tag('foo.gif', :class => 'bar')
88
+ # # => <img src='/images/foo.gif' class='bar' />
89
+ #
90
+ # image_tag('foo.gif', :path => '/files/')
91
+ # # => <img src='/files/foo.gif' />
92
+ #
93
+ # image_tag('http://test.com/foo.gif')
94
+ # # => <img src="http://test.com/foo.gif">
95
+ #
96
+ # image_tag('charts', :path => '/dynamic/')
97
+ # or
98
+ # image_tag('/dynamic/charts')
99
+ # # => <img src="/dynamic/charts">
100
+ def image_tag(img, opts={})
101
+ if img[0].chr == '/'
102
+ opts[:src] = img
103
+ else
104
+ opts[:path] ||=
105
+ if img =~ %r{^https?://}
106
+ ''
107
+ else
108
+ if Merb::Config[:path_prefix]
109
+ Merb::Config[:path_prefix] + '/images/'
110
+ else
111
+ '/images/'
112
+ end
113
+ end
114
+ opts[:src] ||= opts.delete(:path) + img
115
+ end
116
+ %{<img #{ opts.to_xml_attributes } />}
117
+ end
118
+
119
+ # :section: JavaScript related functions
120
+ #
121
+
122
+ # ==== Parameters
123
+ # javascript<String>:: Text to escape for use in JavaScript.
124
+ #
125
+ # ==== Examples
126
+ # escape_js("'Lorem ipsum!' -- Some guy")
127
+ # # => "\\'Lorem ipsum!\\' -- Some guy"
128
+ #
129
+ # escape_js("Please keep text\nlines as skinny\nas possible.")
130
+ # # => "Please keep text\\nlines as skinny\\nas possible."
131
+ def escape_js(javascript)
132
+ (javascript || '').gsub('\\','\0\0').gsub(/\r\n|\n|\r/, "\\n").gsub(/["']/) { |m| "\\#{m}" }
133
+ end
134
+
135
+ # ==== Parameters
136
+ # data<Object>::
137
+ # Object to translate into JSON. If the object does not respond to
138
+ # :to_json, then data.inspect.to_json is returned instead.
139
+ #
140
+ # ==== Examples
141
+ # js({'user' => 'Lewis', 'page' => 'home'})
142
+ # # => "{\"user\":\"Lewis\",\"page\":\"home\"}"
143
+ #
144
+ # js([ 1, 2, {"a"=>3.141}, false, true, nil, 4..10 ])
145
+ # # => "[1,2,{\"a\":3.141},false,true,null,\"4..10\"]"
146
+ def js(data)
147
+ if data.respond_to? :to_json
148
+ data.to_json
149
+ else
150
+ data.inspect.to_json
151
+ end
152
+ end
153
+
154
+ # :section: External JavaScript and Stylesheets
155
+ #
156
+ # You can use require_js(:prototype) or require_css(:shinystyles)
157
+ # from any view or layout, and the scripts will only be included once
158
+ # in the head of the final page. To get this effect, the head of your
159
+ # layout you will need to include a call to include_required_js and
160
+ # include_required_css.
161
+ #
162
+ # ==== Examples
163
+ # # File: app/views/layouts/application.html.erb
164
+ #
165
+ # <html>
166
+ # <head>
167
+ # <%= include_required_js %>
168
+ # <%= include_required_css %>
169
+ # </head>
170
+ # <body>
171
+ # <%= catch_content :layout %>
172
+ # </body>
173
+ # </html>
174
+ #
175
+ # # File: app/views/whatever/_part1.herb
176
+ #
177
+ # <% require_js 'this' -%>
178
+ # <% require_css 'that', 'another_one' -%>
179
+ #
180
+ # # File: app/views/whatever/_part2.herb
181
+ #
182
+ # <% require_js 'this', 'something_else' -%>
183
+ # <% require_css 'that' -%>
184
+ #
185
+ # # File: app/views/whatever/index.herb
186
+ #
187
+ # <%= partial(:part1) %>
188
+ # <%= partial(:part2) %>
189
+ #
190
+ # # Will generate the following in the final page...
191
+ # <html>
192
+ # <head>
193
+ # <script src="/javascripts/this.js" type="text/javascript"></script>
194
+ # <script src="/javascripts/something_else.js" type="text/javascript"></script>
195
+ # <link href="/stylesheets/that.css" media="all" rel="Stylesheet" type="text/css"/>
196
+ # <link href="/stylesheets/another_one.css" media="all" rel="Stylesheet" type="text/css"/>
197
+ # </head>
198
+ # .
199
+ # .
200
+ # .
201
+ # </html>
202
+ #
203
+ # See each method's documentation for more information.
204
+
205
+ # :section: Bundling Asset Files
206
+ #
207
+ # The key to making a fast web application is to reduce both the amount of
208
+ # data transfered and the number of client-server interactions. While having
209
+ # many small, module Javascript or stylesheet files aids in the development
210
+ # process, your web application will benefit from bundling those assets in
211
+ # the production environment.
212
+ #
213
+ # An asset bundle is a set of asset files which are combined into a single
214
+ # file. This reduces the number of requests required to render a page, and
215
+ # can reduce the amount of data transfer required if you're using gzip
216
+ # encoding.
217
+ #
218
+ # Asset bundling is always enabled in production mode, and can be optionally
219
+ # enabled in all environments by setting the <tt>:bundle_assets</tt> value
220
+ # in <tt>config/merb.yml</tt> to +true+.
221
+ #
222
+ # ==== Examples
223
+ #
224
+ # In the development environment, this:
225
+ #
226
+ # js_include_tag :prototype, :lowpro, :bundle => true
227
+ #
228
+ # will produce two <script> elements. In the production mode, however, the
229
+ # two files will be concatenated in the order given into a single file,
230
+ # <tt>all.js</tt>, in the <tt>public/javascripts</tt> directory.
231
+ #
232
+ # To specify a different bundle name:
233
+ #
234
+ # css_include_tag :typography, :whitespace, :bundle => :base
235
+ # css_include_tag :header, :footer, :bundle => "content"
236
+ # css_include_tag :lightbox, :images, :bundle => "lb.css"
237
+ #
238
+ # (<tt>base.css</tt>, <tt>content.css</tt>, and <tt>lb.css</tt> will all be
239
+ # created in the <tt>public/stylesheets</tt> directory.)
240
+ #
241
+ # == Callbacks
242
+ #
243
+ # To use a Javascript or CSS compressor, like JSMin or YUI Compressor:
244
+ #
245
+ # Merb::Assets::JavascriptAssetBundler.add_callback do |filename|
246
+ # system("/usr/local/bin/yui-compress #{filename}")
247
+ # end
248
+ #
249
+ # Merb::Assets::StylesheetAssetBundler.add_callback do |filename|
250
+ # system("/usr/local/bin/css-min #{filename}")
251
+ # end
252
+ #
253
+ # These blocks will be run after a bundle is created.
254
+ #
255
+ # == Bundling Required Assets
256
+ #
257
+ # Combining the +require_css+ and +require_js+ helpers with bundling can be
258
+ # problematic. You may want to separate out the common assets for your
259
+ # application -- Javascript frameworks, common CSS, etc. -- and bundle those
260
+ # in a "base" bundle. Then, for each section of your site, bundle the
261
+ # required assets into a section-specific bundle.
262
+ #
263
+ # <b>N.B.: If you bundle an inconsistent set of assets with the same name,
264
+ # you will have inconsistent results. Be thorough and test often.</b>
265
+ #
266
+ # ==== Example
267
+ #
268
+ # In your application layout:
269
+ #
270
+ # js_include_tag :prototype, :lowpro, :bundle => :base
271
+ #
272
+ # In your controller layout:
273
+ #
274
+ # require_js :bundle => :posts
275
+
276
+ # The require_js method can be used to require any JavaScript file anywhere
277
+ # in your templates. Regardless of how many times a single script is
278
+ # included with require_js, Merb will only include it once in the header.
279
+ #
280
+ # ==== Parameters
281
+ # *js<~to_s>:: JavaScript files to include.
282
+ #
283
+ # ==== Examples
284
+ # <% require_js 'jquery' %>
285
+ # # A subsequent call to include_required_js will render...
286
+ # # => <script src="/javascripts/jquery.js" type="text/javascript"></script>
287
+ #
288
+ # <% require_js 'jquery', 'effects' %>
289
+ # # A subsequent call to include_required_js will render...
290
+ # # => <script src="/javascripts/jquery.js" type="text/javascript"></script>
291
+ # # <script src="/javascripts/effects.js" type="text/javascript"></script>
292
+ #
293
+ def require_js(*js)
294
+ @required_js ||= []
295
+ @required_js << js
296
+ end
297
+
298
+ # All javascript files to include, without duplicates.
299
+ #
300
+ # ==== Parameters
301
+ # options<Hash>:: Default options to pass to js_include_tag.
302
+ def required_js(options = {})
303
+ extract_required_files(@required_js, options)
304
+ end
305
+
306
+ # The require_css method can be used to require any CSS file anywhere in
307
+ # your templates. Regardless of how many times a single stylesheet is
308
+ # included with require_css, Merb will only include it once in the header.
309
+ #
310
+ # ==== Parameters
311
+ # *css<~to_s>:: CSS files to include.
312
+ #
313
+ # ==== Examples
314
+ # <% require_css('style') %>
315
+ # # A subsequent call to include_required_css will render...
316
+ # # => <link href="/stylesheets/style.css" media="all" rel="Stylesheet" type="text/css"/>
317
+ #
318
+ # <% require_css('style', 'ie-specific') %>
319
+ # # A subsequent call to include_required_css will render...
320
+ # # => <link href="/stylesheets/style.css" media="all" rel="Stylesheet" type="text/css"/>
321
+ # # <link href="/stylesheets/ie-specific.css" media="all" rel="Stylesheet" type="text/css"/>
322
+ #
323
+ def require_css(*css)
324
+ @required_css ||= []
325
+ @required_css << css
326
+ end
327
+
328
+ # All css files to include, without duplicates.
329
+ #
330
+ # ==== Parameters
331
+ # options<Hash>:: Default options to pass to css_include_tag.
332
+ def required_css(options = {})
333
+ extract_required_files(@required_css, options)
334
+ end
335
+
336
+ # A method used in the layout of an application to create +<script>+ tags
337
+ # to include JavaScripts required in in templates and subtemplates using
338
+ # require_js.
339
+ #
340
+ # ==== Parameters
341
+ # options<Hash>:: Options to pass to js_include_tag.
342
+ #
343
+ # ==== Options
344
+ # :bundle<~to_s>::
345
+ # The name of the bundle the scripts should be combined into.
346
+ #
347
+ # ==== Returns
348
+ # String:: The JavaScript tag.
349
+ #
350
+ # ==== Examples
351
+ # # my_action.herb has a call to require_js 'jquery'
352
+ # # File: layout/application.html.erb
353
+ # include_required_js
354
+ # # => <script src="/javascripts/jquery.js" type="text/javascript"></script>
355
+ #
356
+ # # my_action.herb has a call to require_js 'jquery', 'effects', 'validation'
357
+ # # File: layout/application.html.erb
358
+ # include_required_js
359
+ # # => <script src="/javascripts/jquery.js" type="text/javascript"></script>
360
+ # # <script src="/javascripts/effects.js" type="text/javascript"></script>
361
+ # # <script src="/javascripts/validation.js" type="text/javascript"></script>
362
+ #
363
+ def include_required_js(options = {})
364
+ required_js(options).map { |req_js| js_include_tag(*req_js) }.join
365
+ end
366
+
367
+ # A method used in the layout of an application to create +<link>+ tags for
368
+ # CSS stylesheets required in in templates and subtemplates using
369
+ # require_css.
370
+ #
371
+ # ==== Parameters
372
+ # options<Hash>:: Options to pass to css_include_tag.
373
+ #
374
+ # ==== Returns
375
+ # String:: The CSS tag.
376
+ #
377
+ # ==== Options
378
+ # :bundle<~to_s>::
379
+ # The name of the bundle the stylesheets should be combined into.
380
+ # :media<~to_s>::
381
+ # The media attribute for the generated link element. Defaults to :all.
382
+ #
383
+ # ==== Examples
384
+ # # my_action.herb has a call to require_css 'style'
385
+ # # File: layout/application.html.erb
386
+ # include_required_css
387
+ # # => <link href="/stylesheets/style.css" media="all" rel="Stylesheet" type="text/css"/>
388
+ #
389
+ # # my_action.herb has a call to require_css 'style', 'ie-specific'
390
+ # # File: layout/application.html.erb
391
+ # include_required_css
392
+ # # => <link href="/stylesheets/style.css" media="all" rel="Stylesheet" type="text/css"/>
393
+ # # <link href="/stylesheets/ie-specific.css" media="all" rel="Stylesheet" type="text/css"/>
394
+ #
395
+ def include_required_css(options = {})
396
+ required_css(options).map { |req_js| css_include_tag(*req_js) }.join
397
+ end
398
+
399
+ # ==== Parameters
400
+ # *scripts::
401
+ # The scripts to include. If the last element is a Hash, it will be used
402
+ # as options (see below). If ".js" is left out from the script names, it
403
+ # will be added to them.
404
+ #
405
+ # ==== Options
406
+ # :bundle<~to_s>::
407
+ # The name of the bundle the scripts should be combined into.
408
+ #
409
+ # ==== Returns
410
+ # String:: The JavaScript include tag(s).
411
+ #
412
+ # ==== Examples
413
+ # js_include_tag 'jquery'
414
+ # # => <script src="/javascripts/jquery.js" type="text/javascript"></script>
415
+ #
416
+ # js_include_tag 'moofx.js', 'upload'
417
+ # # => <script src="/javascripts/moofx.js" type="text/javascript"></script>
418
+ # # <script src="/javascripts/upload.js" type="text/javascript"></script>
419
+ #
420
+ # js_include_tag :effects
421
+ # # => <script src="/javascripts/effects.js" type="text/javascript"></script>
422
+ #
423
+ # js_include_tag :jquery, :validation
424
+ # # => <script src="/javascripts/jquery.js" type="text/javascript"></script>
425
+ # # <script src="/javascripts/validation.js" type="text/javascript"></script>
426
+ #
427
+ def js_include_tag(*scripts)
428
+ options = scripts.last.is_a?(Hash) ? scripts.pop : {}
429
+ return nil if scripts.empty?
430
+
431
+ if (bundle_name = options[:bundle]) && Merb::Assets.bundle? && scripts.size > 1
432
+ bundler = Merb::Assets::JavascriptAssetBundler.new(bundle_name, *scripts)
433
+ bundled_asset = bundler.bundle!
434
+ return js_include_tag(bundled_asset)
435
+ end
436
+
437
+ tags = ""
438
+
439
+ for script in scripts
440
+ attrs = {
441
+ :src => asset_path(:javascript, script),
442
+ :type => "text/javascript"
443
+ }
444
+ tags << %Q{<script #{attrs.to_xml_attributes}></script>}
445
+ end
446
+
447
+ return tags
448
+ end
449
+
450
+ # ==== Parameters
451
+ # *stylesheets::
452
+ # The stylesheets to include. If the last element is a Hash, it will be
453
+ # used as options (see below). If ".css" is left out from the stylesheet
454
+ # names, it will be added to them.
455
+ #
456
+ # ==== Options
457
+ # :bundle<~to_s>::
458
+ # The name of the bundle the stylesheets should be combined into.
459
+ # :media<~to_s>::
460
+ # The media attribute for the generated link element. Defaults to :all.
461
+ #
462
+ # ==== Returns
463
+ # String:: The CSS include tag(s).
464
+ #
465
+ # ==== Examples
466
+ # css_include_tag 'style'
467
+ # # => <link href="/stylesheets/style.css" media="all" rel="Stylesheet" type="text/css" charset="utf-8" />
468
+ #
469
+ # css_include_tag 'style.css', 'layout'
470
+ # # => <link href="/stylesheets/style.css" media="all" rel="Stylesheet" type="text/css" charset="utf-8" />
471
+ # # <link href="/stylesheets/layout.css" media="all" rel="Stylesheet" type="text/css" charset="utf-8" />
472
+ #
473
+ # css_include_tag :menu
474
+ # # => <link href="/stylesheets/menu.css" media="all" rel="Stylesheet" type="text/css" charset="utf-8" />
475
+ #
476
+ # css_include_tag :style, :screen
477
+ # # => <link href="/stylesheets/style.css" media="all" rel="Stylesheet" type="text/css" charset="utf-8" />
478
+ # # <link href="/stylesheets/screen.css" media="all" rel="Stylesheet" type="text/css" charset="utf-8" />
479
+ #
480
+ # css_include_tag :style, :media => :print
481
+ # # => <link href="/stylesheets/style.css" media="print" rel="Stylesheet" type="text/css" charset="utf-8" />
482
+ #
483
+ # css_include_tag :style, :charset => 'iso-8859-1'
484
+ # # => <link href="/stylesheets/style.css" media="print" rel="Stylesheet" type="text/css" charset="iso-8859-1" />
485
+ def css_include_tag(*stylesheets)
486
+ options = stylesheets.last.is_a?(Hash) ? stylesheets.pop : {}
487
+ return nil if stylesheets.empty?
488
+
489
+ if (bundle_name = options[:bundle]) && Merb::Assets.bundle? && stylesheets.size > 1
490
+ bundler = Merb::Assets::StylesheetAssetBundler.new(bundle_name, *stylesheets)
491
+ bundled_asset = bundler.bundle!
492
+ return css_include_tag(bundled_asset)
493
+ end
494
+
495
+ tags = ""
496
+
497
+ for stylesheet in stylesheets
498
+ attrs = {
499
+ :href => asset_path(:stylesheet, stylesheet),
500
+ :type => "text/css",
501
+ :rel => "Stylesheet",
502
+ :charset => options[:charset] || 'utf-8',
503
+ :media => options[:media] || :all
504
+ }
505
+ tags << %Q{<link #{attrs.to_xml_attributes} />}
506
+ end
507
+
508
+ return tags
509
+ end
510
+
511
+ # ==== Parameters
512
+ # *assets::
513
+ # The assets to include. These should be the full paths to any static served file
514
+ #
515
+ # ==== Returns
516
+ # Array:: Full unique paths to assets OR
517
+ # String:: if only a single path is requested
518
+ # ==== Examples
519
+ # uniq_path("/javascripts/my.js","/javascripts/my.css")
520
+ # #=> ["http://assets2.my-awesome-domain.com/javascripts/my.js", "http://assets1.my-awesome-domain.com/javascripts/my.css"]
521
+ #
522
+ # uniq_path(["/javascripts/my.js","/stylesheets/my.css"])
523
+ # #=> ["http://assets2.my-awesome-domain.com/javascripts/my.js", "http://assets1.my-awesome-domain.com/stylesheets/my.css"]
524
+ #
525
+ # uniq_path(%w(/javascripts/my.js /stylesheets/my.css))
526
+ # #=> ["http://assets2.my-awesome-domain.com/javascripts/my.js", "http://assets1.my-awesome-domain.com/stylesheets/my.css"]
527
+ #
528
+ # uniq_path('/stylesheets/somearbitrary.css')
529
+ # #=> "http://assets3.my-awesome-domain.com/stylesheets/somearbitrary.css"
530
+ #
531
+ # uniq_path('/images/hostsexypicture.jpg')
532
+ # #=>"http://assets1.my-awesome-domain.com/images/hostsexypicture.jpg"
533
+ def uniq_path(*assets)
534
+ paths = []
535
+ assets.collect.flatten.each do |filename|
536
+ paths.push(Merb::Assets::UniqueAssetPath.build(filename))
537
+ end
538
+ paths.length > 1 ? paths : paths.first
539
+ end
540
+
541
+ # ==== Parameters
542
+ # *assets::
543
+ # Creates unique paths for javascript files (prepends "/javascripts" and appends ".js")
544
+ #
545
+ # ==== Returns
546
+ # Array:: Full unique paths to assets OR
547
+ # String:: if only a single path is requested
548
+ # ==== Examples
549
+ # uniq_js_path("my")
550
+ # #=> "http://assets2.my-awesome-domain.com/javascripts/my.js"
551
+ #
552
+ # uniq_js_path(["admin/secrets","home/signup"])
553
+ # #=> ["http://assets2.my-awesome-domain.com/javascripts/admin/secrets.js",
554
+ # "http://assets1.my-awesome-domain.com/javascripts/home/signup.js"]
555
+ def uniq_js_path(*assets)
556
+ paths = []
557
+ assets.collect.flatten.each do |filename|
558
+ paths.push(Merb::Assets::UniqueAssetPath.build(asset_path(:javascript,filename)))
559
+ end
560
+ paths.length > 1 ? paths : paths.first
561
+ end
562
+
563
+ # ==== Parameters
564
+ # *assets::
565
+ # Creates unique paths for stylesheet files (prepends "/stylesheets" and appends ".css")
566
+ #
567
+ # ==== Returns
568
+ # Array:: Full unique paths to assets OR
569
+ # String:: if only a single path is requested
570
+ # ==== Examples
571
+ # uniq_css_path("my")
572
+ # #=> "http://assets2.my-awesome-domain.com/stylesheets/my.css"
573
+ #
574
+ # uniq_css_path(["admin/secrets","home/signup"])
575
+ # #=> ["http://assets2.my-awesome-domain.com/stylesheets/admin/secrets.css",
576
+ # "http://assets1.my-awesome-domain.com/stylesheets/home/signup.css"]
577
+ def uniq_css_path(*assets)
578
+ paths = []
579
+ assets.collect.flatten.each do |filename|
580
+ paths.push(Merb::Assets::UniqueAssetPath.build(asset_path(:stylesheet,filename)))
581
+ end
582
+ paths.length > 1 ? paths : paths.first
583
+ end
584
+
585
+ # ==== Parameters
586
+ # *assets::
587
+ # As js_include_tag but has unique path
588
+ #
589
+ # ==== Returns
590
+ # Array:: Full unique paths to assets OR
591
+ # String:: if only a single path is requested
592
+ # ==== Examples
593
+ # uniq_js_tag("my")
594
+ # #=> <script type="text/javascript" src="http://assets2.my-awesome-domain.com/javascripts/my.js"></script>
595
+ def uniq_js_tag(*assets)
596
+ js_include_tag(*uniq_js_path(assets))
597
+ end
598
+
599
+ # ==== Parameters
600
+ # *assets::
601
+ # As uniq_css_tag but has unique path
602
+ #
603
+ # ==== Returns
604
+ # Array:: Full unique paths to assets OR
605
+ # String:: if only a single path is requested
606
+ # ==== Examples
607
+ # uniq_css_tag("my")
608
+ # #=> <link href="http://assets2.my-awesome-domain.com/stylesheets/my.css" type="text/css" />
609
+ def uniq_css_tag(*assets)
610
+ css_include_tag(*uniq_css_path(assets))
611
+ end
612
+
613
+ private
614
+
615
+ # Helper method to filter out duplicate files.
616
+ #
617
+ # ==== Parameters
618
+ # options<Hash>:: Options to pass to include tag methods.
619
+ def extract_required_files(files, options = {})
620
+ return [] if files.nil? || files.empty?
621
+ seen = []
622
+ files.inject([]) do |extracted, req_js|
623
+ include_files, include_options = if req_js.last.is_a?(Hash)
624
+ [req_js[0..-2], options.merge(req_js.last)]
625
+ else
626
+ [req_js, options]
627
+ end
628
+ seen += (includes = include_files - seen)
629
+ extracted << (includes + [include_options]) unless includes.empty?
630
+ extracted
631
+ end
632
+ end
633
+
634
+ end
635
+ end