requirejs-rails 0.7.3 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.md CHANGED
@@ -1,3 +1,9 @@
1
+ # v0.8.0
2
+
3
+ - Build will now substitute `empty:` for the right-hand side of
4
+ `config/requirejs.yml` paths entries that are URLs.
5
+ - Documented how to configure assets hosted on a CDN.
6
+
1
7
  # v0.7.3
2
8
 
3
9
  - Upgrade RequireJS and r.js to v1.0.8
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- requirejs-rails (0.7.3)
4
+ requirejs-rails (0.8.0)
5
5
  railties (>= 3.1.1, < 3.3)
6
6
 
7
7
  GEM
data/README.md CHANGED
@@ -186,9 +186,51 @@ This will generate a script tag like so:
186
186
  <script data-main="/assets/page1.js" data-foo="..." data-bar="..." src="/assets/require.js"></script>
187
187
  ```
188
188
 
189
+ ### External domain (CDN) support
190
+
191
+ There are two ways in which requirejs-rails supports the use of different
192
+ domains for serving built JavaScript modules, as is the case when using
193
+ a [CDN](http://en.wikipedia.org/wiki/Content_delivery_network).
194
+
195
+ 1. URLs in paths config in `requirejs.yml`:
196
+
197
+ If requirejs-rails encounters an URL as the right-hand side of a paths
198
+ configuration, it will correctly emit that as `"empty:"` during the build
199
+ process so that [r.js will do the right thing](http://requirejs.org/docs/optimization.html#empty).
200
+
201
+ Example:
202
+
203
+ ```yaml
204
+ paths:
205
+ jquery: "https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"
206
+ ```
207
+
208
+ 2. Deploying all requirejs-rails assets to a CDN:
209
+
210
+ In `config/environments/production.rb` (or another environment)
211
+ set the run_config as follows:
212
+
213
+ ```ruby
214
+ config.requirejs.run_config['baseUrl'] = 'http://mycdn.example.com/12345abc/assets'
215
+ ```
216
+
217
+ The [`asset_sync` gem](https://github.com/rumblelabs/asset_sync) is one
218
+ tool that can be used to deploy your built assets to a CDN (S3, in this
219
+ case).
220
+
221
+ ## Troubleshooting
222
+
223
+ ### Avoid `config.assets.precompile`
224
+
225
+ Don't set `config.assets.precompile` to reference any of your AMD module code.
226
+ Avoid it altogether, except to reference non-AMD code that you're loading via
227
+ javascript_include_tag, and which is **never** referenced by the AMD codebase.
228
+
189
229
  ## Using AMD libraries
190
230
 
191
- I currently recommend placing your AMD libraries into `vendor/assets/javascripts`. The needs of a few specific libraries are discussed below.
231
+ I currently recommend placing your AMD libraries into
232
+ `vendor/assets/javascripts`. The needs of a few specific libraries are
233
+ discussed below.
192
234
 
193
235
  ### jQuery
194
236
 
@@ -1,11 +1,17 @@
1
1
  require 'requirejs/error'
2
2
 
3
3
  module RequirejsHelper
4
+ # EXPERIMENTAL: Additional priority settings appended to
5
+ # any user-specified priority setting by requirejs_include_tag.
6
+ # Used for JS test suite integration.
7
+ mattr_accessor :_priority
8
+ @@_priority = []
9
+
4
10
  def _requirejs_data(name, &block)
5
11
  {}.tap do |data|
6
12
  if name
7
13
  name += ".js" unless name =~ /\.js$/
8
- data['main'] = javascript_path(name)
14
+ data['main'] = _javascript_path(name)
9
15
  end
10
16
 
11
17
  data.merge!(yield controller) if block_given?
@@ -17,7 +23,7 @@ module RequirejsHelper
17
23
  def _data_main(name)
18
24
  if name
19
25
  name += ".js" unless name =~ /\.js$/
20
- %Q{data-main="#{javascript_path(name)}"}
26
+ %Q{data-main="#{_javascript_path(name)}"}
21
27
  else
22
28
  ""
23
29
  end
@@ -33,37 +39,61 @@ module RequirejsHelper
33
39
 
34
40
  html = ""
35
41
 
36
- if controller.requirejs_included
37
- raise Requirejs::MultipleIncludeError, "Only one requirejs_include_tag allowed per page."
38
- end
42
+ _once_guard do
43
+ unless requirejs.run_config.empty?
44
+ run_config = requirejs.run_config.dup
45
+ unless _priority.empty?
46
+ run_config = run_config.dup
47
+ run_config[:priority] ||= []
48
+ run_config[:priority].concat _priority
49
+ end
50
+ if Rails.application.config.assets.digest
51
+ modules = requirejs.build_config['modules'].map { |m| requirejs.module_name_for m }
39
52
 
40
- unless requirejs.run_config.empty?
41
- run_config = requirejs.run_config
42
- if Rails.application.config.assets.digest
43
- modules = requirejs.build_config['modules'].map { |m| requirejs.module_name_for m }
53
+ # Generate digestified paths from the modules spec
54
+ paths = {}
55
+ modules.each { |m| paths[m] = _javascript_path(m).sub /\.js$/,'' }
44
56
 
45
- # Generate digestified paths from the modules spec
46
- paths = {}
47
- modules.each { |m| paths[m] = javascript_path(m).sub /\.js$/,'' }
57
+ # Add paths for assets specified by full URL (on a CDN)
58
+ run_config['paths'].each { |k,v| paths[k] = v if v =~ /^https?:/ }
48
59
 
49
- # Override uesr paths, whose mappings are only relevant in dev mode
50
- # and in the build_config.
51
- run_config['paths'] = paths
60
+ # Override user paths, whose mappings are only relevant in dev mode
61
+ # and in the build_config.
62
+ run_config['paths'] = paths
63
+ end
64
+ html.concat <<-HTML
65
+ <script>var require = #{run_config.to_json};</script>
66
+ HTML
52
67
  end
68
+
53
69
  html.concat <<-HTML
54
- <script>var require = #{run_config.to_json};</script>
70
+ <script #{_requirejs_data(name, &block)} src="#{_javascript_path 'require.js'}"></script>
55
71
  HTML
72
+
73
+ html.html_safe
56
74
  end
75
+ end
57
76
 
58
- html.concat <<-HTML
59
- <script #{_requirejs_data(name, &block)} src="#{javascript_path 'require.js'}"></script>
60
- HTML
77
+ def _once_guard
78
+ if defined?(controller) && controller.requirejs_included
79
+ raise Requirejs::MultipleIncludeError, "Only one requirejs_include_tag allowed per page."
80
+ end
81
+
82
+ retval = yield
61
83
 
62
- controller.requirejs_included = true
63
- html.html_safe
84
+ controller.requirejs_included = true if defined?(controller)
85
+ retval
64
86
  end
65
87
 
66
88
  def _almond_include_tag(name, &block)
67
- "<script src='#{javascript_path name}'></script>\n".html_safe
89
+ "<script src='#{_javascript_path name}'></script>\n".html_safe
90
+ end
91
+
92
+ def _javascript_path(name)
93
+ if defined?(javascript_path)
94
+ javascript_path(name)
95
+ else
96
+ "/assets/#{name}"
97
+ end
68
98
  end
69
99
  end
@@ -26,6 +26,8 @@ module Requirejs::Rails
26
26
  self.driver_template_path = Pathname.new(__FILE__+'/../rjs_driver.js.erb').cleanpath
27
27
  self.driver_path = self.tmp_dir + 'rjs_driver.js'
28
28
 
29
+ self.user_config = {}
30
+
29
31
  self.run_config_whitelist = %w{
30
32
  baseUrl
31
33
  callback
@@ -106,13 +108,24 @@ module Requirejs::Rails
106
108
  mod['name'] = 'almond'
107
109
  mod['include'] = name
108
110
  end
111
+ self.rewrite_urls_in_paths self[:build_config]
109
112
  end
110
113
  self[:build_config]
111
114
  end
112
115
 
113
116
  def run_config
114
- run_config = { "baseUrl" => "/assets" }
115
- run_config.merge!(self.user_config).slice(*self.run_config_whitelist)
117
+ unless self.has_key?(:run_config)
118
+ self[:run_config] = { "baseUrl" => "/assets" }
119
+ self[:run_config].merge!(self.user_config).slice!(*self.run_config_whitelist)
120
+ end
121
+ self[:run_config]
122
+ end
123
+
124
+ def user_config=(cfg)
125
+ if url = cfg.delete('baseUrl')
126
+ raise Requirejs::ConfigError, "baseUrl is not needed or permitted in the configuration"
127
+ end
128
+ self[:user_config] = cfg
116
129
  end
117
130
 
118
131
  def module_name_for(mod)
@@ -137,5 +150,13 @@ module Requirejs::Rails
137
150
  accum || (matcher =~ asset)
138
151
  end ? true : false
139
152
  end
153
+
154
+ def rewrite_urls_in_paths(cfg)
155
+ if cfg.has_key? 'paths'
156
+ cfg['paths'] = cfg['paths'].each_with_object({}) do |(k, v), h|
157
+ h[k] = (v =~ /^https?:/) ? 'empty:' : v
158
+ end
159
+ end
160
+ end
140
161
  end
141
162
  end
@@ -1,6 +1,6 @@
1
1
  module Requirejs
2
2
  module Rails
3
- Version = "0.7.3"
4
- LibVersion = "1.0.7"
3
+ Version = "0.8.0"
4
+ LibVersion = "1.0.8"
5
5
  end
6
6
  end
@@ -44,12 +44,92 @@ class RequirejsRailsConfigTest < ActiveSupport::TestCase
44
44
  @cfg.logical_asset_filter += [/\.frobnitz$/]
45
45
  assert_equal true, @cfg.asset_allowed?('bar.frobnitz')
46
46
  end
47
+
48
+ test "should have a default empty user_config" do
49
+ assert_kind_of Hash, @cfg.user_config
50
+ end
51
+
52
+ test "user_config should reject baseUrl" do
53
+ exc = assert_raises Requirejs::ConfigError do
54
+ @cfg.user_config = { 'baseUrl' => '/frobnitz' }
55
+ end
56
+ assert_match /baseUrl is not needed/, exc.message
57
+ end
58
+
59
+ test "run_config should inherit user_config settings" do
60
+ @cfg.user_config = { 'paths' => { 'jquery' => 'lib/jquery-1.7.2.min' } }
61
+ refute_nil @cfg.run_config['paths']
62
+ assert_kind_of Hash, @cfg.run_config['paths']
63
+ assert_equal 'lib/jquery-1.7.2.min', @cfg.run_config['paths']['jquery']
64
+ end
65
+
66
+ test "run_config should allow settings to be overridden" do
67
+ @cfg.run_config['baseUrl'] = 'http://cdn.example.com/assets'
68
+ assert_equal 'http://cdn.example.com/assets', @cfg.run_config['baseUrl']
69
+ end
70
+
71
+ test "build_config should inherit user_config settings" do
72
+ @cfg.user_config = { 'paths' => { 'jquery' => 'lib/jquery-1.7.2.min' } }
73
+ refute_nil @cfg.build_config['paths']
74
+ assert_kind_of Hash, @cfg.build_config['paths']
75
+ assert_equal 'lib/jquery-1.7.2.min', @cfg.build_config['paths']['jquery']
76
+ end
77
+
78
+ test "run_config should reject irrelevant settings" do
79
+ @cfg.user_config = { 'optimize' => 'none' }
80
+ assert_nil @cfg.run_config['optimize']
81
+ end
82
+
83
+ test "build_config should reject irrelevant settings" do
84
+ @cfg.user_config = { 'priority' => %w{ foo bar baz } }
85
+ assert_nil @cfg.build_config['priority']
86
+ end
87
+
88
+ test "build config should replace urls in paths with 'empty:'" do
89
+ @cfg.user_config = { 'paths' =>
90
+ {
91
+ 'jquery' => 'http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js',
92
+ 'jqueryssl' => 'https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js'
93
+ }
94
+ }
95
+ assert_equal 'empty:', @cfg.build_config['paths']['jquery']
96
+ assert_equal 'empty:', @cfg.build_config['paths']['jqueryssl']
97
+ end
98
+
99
+ test "build_config should not modify non-urls in paths" do
100
+ @cfg.user_config = { 'paths' =>
101
+ {
102
+ 'foo' => 'components/foo'
103
+ }
104
+ }
105
+ assert_equal 'components/foo', @cfg.build_config['paths']['foo']
106
+ end
107
+
108
+ ## Almond-specific tests
109
+ test "build_config with almond should accept one module" do
110
+ @cfg.loader = :almond
111
+ @cfg.user_config = { 'modules' => [ { 'name' => 'foo' } ] }
112
+ assert_match 'almond', @cfg.build_config['modules'][0]['name']
113
+ end
114
+
115
+ test "build_config with almond must reject more than one module" do
116
+ @cfg.loader = :almond
117
+ @cfg.user_config = { 'modules' => [ { 'name' => 'foo' }, { 'name' => 'bar' } ] }
118
+ exc = assert_raises Requirejs::ConfigError do
119
+ @cfg.build_config
120
+ end
121
+ assert_match /requires exactly one module/, exc.message
122
+ end
47
123
  end
48
124
 
49
125
  class RequirejsHelperTest < ActionView::TestCase
50
126
 
51
127
  def setup
52
128
  controller.requirejs_included = false
129
+ Rails.application.config.requirejs.user_config = { 'paths' =>
130
+ { 'jquery' => 'http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js' }
131
+ }
132
+
53
133
  end
54
134
 
55
135
  def wrap(tag)
@@ -82,4 +162,20 @@ class RequirejsHelperTest < ActionView::TestCase
82
162
  render :text => "#{requirejs_include_tag}\n#{requirejs_include_tag}"
83
163
  end
84
164
  end
165
+
166
+ test "requirejs_include_tag with CDN asset in paths" do
167
+ render :text => wrap(requirejs_include_tag)
168
+ assert_select "script:first-of-type", :text => %r{var require =.*paths.*http://ajax}
169
+ end
170
+
171
+ test "requirejs_include_tag with CDN asset and digested asset paths" do
172
+ begin
173
+ saved_digest = Rails.application.config.assets.digest
174
+ Rails.application.config.assets.digest = true
175
+ render :text => wrap(requirejs_include_tag)
176
+ assert_select "script:first-of-type", :text => %r{var require =.*paths.*http://ajax}
177
+ ensure
178
+ Rails.application.config.assets.digest = saved_digest
179
+ end
180
+ end
85
181
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: requirejs-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.3
4
+ version: 0.8.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-04-20 00:00:00.000000000 Z
12
+ date: 2012-05-01 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: railties
16
- requirement: &70218915266960 !ruby/object:Gem::Requirement
16
+ requirement: &70259994422520 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -24,10 +24,10 @@ dependencies:
24
24
  version: '3.3'
25
25
  type: :runtime
26
26
  prerelease: false
27
- version_requirements: *70218915266960
27
+ version_requirements: *70259994422520
28
28
  - !ruby/object:Gem::Dependency
29
29
  name: rails
30
- requirement: &70218915433300 !ruby/object:Gem::Requirement
30
+ requirement: &70259994419640 !ruby/object:Gem::Requirement
31
31
  none: false
32
32
  requirements:
33
33
  - - ! '>='
@@ -38,10 +38,10 @@ dependencies:
38
38
  version: '3.3'
39
39
  type: :development
40
40
  prerelease: false
41
- version_requirements: *70218915433300
41
+ version_requirements: *70259994419640
42
42
  - !ruby/object:Gem::Dependency
43
43
  name: sqlite3
44
- requirement: &70218915431540 !ruby/object:Gem::Requirement
44
+ requirement: &70259994416180 !ruby/object:Gem::Requirement
45
45
  none: false
46
46
  requirements:
47
47
  - - ! '>='
@@ -49,7 +49,7 @@ dependencies:
49
49
  version: '0'
50
50
  type: :development
51
51
  prerelease: false
52
- version_requirements: *70218915431540
52
+ version_requirements: *70259994416180
53
53
  description: This gem provides RequireJS support for your Rails 3 application.
54
54
  email:
55
55
  - whitley@bangpath.org
@@ -129,7 +129,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
129
129
  version: '0'
130
130
  segments:
131
131
  - 0
132
- hash: 2649433147791205198
132
+ hash: -70510863405532610
133
133
  required_rubygems_version: !ruby/object:Gem::Requirement
134
134
  none: false
135
135
  requirements:
@@ -138,7 +138,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
138
138
  version: '0'
139
139
  segments:
140
140
  - 0
141
- hash: 2649433147791205198
141
+ hash: -70510863405532610
142
142
  requirements:
143
143
  - node.js is required for 'rake assets:precompile', used to run the r.js build
144
144
  - If needed, jQuery should be v1.7 or greater (jquery-rails >= 1.0.17).