merb-assets 1.1.0.rc1 → 1.1.0

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/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: