requirejs-rails 0.0.2 → 0.5.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.
@@ -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