merb-assets 1.1.0.rc1 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/merb-assets.rb CHANGED
@@ -12,6 +12,7 @@ Merb::Plugins.config[:asset_helpers] = {
12
12
  :asset_domain => "assets%s",
13
13
  :domain => "my-awesome-domain.com",
14
14
  :use_ssl => false,
15
+ :asset_timestamp => false,
15
16
 
16
17
  # Global prefix/suffix for css/js include tags, overridable in js_include_tag and css_include_tag
17
18
  #
@@ -1,66 +1,72 @@
1
1
  module Merb
2
2
  # The AssetsMixin module provides a number of helper methods to views for
3
3
  # linking to assets and other pages, dealing with JavaScript and CSS.
4
+ #
5
+ # Merb provides views with convenience methods for links images and other
6
+ # assets.
4
7
  module AssetsMixin
5
8
  include Merb::Assets::AssetHelpers
6
- # :section: Accessing Assets
7
- # Merb provides views with convenience methods for links images and other
8
- # assets.
9
9
 
10
+ ABSOLUTE_PATH_REGEXP = %r{^#{Merb::Const::HTTP}s?://}
10
11
 
11
12
  # This tests whether a random query string shall be appended to a url.
13
+ #
12
14
  # Basically, you tell it your intention and if it's ok to use default
13
15
  # config values, and it will either use your intention or the value
14
16
  # set in Merb::Config[:reload_templates]
15
17
  #
16
- # ==== Parameters
17
- # intention<Boolean>: true if a random string shall be appended
18
- # allow_default<Boolean>: true if it's ok to use Merb::Config[:reload_templates]
19
- #
20
- # ==== Returns
21
- # <Boolean> true if a random query string shall be appended
22
- #
23
- # ==== Examples
18
+ # @example
24
19
  # Merb::AssetsMixin.append_random_query_string?(options[:reload])
25
20
  # Merb::AssetsMixin.append_random_query_string?(options[:reload], !absolute)
21
+ #
22
+ # @param [Boolean] intention: true if a random string shall be appended
23
+ # @param [Boolean] allow_default: true if it's ok to use Merb::Config[:reload_templates]
24
+ # @return [Boolean] true if a random query string shall be appended
26
25
  def self.append_random_query_string?(intention, allow_default = true)
27
26
  intention.nil? && allow_default ? Merb::Config[:reload_templates] : intention
28
27
  end
29
28
 
30
- # ==== Parameters
31
- # none
29
+ # This tests whether a timestamp query string shall be appended to a url.
32
30
  #
33
- # ==== Returns
34
- # html<String>
31
+ # @see self.append_random_query_string?
35
32
  #
36
- # ==== Examples
37
- # We want all possible matches in the FileSys up to the action name
38
- # Given: controller_name = "namespace/controller"
39
- # action_name = "action"
40
- # If all files are present should generate link/script tags for:
41
- # namespace.(css|js)
42
- # namespace/controller.(css|js)
43
- # namespace/controller/action.(css|js)
33
+ # @example
34
+ # Merb::AssetsMixin.append_timestamp_query_string?(options[:timestamp])
35
+ # Merb::AssetsMixin.append_timestamp_query_string?(options[:timestamp], !absolute)
44
36
  #
45
- def auto_link
46
- [auto_link_css, auto_link_js].join("\n")
37
+ # @param [Boolean] intention: true if a timestamp string shall be appended
38
+ # @param [Boolean] allow_default: true if it's ok to use Merb::Plugins.config[:asset_helpers][:asset_timestamp]
39
+ # @return [Boolean] true if a timestamp query string shall be appended
40
+ def self.append_timestamp_query_string?(intention, allow_default = true)
41
+ intention.nil? && allow_default ? Merb::Plugins.config[:asset_helpers][:asset_timestamp] : intention
47
42
  end
48
43
 
49
- # ==== Parameters
50
- # none
44
+ # Automatically generates link for CSS and JS
51
45
  #
52
- # ==== Returns
53
- # html<String>
46
+ # We want all possible matches in the FileSys up to the action name
47
+ # Given: controller_name = "namespace/controller"
48
+ # action_name = "action"
49
+ # @example
50
+ # If all files are present should generate link/script tags for:
51
+ # namespace.(css|js)
52
+ # namespace/controller.(css|js)
53
+ # namespace/controller/action.(css|js)
54
54
  #
55
- # ==== Examples
55
+ # @return [String] html
56
+ def auto_link
57
+ [auto_link_css, auto_link_js].join(Merb::Const::NEWLINE)
58
+ end
59
+
56
60
  # We want all possible matches in the file system upto the action name
57
61
  # for CSS. The reason for separating auto_link for CSS and JS is
58
62
  # performance concerns with page loading. See Yahoo performance rules
59
63
  # (http://developer.yahoo.com/performance/rules.html)
64
+ #
65
+ # @return [String] html
60
66
  def auto_link_css
61
67
  auto_link_paths.map do |path|
62
68
  asset_exists?(:stylesheet, path) ? css_include_tag(path) : nil
63
- end.compact.join("\n")
69
+ end.compact.join(Merb::Const::NEWLINE)
64
70
  end
65
71
 
66
72
  # ==== Parameters
@@ -77,7 +83,7 @@ module Merb
77
83
  def auto_link_js
78
84
  auto_link_paths.map do |path|
79
85
  asset_exists?(:javascript, path) ? js_include_tag(path) : nil
80
- end.compact.join("\n")
86
+ end.compact.join(Merb::Const::NEWLINE)
81
87
  end
82
88
 
83
89
  # ==== Parameters
@@ -103,10 +109,10 @@ module Merb
103
109
  # This is an auxiliary method which returns an array of all possible asset
104
110
  # paths for the current controller/action.
105
111
  def auto_link_paths
106
- paths = (controller_name / action_name).split('/')
112
+ paths = (controller_name / action_name).split(Merb::Const::SLASH)
107
113
  first = paths.shift
108
114
  paths.inject( [first] ) do |memo, val|
109
- memo.push [memo.last, val].join('/')
115
+ memo.push [memo.last, val].join(Merb::Const::SLASH)
110
116
  end
111
117
  end
112
118
 
@@ -130,22 +136,25 @@ module Merb
130
136
  %{<a #{ opts.to_xml_attributes }>#{name}</a>}
131
137
  end
132
138
 
133
- # ==== Parameters
134
- # img<~to_s>:: The image path.
135
- # opts<Hash>:: Additional options for the image tag (see below).
139
+ # Generate IMG tag
136
140
  #
137
- # ==== Options (opts)
138
- # :path<String>::
141
+ # @param [String, #to_s] img The image path.
142
+ # @param [Hash] opts Additional options for the image tag (see below).
143
+ # @option opts [String] :path
139
144
  # Sets the path prefix for the image. Defaults to "/images/" or whatever
140
145
  # is specified in Merb::Config. This is ignored if img is an absolute
141
146
  # path or full URL.
142
- # :reload<Boolean>::
147
+ # @option opts [Boolean] :reload
143
148
  # Override the Merb::Config[:reload_templates] value. If true, a random query param will be appended
144
149
  # to the image url
150
+ # @option opts [Boolean, String] :timestamp
151
+ # Override the Merb::Plugins.config[:asset_helpers][:asset_timestamp] value. If true, a timestamp query param will be appended
152
+ # to the image url. The value will be File.mtime(Merb.dir_for(:public) / path).
153
+ # If String is passed than it will be used as the timestamp.
145
154
  #
146
155
  # All other options set HTML attributes on the tag.
147
156
  #
148
- # ==== Examples
157
+ # @example
149
158
  # image_tag('foo.gif')
150
159
  # # => <img src='/images/foo.gif' />
151
160
  #
@@ -162,13 +171,15 @@ module Merb
162
171
  # or
163
172
  # image_tag('/dynamic/charts')
164
173
  # # => <img src="/dynamic/charts">
174
+ #
175
+ # @return [String]
165
176
  def image_tag(img, opts={})
166
177
  return "" if img.blank?
167
- if img[0].chr == '/'
178
+ if img[0].chr == Merb::Const::SLASH
168
179
  opts[:src] = "#{Merb::Config[:path_prefix]}#{img}"
169
180
  else
170
181
  opts[:path] ||=
171
- if img =~ %r{^https?://}
182
+ if img =~ ABSOLUTE_PATH_REGEXP
172
183
  absolute = true
173
184
  ''
174
185
  else
@@ -177,10 +188,11 @@ module Merb
177
188
  opts[:src] ||= opts.delete(:path) + img
178
189
  end
179
190
 
180
- if AssetsMixin.append_random_query_string?(opts.delete(:reload), !absolute)
181
- opts[:src] += opts[:src].include?('?') ? "&#{random_query_string}" : "?#{random_query_string}"
182
- end
183
-
191
+ opts[:src] = append_query_string(opts[:src],
192
+ opts.delete(:reload),
193
+ opts.delete(:timestamp),
194
+ !absolute)
195
+
184
196
  %{<img #{ opts.to_xml_attributes } />}
185
197
  end
186
198
 
@@ -464,8 +476,9 @@ module Merb
464
476
  required_css(options).map { |req_js| css_include_tag(*req_js) }.join
465
477
  end
466
478
 
467
- # ==== Parameters
468
- # *scripts::
479
+ # Generate JavaScript include tag(s).
480
+ #
481
+ # @param [Array] scripts
469
482
  # The scripts to include. If the last element is a Hash, it will be used
470
483
  # as options (see below). If ".js" is left out from the script names, it
471
484
  # will be added to them.
@@ -482,11 +495,12 @@ module Merb
482
495
  # :reload<Boolean>::
483
496
  # Override the Merb::Config[:reload_templates] value. If true, a random query param will be appended
484
497
  # to the js url
498
+ # @option opts [Boolean, String] :timestamp
499
+ # Override the Merb::Plugins.config[:asset_helpers][:asset_timestamp] value. If true, a timestamp query param will be appended
500
+ # to the image url. The value will be File.mtime(Merb.dir_for(:public) / path).
501
+ # If String is passed than it will be used as the timestamp.
485
502
  #
486
- # ==== Returns
487
- # String:: The JavaScript include tag(s).
488
- #
489
- # ==== Examples
503
+ # @example
490
504
  # js_include_tag 'jquery'
491
505
  # # => <script src="/javascripts/jquery.js" type="text/javascript" charset="utf-8"></script>
492
506
  #
@@ -511,6 +525,8 @@ module Merb
511
525
  # js_include_tag :application, :validation, :suffix => ".#{MyApp.version}"
512
526
  # # => <script src="/javascripts/application.1.0.3.js" type="text/javascript" charset="utf-8"></script>
513
527
  # # <script src="/javascripts/validation.1.0.3.js" type="text/javascript" charset="utf-8"></script>
528
+ #
529
+ # @return [String] The JavaScript include tag(s).
514
530
  def js_include_tag(*scripts)
515
531
  options = scripts.last.is_a?(Hash) ? scripts.pop : {}
516
532
  return nil if scripts.empty?
@@ -534,9 +550,9 @@ module Merb
534
550
  src.insert(-ext_length,js_suffix)
535
551
  end
536
552
 
537
- if AssetsMixin.append_random_query_string?(options[:reload])
538
- src += src.include?('?') ? "&#{random_query_string}" : "?#{random_query_string}"
539
- end
553
+ src = append_query_string(src,
554
+ options.delete(:reload),
555
+ options.delete(:timestamp))
540
556
 
541
557
  attrs = {
542
558
  :src => src,
@@ -549,31 +565,33 @@ module Merb
549
565
  return tags
550
566
  end
551
567
 
552
- # ==== Parameters
553
- # *stylesheets::
568
+ # Generate CSS include tag(s).
569
+ #
570
+ # @param [Array<*String, Hash>] stylesheets
554
571
  # The stylesheets to include. If the last element is a Hash, it will be
555
572
  # used as options (see below). If ".css" is left out from the stylesheet
556
573
  # names, it will be added to them.
557
574
  #
558
575
  # ==== Options
559
- # :charset<~to_s>::
576
+ # @option opts <String, #to_s> charset
560
577
  # Charset which will be used as value for charset attribute
561
- # :bundle<~to_s>::
578
+ # @option opts <String, #to_s> bundle
562
579
  # The name of the bundle the stylesheets should be combined into.
563
- # :media<~to_s>::
580
+ # @option opts <String, #to_s> media
564
581
  # The media attribute for the generated link element. Defaults to :all.
565
- # :prefix<~to_s>::
582
+ # @option opts <String, #to_s> prefix
566
583
  # prefix to add to include tag, overrides any set in Merb::Plugins.config[:asset_helpers][:css_prefix]
567
- # :suffix<~to_s>::
584
+ # @option opts <String, #to_s> suffix
568
585
  # suffix to add to include tag, overrides any set in Merb::Plugins.config[:asset_helpers][:css_suffix]
569
- # :reload<Boolean>::
586
+ # @option opts <Boolean> reload
570
587
  # Override the Merb::Config[:reload_templates] value. If true, a random query param will be appended
571
588
  # to the css url
589
+ # @option opts [Boolean, String] :timestamp
590
+ # Override the Merb::Plugins.config[:asset_helper][:asset_timestamp] value. If true, a timestamp query param will be appended
591
+ # to the image url. The value will be File.mtime(Merb.dir_for(:public) / path).
592
+ # If String is passed than it will be used as the timestamp.
572
593
  #
573
- # ==== Returns
574
- # String:: The CSS include tag(s).
575
- #
576
- # ==== Examples
594
+ # @example
577
595
  # css_include_tag 'style'
578
596
  # # => <link href="/stylesheets/style.css" media="all" rel="Stylesheet" type="text/css" charset="utf-8" />
579
597
  #
@@ -599,6 +617,8 @@ module Merb
599
617
  #
600
618
  # css_include_tag :style, :suffix => ".#{MyApp.version}"
601
619
  # # => <link href="/stylesheets/style.1.0.0.css" media="print" rel="Stylesheet" type="text/css" />
620
+ #
621
+ # @return [String] The CSS include tag(s)
602
622
  def css_include_tag(*stylesheets)
603
623
  options = stylesheets.last.is_a?(Hash) ? stylesheets.pop : {}
604
624
  return nil if stylesheets.empty?
@@ -614,6 +634,8 @@ module Merb
614
634
 
615
635
  tags = ""
616
636
 
637
+ reload = options.delete(:reload)
638
+ timestamp = options.delete(:timestamp)
617
639
  for stylesheet in stylesheets
618
640
  href = css_prefix.to_s + asset_path(:stylesheet, stylesheet)
619
641
 
@@ -622,9 +644,7 @@ module Merb
622
644
  href.insert(-ext_length,css_suffix)
623
645
  end
624
646
 
625
- if AssetsMixin.append_random_query_string?(options[:reload])
626
- href += href.include?('?') ? "&#{random_query_string}" : "?#{random_query_string}"
627
- end
647
+ href = append_query_string(href, reload, timestamp)
628
648
 
629
649
  attrs = {
630
650
  :href => href,
@@ -761,9 +781,37 @@ module Merb
761
781
  extracted
762
782
  end
763
783
  end
784
+
785
+ def append_query_string(path, random, timestamp, allow_default = true)
786
+ random = AssetsMixin.append_random_query_string?(random, allow_default)
787
+ timestamp = AssetsMixin.append_timestamp_query_string?(timestamp, allow_default)
788
+
789
+ query_string = if random
790
+ random_query_string
791
+ elsif timestamp
792
+ timestamp == true ? timestamp_for_asset(path) : timestamp
793
+ end
794
+
795
+ if query_string
796
+ path + (path.include?('?') ? "&#{query_string}" : "?#{query_string}")
797
+ else
798
+ path
799
+ end
800
+ end
764
801
 
765
802
  def random_query_string
766
803
  Time.now.strftime("%m%d%H%M%S#{rand(99)}")
767
804
  end
805
+
806
+ def timestamp_for_asset(path)
807
+ if path !~ ABSOLUTE_PATH_REGEXP
808
+ begin
809
+ File.mtime(Merb.dir_for(:public) / path).to_i
810
+ rescue
811
+ Merb.logger.warn "#{self.class}: Unable to get mtime for #{path}"
812
+ end
813
+ end
814
+ end
815
+
768
816
  end
769
817
  end
@@ -1,5 +1,5 @@
1
1
  module Merb
2
2
  module Assets
3
- VERSION = '1.1.0.rc1'.freeze
3
+ VERSION = '1.1.0'.freeze
4
4
  end
5
5
  end
Binary file
File without changes
File without changes
@@ -1,5 +1,7 @@
1
1
  require 'spec_helper'
2
2
 
3
+ Merb.push_path(:public, 'spec/fixtures/')
4
+
3
5
  include Merb::AssetsMixin
4
6
 
5
7
  describe "Accessing Assets" do
@@ -182,6 +184,33 @@ describe "With Merb::Config[:reload_templates] set," do
182
184
  end
183
185
  end
184
186
 
187
+ describe "With Merb::Plugins.config[:asset_helpers][:asset_timestamp] set," do
188
+ before(:all) do
189
+ Merb::Plugins.config[:asset_helpers][:asset_timestamp] = true
190
+ end
191
+ after(:all) do
192
+ Merb::Plugins.config[:asset_helpers][:asset_timestamp] = false
193
+ end
194
+
195
+ it "should create image tag with absolute url" do
196
+ image_tag('http://example.com/foo.gif').should ==
197
+ "<img src=\"http://example.com/foo.gif\" />"
198
+ end
199
+
200
+ it "should not add timestamp to the image tag with absolute url if :timestamp option is set" do
201
+ image_tag('http://example.com/foo.gif', :timestamp => true).should =~
202
+ %r{<img src="http://example.com/foo.gif" />}
203
+ end
204
+
205
+ it "should create image tag with relative url" do
206
+ image_tag('merb.jpg').should =~ %r{<img src="/images/merb.jpg\?\d+" />}
207
+ end
208
+
209
+ it "should create image tag with relative url and timestamp which is provided" do
210
+ image_tag('merb.jpg', :timestamp => 123456789).should =~ %r{<img src="/images/merb.jpg\?123456789" />}
211
+ end
212
+ end
213
+
185
214
  describe "JavaScript related functions" do
186
215
  it "should escape js having quotes" do
187
216
  escape_js("'Lorem ipsum!' -- Some guy").should ==
@@ -313,16 +342,72 @@ describe "External JavaScript and Stylesheets" do
313
342
  result.should match(%r{/stylesheets/layout.css})
314
343
  end
315
344
 
316
- it "should create a js include tag with a random query string" do
317
- Merb::Config[:reload_templates] = true
318
- result = js_include_tag('jquery.js')
319
- result.should match(%r{/javascripts/jquery.js\?\d+})
320
- Merb::Config[:reload_templates] = false
345
+ describe "with Merb::Config[:reload_templates] set" do
346
+ it "should create a js include tag with a random query string" do
347
+ Merb::Config[:reload_templates] = true
348
+ result = js_include_tag('jquery.js')
349
+ result.should match(%r{/javascripts/jquery.js\?\d+})
350
+ Merb::Config[:reload_templates] = false
351
+ end
352
+
353
+ it "should create a css include tag with a random query string" do
354
+ Merb::Config[:reload_templates] = true
355
+ result = css_include_tag('style.css')
356
+ result.should match(%r{/stylesheets/style.css\?\d+})
357
+ Merb::Config[:reload_templates] = false
358
+ end
321
359
  end
322
360
 
323
- it "should create a css include tag with a random query string" do
324
- result = css_include_tag('style.css', :reload => true)
325
- result.should match(%r{/stylesheets/style.css\?\d+})
361
+ describe "with Merb::Plugins.config[:asset_helpers][:asset_timestamp] set" do
362
+ it "should create a css include tag with a timestamp query string" do
363
+ Merb::Plugins.config[:asset_helpers][:asset_timestamp] = true
364
+ result = css_include_tag('style.css')
365
+ result.should match(%r{/stylesheets/style.css\?\d+})
366
+ Merb::Plugins.config[:asset_helpers][:asset_timestamp] = false
367
+ end
368
+
369
+ it "should create a js include tag with a timestamp query string" do
370
+ Merb::Plugins.config[:asset_helpers][:asset_timestamp] = true
371
+ result = js_include_tag('jquery.js')
372
+ result.should match(%r{/javascripts/jquery.js\?\d+})
373
+ Merb::Plugins.config[:asset_helpers][:asset_timestamp] = false
374
+ end
375
+ end
376
+
377
+ describe "with :reload => true" do
378
+ it "should create a js include tag with a random query string" do
379
+ result = js_include_tag('jquery.js', :reload => true)
380
+ result.should match(%r{/javascripts/jquery.js\?\d+})
381
+ end
382
+
383
+ it "should create a css include tag with a random query string" do
384
+ result = css_include_tag('style.css', :reload => true)
385
+ result.should match(%r{/stylesheets/style.css\?\d+})
386
+ end
387
+ end
388
+
389
+ describe "with :timestamp => true" do
390
+ it "should create a js include tag with a timestamp query string" do
391
+ result = js_include_tag('jquery.js', :timestamp => true)
392
+ result.should match(%r{/javascripts/jquery.js\?\d+})
393
+ end
394
+
395
+ it "should create a css include tag with a timestamp query string" do
396
+ result = css_include_tag('style.css', :timestamp => true)
397
+ result.should match(%r{/stylesheets/style.css\?\d+})
398
+ end
399
+ end
400
+
401
+ describe "with :timestamp => 123456789" do
402
+ it "should create a js include tag with a 123456789 timestamp query string" do
403
+ result = js_include_tag('jquery.js', :timestamp => 123456789)
404
+ result.should match(%r{/javascripts/jquery.js\?123456789})
405
+ end
406
+
407
+ it "should create a css include tag with a 123456789 timestamp query string" do
408
+ result = css_include_tag('style.css', :timestamp => 123456789)
409
+ result.should match(%r{/stylesheets/style.css\?123456789})
410
+ end
326
411
  end
327
412
 
328
413
  it "should create a css include tag with the specified media" do
data/spec/spec_helper.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require "rubygems"
2
+ require "json"
2
3
 
3
4
  # Use current merb-core sources if running from a typical dev checkout.
4
5
  lib = File.expand_path('../../../merb-core/lib', __FILE__)
metadata CHANGED
@@ -1,13 +1,12 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: merb-assets
3
3
  version: !ruby/object:Gem::Version
4
- prerelease: true
4
+ prerelease: false
5
5
  segments:
6
6
  - 1
7
7
  - 1
8
8
  - 0
9
- - rc1
10
- version: 1.1.0.rc1
9
+ version: 1.1.0
11
10
  platform: ruby
12
11
  authors:
13
12
  - Ezra Zygmuntowicz
@@ -15,7 +14,7 @@ autorequire:
15
14
  bindir: bin
16
15
  cert_chain: []
17
16
 
18
- date: 2010-03-14 00:00:00 +00:00
17
+ date: 2010-03-22 00:00:00 +00:00
19
18
  default_executable:
20
19
  dependencies:
21
20
  - !ruby/object:Gem::Dependency
@@ -29,8 +28,7 @@ dependencies:
29
28
  - 1
30
29
  - 1
31
30
  - 0
32
- - rc1
33
- version: 1.1.0.rc1
31
+ version: 1.1.0
34
32
  type: :runtime
35
33
  version_requirements: *id001
36
34
  - !ruby/object:Gem::Dependency
@@ -66,6 +64,9 @@ files:
66
64
  - lib/merb-assets/assets.rb
67
65
  - lib/merb-assets/assets_mixin.rb
68
66
  - lib/merb-assets/version.rb
67
+ - spec/fixtures/images/merb.jpg
68
+ - spec/fixtures/javascripts/jquery.js
69
+ - spec/fixtures/stylesheets/style.css
69
70
  - spec/merb-assets_spec.rb
70
71
  - spec/spec.opts
71
72
  - spec/spec_helper.rb
@@ -87,13 +88,11 @@ required_ruby_version: !ruby/object:Gem::Requirement
87
88
  version: "0"
88
89
  required_rubygems_version: !ruby/object:Gem::Requirement
89
90
  requirements:
90
- - - ">"
91
+ - - ">="
91
92
  - !ruby/object:Gem::Version
92
93
  segments:
93
- - 1
94
- - 3
95
- - 1
96
- version: 1.3.1
94
+ - 0
95
+ version: "0"
97
96
  requirements: []
98
97
 
99
98
  rubyforge_project: