requirejs-rails 0.0.2 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,4 @@
1
+ module Requirejs
2
+ # Raised if requirejs_include_tag appears multiple times on a page.
3
+ class MultipleIncludeError < RuntimeError; end
4
+ end
@@ -0,0 +1,29 @@
1
+ require 'requirejs/rails'
2
+
3
+ require 'pathname'
4
+ require 'ostruct'
5
+
6
+ module Requirejs::Rails
7
+ class Builder
8
+ # config should be an instance of Requirejs::Rails::Config
9
+
10
+ def initialize(config)
11
+ @config = config
12
+ end
13
+
14
+ def build
15
+ @config.tmp_dir
16
+ end
17
+
18
+ def digest_for(path)
19
+ Rails.application.assets.file_digest(path).hexdigest
20
+ end
21
+
22
+ def generate_rjs_driver
23
+ templ = Erubis::Eruby.new(@config.driver_template_path.read)
24
+ @config.driver_path.open('w') do |f|
25
+ f.write(templ.result(@config.get_binding))
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,52 @@
1
+ require 'requirejs/rails'
2
+
3
+ require 'active_support/ordered_options'
4
+ require 'erubis'
5
+ require 'pathname'
6
+
7
+ module Requirejs::Rails
8
+ class Config < ::ActiveSupport::OrderedOptions
9
+
10
+ def initialize(app=Rails.application)
11
+ super
12
+ self.manifest = nil
13
+
14
+ self.tmp_dir = Rails.root + 'tmp'
15
+ self.bin_dir = Pathname.new(__FILE__+'/../../../../bin').cleanpath
16
+
17
+ self.source_dir = self.tmp_dir + 'assets'
18
+ self.target_dir = Rails.root + 'public/assets'
19
+ self.rjs_path = self.bin_dir+'r.js'
20
+
21
+ self.driver_template_path = Pathname.new(__FILE__+'/../rjs_driver.js.erb').cleanpath
22
+ self.driver_path = self.tmp_dir + 'rjs_driver.js'
23
+
24
+ # The user-supplied config parameters, to be merged with the default params.
25
+ # This file must contain a single JavaScript object.
26
+ self.user_config_file = Pathname.new(app.paths["config"].first)+'requirejs.yml'
27
+ if self.user_config_file.exist?
28
+ self.user_config = YAML.load(self.user_config_file.read)
29
+ else
30
+ self.user_config = {}
31
+ end
32
+
33
+ self.run_config = {
34
+ "baseUrl" => "/assets",
35
+ "modules" => [ { name: 'application' } ]
36
+ }
37
+ self.run_config.merge!(self.user_config)
38
+ self.run_config_json = self.run_config.to_json
39
+
40
+ self.build_config = self.run_config.merge "baseUrl" => source_dir.to_s
41
+ self.build_config.merge!(self.user_config)
42
+ end
43
+
44
+ def module_path_for(name)
45
+ self.target_dir+(name+'.js')
46
+ end
47
+
48
+ def get_binding
49
+ return binding()
50
+ end
51
+ end
52
+ end
@@ -1,6 +1,44 @@
1
+ require 'requirejs/rails/config'
2
+
3
+ require 'pathname'
4
+
1
5
  module Requirejs
2
6
  module Rails
3
7
  class Engine < ::Rails::Engine
4
- end
8
+
9
+ initializer "requirejs.tag_included_state" do |app|
10
+ ActiveSupport.on_load(:action_controller) do
11
+ ::ActionController::Base.class_eval do
12
+ attr_accessor :requirejs_included
13
+ end
14
+ end
15
+ end
16
+
17
+ initializer "requirejs.config" do |app|
18
+ config = app.config
19
+ config.requirejs = Requirejs::Rails::Config.new(app)
20
+ if config.requirejs.manifest
21
+ path = File.join(config.assets.manifest, "rjs_manifest.yml")
22
+ else
23
+ path = File.join(::Rails.public_path, config.assets.prefix, "rjs_manifest.yml")
24
+ end
25
+ config.requirejs.manifest_path = Pathname.new(path)
26
+
27
+ config.requirejs.precompile = [/require\.js$/]
28
+
29
+ if ::Rails.env == "production"
30
+ config.assets.precompile += config.requirejs.precompile
31
+ end
32
+ end
33
+
34
+ initializer "requirejs.manifest", :after => "sprockets.environment" do |app|
35
+ config = app.config
36
+ if config.requirejs.manifest_path.exist? && config.assets.digests
37
+ rjs_digests = YAML.load_file(config.requirejs.manifest_path)
38
+ config.assets.digests.merge!(rjs_digests)
39
+ end
40
+ end
41
+
42
+ end # class Engine
5
43
  end
6
44
  end
@@ -0,0 +1,40 @@
1
+ //Load the requirejs optimizer
2
+ var requirejs = require('<%= rjs_path %>'),
3
+ //Set up basic config, include config that is
4
+ //common to all the optimize() calls.
5
+ basConfig = <%= JSON.pretty_generate(build_config) %>;
6
+
7
+ // Function used to mix in baseConfig to a new config target
8
+ function mix(target) {
9
+ for (var prop in basConfig) {
10
+ if (basConfig.hasOwnProperty(prop)) {
11
+ target[prop] = basConfig[prop];
12
+ }
13
+ }
14
+ return target;
15
+ }
16
+
17
+ var module_specs = [
18
+ <% build_config['modules'].each do |m| %>
19
+ {
20
+ name: "<%= m['name'] %>",
21
+ <% if m['includes'] %>
22
+ include: [<%= m['includes'].map {|i| "'#{i}'" }.join(", ") %>],
23
+ <% end %>
24
+ out: '<%= module_path_for m['name'] %>'
25
+ },
26
+ <% end %>
27
+ ];
28
+
29
+ // Do a series of builds of individual files, using the args suggested by:
30
+ // http://requirejs.org/docs/optimization.html#onejs
31
+ //
32
+ // r.js will eventually need a nested call idiom to handle async
33
+ // builds. Anticipating that need.
34
+ var async_runner = module_specs.reduceRight(function(prev, curr) {
35
+ return function (buildReportText) {
36
+ requirejs.optimize(mix(curr), prev);
37
+ };
38
+ }, function(buildReportText) {} );
39
+
40
+ async_runner();
@@ -1,5 +1,5 @@
1
1
  module Requirejs
2
2
  module Rails
3
- VERSION = "0.0.2"
3
+ VERSION = "0.5.0"
4
4
  end
5
5
  end
@@ -1,4 +1,193 @@
1
- # desc "Explaining what the task does"
2
- # task :requirejs-rails do
3
- # # Task goes here
4
- # end
1
+ require 'requirejs/rails/builder'
2
+ require 'requirejs/rails/config'
3
+
4
+ require 'fileutils'
5
+ require 'pathname'
6
+ require 'sprockets/digest'
7
+ require 'tempfile'
8
+
9
+ require 'active_support/ordered_options'
10
+
11
+ # Prevent Sprockets::Bootstrap from making the environment immutable,
12
+ # as we need to manipulate the environment paths before the asset build.
13
+ #
14
+ # Without this, task requirejs:assets:purge_js throws an exception from
15
+ # Sprockets::Index#expire_index!, which is in response to any mutating
16
+ # method call.
17
+ #
18
+ if Rails.env == "production"
19
+ require 'sprockets/bootstrap'
20
+ module ::Sprockets
21
+ class Bootstrap
22
+ alias_method :orig_run, :run
23
+ def run(*args)
24
+ config = @app.config
25
+ saved_config_assets_digest = config.assets.digest
26
+ begin
27
+ config.assets.digest = false
28
+ orig_run(*args)
29
+ ensure
30
+ config.assets.digest = saved_config_assets_digest
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+
37
+ namespace :requirejs do
38
+
39
+ # From Rails 3 assets.rake; we have the same problem:
40
+ #
41
+ # We are currently running with no explicit bundler group
42
+ # and/or no explicit environment - we have to reinvoke rake to
43
+ # execute this task.
44
+ def invoke_or_reboot_rake_task(task)
45
+ if ENV['RAILS_GROUPS'].to_s.empty? || ENV['RAILS_ENV'].to_s.empty?
46
+ ruby_rake_task task
47
+ else
48
+ Rake::Task[task].invoke
49
+ end
50
+ end
51
+
52
+ class String
53
+ def unindent
54
+ gsub /^#{self[/\A\s*/]}/, ''
55
+ end
56
+ end
57
+
58
+ requirejs = ActiveSupport::OrderedOptions.new
59
+
60
+ task :clean => ["requirejs:setup"] do
61
+ FileUtils.remove_entry_secure(requirejs.config.source_dir, true)
62
+ FileUtils.remove_entry_secure(requirejs.driver_path, true)
63
+ end
64
+
65
+ task :setup => ["environment"] do
66
+ unless Rails.application.config.assets.enabled
67
+ warn "Cannot precompile assets if sprockets is disabled. Please set config.assets.enabled to true"
68
+ exit
69
+ end
70
+
71
+ # Ensure that action view is loaded and the appropriate
72
+ # sprockets hooks get executed
73
+ _ = ActionView::Base
74
+
75
+ requirejs.env = Rails.application.assets
76
+ # Preserve the original asset paths, as we'll be manipulating them later
77
+ requirejs.env_paths = requirejs.env.paths.dup
78
+ requirejs.config = Rails.application.config.requirejs
79
+ requirejs.builder = Requirejs::Rails::Builder.new(requirejs.config)
80
+ requirejs.manifest = {}
81
+ end
82
+
83
+ task :test_node do
84
+ begin
85
+ `node -v`
86
+ rescue Errno::ENOENT
87
+ STDERR.puts <<-EOM
88
+ Unable to find 'node' on the current path, required for precompilation
89
+ using the requirejs-ruby gem. To install node.js, see http://nodejs.org/
90
+ OS X Homebrew users can use 'brew install node'.
91
+ EOM
92
+ exit 1
93
+ end
94
+ end
95
+
96
+ namespace :precompile do
97
+ # stage1 must NOT be run in the production environment
98
+ #
99
+ # Depend on test_node first here so we'll fail early and hard if
100
+ # node isn't available.
101
+ task :stage1 => ["requirejs:test_node",
102
+ "requirejs:precompile:prepare_source",
103
+ "requirejs:precompile:generate_rjs_driver",
104
+ "requirejs:precompile:run_rjs"]
105
+ task :stage2 => ["requirejs:precompile:digestify_and_compress"]
106
+
107
+ # Copy all assets to tmp/assets
108
+ task :prepare_source => ["requirejs:setup",
109
+ "requirejs:clean",
110
+ "requirejs:assets:keep_js"] do
111
+ requirejs.config.source_dir.mkpath
112
+ requirejs.env.each_logical_path do |logical_path|
113
+ if asset = requirejs.env.find_asset(logical_path)
114
+ filename = requirejs.config.source_dir + asset.logical_path
115
+ filename.dirname.mkpath
116
+
117
+ asset.write_to(filename)
118
+ end
119
+ end
120
+ end
121
+
122
+ task :generate_rjs_driver => ["requirejs:setup"] do
123
+ requirejs.builder.generate_rjs_driver
124
+ end
125
+
126
+ task :run_rjs => ["requirejs:setup",
127
+ "requirejs:test_node"] do
128
+ requirejs.config.target_dir.mkpath
129
+
130
+ `node #{requirejs.config.driver_path}`
131
+ unless $?.success?
132
+ raise RuntimeError, "Asset compilation with node failed."
133
+ end
134
+ end
135
+
136
+ # Copy each built asset, identified by a named module in the
137
+ # build config, to its Sprockets digestified name.
138
+ task :digestify_and_compress => ["requirejs:setup"] do
139
+ requirejs.config.build_config['modules'].each do |m|
140
+ asset_name = "#{m['name']}.js"
141
+ built_asset_path = requirejs.config.target_dir + asset_name
142
+ digest_name = asset_name.sub(/\.(\w+)$/) { |ext| "-#{requirejs.builder.digest_for(built_asset_path)}#{ext}" }
143
+ digest_asset_path = requirejs.config.target_dir + digest_name
144
+ requirejs.manifest[asset_name] = digest_name
145
+ FileUtils.cp built_asset_path, digest_asset_path
146
+
147
+ # Create the compressed versions
148
+ File.open("#{built_asset_path}.gz",'wb') do |f|
149
+ zgw = Zlib::GzipWriter.new(f, Zlib::BEST_COMPRESSION)
150
+ zgw.write built_asset_path.read
151
+ zgw.close
152
+ end
153
+ FileUtils.cp "#{built_asset_path}.gz", "#{digest_asset_path}.gz"
154
+
155
+ requirejs.config.manifest_path.open('wb') do |f|
156
+ YAML.dump(requirejs.manifest,f)
157
+ end
158
+ end
159
+ end
160
+ end
161
+
162
+ desc "Precompile RequireJS-managed assets"
163
+ task :precompile do
164
+ invoke_or_reboot_rake_task "requirejs:precompile:all"
165
+ end
166
+
167
+ # We remove all .js assets from the Rails Asset Pipeline when
168
+ # precompiling, as those are handled by r.js. Conversely, r.js
169
+ # only sees .js assets. For now, this is by path convention; any
170
+ # asset path ending in "javascript". If you've got javascripts in
171
+ # your stylesheets directory, then heaven help you. You've got bigger
172
+ # problems.
173
+ namespace :assets do
174
+ # Purge all ".../javascripts" directories from the asset paths
175
+ task :purge_js => ["requirejs:setup"] do
176
+ new_paths = requirejs.env_paths.dup.delete_if { |p| p =~ /javascripts$/ && p !~ /requirejs-rails/ }
177
+ requirejs.env.clear_paths
178
+ new_paths.each { |p| requirejs.env.append_path(p) }
179
+ end
180
+
181
+ # Preserve only ".../javascripts" directories
182
+ task :keep_js => ["requirejs:setup"] do
183
+ new_paths = requirejs.env_paths.dup.keep_if { |p| p =~ /javascripts$/ }
184
+ requirejs.env.clear_paths
185
+ new_paths.each { |p| requirejs.env.append_path(p) }
186
+ end
187
+ end
188
+ end
189
+
190
+ task "assets:precompile:primary" => ["requirejs:precompile:stage2",
191
+ "requirejs:assets:purge_js"]
192
+ task "assets:precompile:nondigest" => ["requirejs:assets:purge_js"]
193
+ task "assets:precompile" => ["requirejs:precompile:stage1"]
@@ -22,5 +22,6 @@ Gem::Specification.new do |s|
22
22
  s.add_development_dependency "rails", "~> 3.1.1"
23
23
  s.add_development_dependency "sqlite3"
24
24
 
25
+ s.requirements << "node.js is required for 'rake assets:precompile', used to run the r.js build"
25
26
  s.requirements << "If needed, jQuery should be v1.7 or greater (jquery-rails >= 1.0.17)."
26
27
  end
File without changes
@@ -16,3 +16,32 @@ class RequirejsRailsTest < ActiveSupport::TestCase
16
16
  assert_equal "1.0.2", context.eval("require.version")
17
17
  end
18
18
  end
19
+
20
+ class RequirejsHelperTest < ActionView::TestCase
21
+
22
+ def setup
23
+ controller.requirejs_included = false
24
+ end
25
+
26
+ def wrap(tag)
27
+ "<html><head>#{tag}</head></html>"
28
+ end
29
+
30
+ test "requirejs_include_tag" do
31
+ render :text => wrap(requirejs_include_tag)
32
+ assert_select "script:first-of-type", :text => /var require =/
33
+ assert_select "script:last-of-type[src^=/javascripts/require.js]", :count => 1
34
+ end
35
+
36
+ test "requirejs_include_tag_with_param" do
37
+ render :text => wrap(requirejs_include_tag("application"))
38
+ assert_select "script:nth-of-type(2)[src^=/javascripts/require.js]", :count => 1
39
+ assert_select "script:last-of-type[src^=/javascripts/application.js]", :count => 1
40
+ end
41
+
42
+ test "requirejs_include_tag can appear only once" do
43
+ assert_raises Requirejs::MultipleIncludeError do
44
+ render :text => "#{requirejs_include_tag}\n#{requirejs_include_tag}"
45
+ end
46
+ end
47
+ 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.0.2
4
+ version: 0.5.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: 2011-11-22 00:00:00.000000000 Z
12
+ date: 2011-12-16 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: railties
16
- requirement: &70199933410040 !ruby/object:Gem::Requirement
16
+ requirement: &70099873431600 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: 3.1.1
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70199933410040
24
+ version_requirements: *70099873431600
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: rails
27
- requirement: &70199933409200 !ruby/object:Gem::Requirement
27
+ requirement: &70099873416040 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ~>
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: 3.1.1
33
33
  type: :development
34
34
  prerelease: false
35
- version_requirements: *70199933409200
35
+ version_requirements: *70099873416040
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: sqlite3
38
- requirement: &70199933408160 !ruby/object:Gem::Requirement
38
+ requirement: &70099873414400 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,7 +43,7 @@ dependencies:
43
43
  version: '0'
44
44
  type: :development
45
45
  prerelease: false
46
- version_requirements: *70199933408160
46
+ version_requirements: *70099873414400
47
47
  description: This gem provides RequireJS support for your Rails 3 application.
48
48
  email:
49
49
  - whitley@bangpath.org
@@ -59,9 +59,15 @@ files:
59
59
  - MIT-LICENSE
60
60
  - README.md
61
61
  - Rakefile
62
+ - app/helpers/requirejs_helper.rb
63
+ - bin/r.js
62
64
  - lib/requirejs-rails.rb
65
+ - lib/requirejs/error.rb
63
66
  - lib/requirejs/rails.rb
67
+ - lib/requirejs/rails/builder.rb
68
+ - lib/requirejs/rails/config.rb
64
69
  - lib/requirejs/rails/engine.rb
70
+ - lib/requirejs/rails/rjs_driver.js.erb
65
71
  - lib/requirejs/rails/version.rb
66
72
  - lib/tasks/requirejs-rails_tasks.rake
67
73
  - requirejs-rails.gemspec
@@ -92,6 +98,7 @@ files:
92
98
  - test/dummy/config/initializers/wrap_parameters.rb
93
99
  - test/dummy/config/locales/en.yml
94
100
  - test/dummy/config/routes.rb
101
+ - test/dummy/db/.gitkeep
95
102
  - test/dummy/lib/assets/.gitkeep
96
103
  - test/dummy/log/.gitkeep
97
104
  - test/dummy/public/404.html
@@ -115,7 +122,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
115
122
  version: '0'
116
123
  segments:
117
124
  - 0
118
- hash: 2678184901028172103
125
+ hash: 3746544673108118455
119
126
  required_rubygems_version: !ruby/object:Gem::Requirement
120
127
  none: false
121
128
  requirements:
@@ -124,8 +131,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
124
131
  version: '0'
125
132
  segments:
126
133
  - 0
127
- hash: 2678184901028172103
134
+ hash: 3746544673108118455
128
135
  requirements:
136
+ - node.js is required for 'rake assets:precompile', used to run the r.js build
129
137
  - If needed, jQuery should be v1.7 or greater (jquery-rails >= 1.0.17).
130
138
  rubyforge_project:
131
139
  rubygems_version: 1.8.10
@@ -158,6 +166,7 @@ test_files:
158
166
  - test/dummy/config/initializers/wrap_parameters.rb
159
167
  - test/dummy/config/locales/en.yml
160
168
  - test/dummy/config/routes.rb
169
+ - test/dummy/db/.gitkeep
161
170
  - test/dummy/lib/assets/.gitkeep
162
171
  - test/dummy/log/.gitkeep
163
172
  - test/dummy/public/404.html