middleman-sprockets 4.0.0.beta.1 → 4.0.0.rc.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +2 -3
  3. data/Gemfile +15 -16
  4. data/README.md +0 -58
  5. data/Rakefile +1 -16
  6. data/features/asset_hash.feature +5 -6
  7. data/features/bower.feature +6 -6
  8. data/features/sprockets.feature +13 -65
  9. data/features/sprockets_gems.feature +7 -26
  10. data/features/step_definitions/server_steps.rb +0 -4
  11. data/fixtures/asset-paths-app/config.rb +1 -4
  12. data/fixtures/bower-app/config.rb +0 -2
  13. data/fixtures/bower-app/source/javascripts/application.js +1 -1
  14. data/fixtures/bower-app/source/javascripts/import.js +1 -0
  15. data/fixtures/bower-individual-outputdir-app/config.rb +0 -4
  16. data/fixtures/bower-individual-outputdir-app/source/javascripts/application.js +3 -0
  17. data/fixtures/bower-multiple-assets-app/config.rb +1 -7
  18. data/fixtures/{sprockets-app-debug-assets/source/stylesheets/dependency1.css → bower-multiple-assets-app/source/index.html} +0 -0
  19. data/fixtures/bower-multiple-assets-app/source/javascripts/core.js +2 -0
  20. data/fixtures/jquery-mobile-app/source/javascripts/app.js +1 -0
  21. data/fixtures/sprockets-app/config.rb +0 -5
  22. data/fixtures/sprockets-app/source/library/css/bootstrap_include.css.scss +1 -1
  23. data/fixtures/sprockets-app/source/library/css/plain.css +2 -0
  24. data/fixtures/sprockets-app/source/library/css/sprockets_base2.css.scss +1 -1
  25. data/fixtures/sprockets-app/source/library/js/jquery_include.js +1 -1
  26. data/fixtures/sprockets-app/source/library/js/plain.js +3 -0
  27. data/fixtures/sprockets-app2/source/stylesheets/sprockets_base2.css.scss +1 -1
  28. data/fixtures/sprockets-imported-asset-path-conflicts-app/config.rb +1 -1
  29. data/fixtures/sprockets-imported-assets-match-multiple-paths-app/config.rb +1 -1
  30. data/fixtures/sprockets-multiple-extensions-app/config.rb +0 -3
  31. data/fixtures/sprockets-multiple-extensions-app/source/stylesheets/app.css.scss +3 -0
  32. data/fixtures/sprockets-svg-font-app/config.rb +0 -4
  33. data/fixtures/sprockets-svg-font-app/source/stylesheets/app.css.scss +4 -0
  34. data/lib/middleman-sprockets.rb +1 -6
  35. data/lib/middleman-sprockets/extension.rb +197 -113
  36. data/lib/middleman-sprockets/version.rb +1 -1
  37. data/middleman-sprockets.gemspec +2 -4
  38. metadata +29 -74
  39. data/Gemfile-Sprockets3 +0 -36
  40. data/Gemfile-v3 +0 -36
  41. data/features/asset_hash-3.0.feature +0 -105
  42. data/fixtures/sprockets-app-debug-assets/config.rb +0 -1
  43. data/fixtures/sprockets-app-debug-assets/source/index.html.erb +0 -8
  44. data/fixtures/sprockets-app-debug-assets/source/javascripts/dependency1.js +0 -3
  45. data/fixtures/sprockets-app-debug-assets/source/javascripts/dependency2.js +0 -1
  46. data/fixtures/sprockets-app-debug-assets/source/javascripts/main.js +0 -4
  47. data/fixtures/sprockets-app-debug-assets/source/stylesheets/app.css.scss +0 -4
  48. data/fixtures/sprockets-app-debug-assets/source/stylesheets/dependency2.css.scss +0 -0
  49. data/lib/middleman-sprockets/asset.rb +0 -142
  50. data/lib/middleman-sprockets/asset_tag_helpers.rb +0 -54
  51. data/lib/middleman-sprockets/config_only_environment.rb +0 -50
  52. data/lib/middleman-sprockets/environment.rb +0 -293
  53. data/lib/middleman-sprockets/imported_asset.rb +0 -30
  54. data/lib/middleman-sprockets/sass_function_hack.rb +0 -9
  55. data/lib/middleman-sprockets/sass_utils.rb +0 -14
  56. data/spec/asset_spec.rb +0 -118
  57. data/spec/imported_asset_spec.rb +0 -42
@@ -1 +1,4 @@
1
+ //= link "underscore/underscore.js"
2
+ //= link "lightbox2/img/close.png"
3
+ //= link "lightbox2/js/lightbox.js"
1
4
  //= require underscore/underscore
@@ -1,7 +1 @@
1
- set :css_dir, 'stylesheets'
2
- set :js_dir, 'javascripts'
3
- set :images_dir, 'images'
4
-
5
- sprockets.append_path File.join(root, 'vendor/assets/components')
6
- sprockets.import_asset 'lightbox2/img/close.png'
7
- sprockets.import_asset 'lightbox2/js/lightbox.js'
1
+ sprockets.append_path File.join(root, 'vendor/assets/components')
@@ -0,0 +1,2 @@
1
+ //= link "lightbox2/img/close.png"
2
+ //= link "lightbox2/js/lightbox.js"
@@ -0,0 +1 @@
1
+ //= link "jquery.mobile"
@@ -1,7 +1,2 @@
1
1
  set :js_dir, "library/js"
2
2
  set :css_dir, "library/css"
3
-
4
- after_configuration do
5
- sprockets.import_asset "vendored.css"
6
- sprockets.import_asset "coffee.js"
7
- end
@@ -1 +1 @@
1
- //= require "bootstrap.scss"
1
+ //= require "bootstrap.scss"
@@ -1,3 +1,5 @@
1
+ /*= link "vendored.css" */
2
+
1
3
  #helloWorld {
2
4
  color: red;
3
5
  }
@@ -1 +1 @@
1
- @import "sprockets_sub";
1
+ @import "sprockets_sub.css";
@@ -1 +1 @@
1
- //= require "jquery"
1
+ //= require "jquery"
@@ -1,3 +1,6 @@
1
+ //= link "vendored_js"
2
+ //= link "coffee"
3
+
1
4
  function hellowWorld() {
2
5
 
3
6
  }
@@ -1 +1 @@
1
- @import "sprockets_sub";
1
+ @import "sprockets_sub.css";
@@ -1,4 +1,4 @@
1
1
  set :css_dir, "assets/css"
2
2
 
3
3
  sprockets.append_path File.join(root, 'resources/assets')
4
- sprockets.import_asset "stylesheets/test"
4
+ # sprockets.import_asset "stylesheets/test"
@@ -1,4 +1,4 @@
1
1
  set :css_dir, "assets/css"
2
2
 
3
3
  sprockets.append_path File.join(root, 'vendor/assets')
4
- sprockets.import_asset "css/test"
4
+ # sprockets.import_asset "css/test"
@@ -1,4 +1 @@
1
1
  sprockets.append_path File.join(root, 'vendor/assets/components')
2
- sprockets.import_asset('font-awesome/fonts/fontawesome-webfont-bower.svg.gz')
3
- sprockets.import_asset('jquery/jquery.min.js')
4
- sprockets.import_asset('jquery/jquery.asdf.asdf.js.min.asdf')
@@ -0,0 +1,3 @@
1
+ //= link "font-awesome/fonts/fontawesome-webfont-bower.svg.gz"
2
+ //= link "jquery/jquery.min.js"
3
+ //= link "jquery/jquery.asdf.asdf.js.min.asdf"
@@ -1,5 +1 @@
1
1
  sprockets.append_path File.join(root, 'vendor/assets/components')
2
- sprockets.import_asset('blub/images/drawing-bower.svg')
3
- sprockets.import_asset('font-awesome/fonts/fontawesome-webfont-bower.svg')
4
- sprockets.import_asset('font-awesome/fonts/fontawesome-webfont-bower.svg.gz')
5
- sprockets.import_asset('font-awesome/fonts/fontawesome-webfont-bower.ttf.gz')
@@ -0,0 +1,4 @@
1
+ //= link "blub/images/drawing-bower.svg"
2
+ //= link "font-awesome/fonts/fontawesome-webfont-bower.svg"
3
+ //= link "font-awesome/fonts/fontawesome-webfont-bower.svg.gz"
4
+ //= link "font-awesome/fonts/fontawesome-webfont-bower.ttf.gz"
@@ -1,11 +1,6 @@
1
1
  require "middleman-core"
2
2
 
3
- params = [:sprockets]
4
-
5
- # If we're in v4
6
- params << { auto_activate: :before_configuration } if Middleman::Extensions.method(:register).arity != -1
7
-
8
- Middleman::Extensions.register(*params) do
3
+ Middleman::Extensions.register(:sprockets, auto_activate: :before_configuration) do
9
4
  require "middleman-sprockets/extension"
10
5
  Middleman::SprocketsExtension
11
6
  end
@@ -1,148 +1,206 @@
1
1
  require "sprockets"
2
- require "sprockets-sass"
3
- require "middleman-sprockets/asset"
4
- require "middleman-sprockets/imported_asset"
5
- require "middleman-sprockets/config_only_environment"
6
- require "middleman-sprockets/environment"
7
- require "middleman-sprockets/asset_tag_helpers"
8
-
9
- class Sprockets::Sass::SassTemplate
10
- # Get the default, global Sass options. Start with Compass's
11
- # options, if it's available.
12
- def default_sass_options
13
- if defined?(Compass) && defined?(Compass.configuration)
14
- merge_sass_options Compass.configuration.to_sass_engine_options.dup, Sprockets::Sass.options
15
- else
16
- Sprockets::Sass.options.dup
17
- end
18
- end
19
- end
20
-
21
- IS_V4 = ::Middleman::Extension.respond_to? :expose_to_config
2
+ require "middleman-core/sitemap/resource"
22
3
 
23
- # Sprockets extension
24
4
  module Middleman
25
5
  class SprocketsExtension < Extension
26
- option :debug_assets, false, 'Split up each required asset into its own script/style tag instead of combining them (development only)'
27
-
28
6
  attr_reader :environment
29
7
 
30
- if IS_V4
31
- expose_to_config sprockets: :environment
32
- expose_to_template sprockets: :environment
33
- end
34
-
35
- # This module gets mixed into both the Middleman instance and the Middleman class,
36
- # so that it's available in config.rb
37
- module SprocketsAccessor
38
- # The sprockets environment
39
- # @return [Middleman::MiddlemanSprocketsEnvironment]
40
- def sprockets
41
- extensions[:sprockets].environment
42
- end
43
- end
8
+ expose_to_config sprockets: :environment
44
9
 
45
10
  def initialize(app, options_hash={}, &block)
46
- require "middleman-sprockets/sass_function_hack"
47
- require "middleman-sprockets/sass_utils"
48
-
49
11
  super
50
12
 
51
- # Start out with a stub environment that can only be configured (paths and such)
52
- @environment = ::Middleman::Sprockets::ConfigOnlyEnvironment.new
13
+ @inline_asset_references = Set.new
53
14
 
54
- # v3
55
- app.send :include, SprocketsAccessor if !IS_V4
56
- end
15
+ @environment = ::Sprockets::Environment.new
57
16
 
58
- helpers do
59
- include SprocketsAccessor if !IS_V4
60
- include ::Middleman::Sprockets::AssetTagHelpers
17
+ app.config.define_setting :sprockets_imported_asset_path, "assets", "Where under source should imported assets be placed."
61
18
  end
62
19
 
63
20
  def after_configuration
64
- begin
65
- require 'ejs'
66
- ::Tilt.register ::Sprockets::EjsTemplate, 'ejs'
67
- rescue LoadError
68
- end
21
+ @environment.append_path((app.source_dir + app.config[:js_dir]).to_s)
22
+ @environment.append_path((app.source_dir + app.config[:css_dir]).to_s)
69
23
 
70
- begin
71
- require 'eco'
72
- ::Tilt.register ::Sprockets::EcoTemplate, 'eco'
73
- rescue LoadError
74
- end
75
-
76
- ::Tilt.register ::Sprockets::JstProcessor, 'jst'
77
-
78
- if app.respond_to?(:template_extensions)
79
- app.template_extensions :jst => :js, :eco => :js, :ejs => :js
80
- end
24
+ append_paths_from_gems
81
25
 
82
- if app.config.defines_setting?(:debug_assets) && !options.setting(:debug_assets).value_set?
83
- options[:debug_assets] = app.config[:debug_assets]
26
+ the_app = app
27
+ the_env = environment
28
+
29
+ @environment.context_class.send(:define_method, :app) { the_app }
30
+ @environment.context_class.send(:define_method, :data) { the_app.data }
31
+ @environment.context_class.send(:define_method, :env) { the_env }
32
+
33
+ @environment.context_class.class_eval do
34
+ def asset_path(path, options = {})
35
+ # Handle people calling with the Middleman/Padrino asset path signature
36
+ if path.is_a?(::Symbol) && !options.is_a?(::Hash)
37
+ kind = path
38
+ path = options
39
+ else
40
+
41
+ kind = case options[:type]
42
+ when :image then :images
43
+ when :font then :fonts
44
+ when :javascript then :js
45
+ when :stylesheet then :css
46
+ else options[:type]
47
+ end
48
+ end
49
+
50
+ if app.extensions[:sprockets].check_asset(path)
51
+ "/#{app.config[:sprockets_imported_asset_path]}/#{path}"
52
+ else
53
+ app.asset_path(kind, path)
54
+ end
55
+ end
84
56
  end
57
+ end
85
58
 
86
- config_environment = @environment
87
- debug_assets = !app.build? && options[:debug_assets]
88
- @environment = ::Middleman::Sprockets::Environment.new(app, :debug_assets => debug_assets)
89
- config_environment.apply_to_environment(@environment)
90
-
91
- append_paths_from_gems
92
- import_images_and_fonts_from_gems
59
+ def base_resource?(r)
60
+ r.class.ancestors.first == ::Middleman::Sitemap::Resource
61
+ end
93
62
 
94
- # Setup Sprockets Sass options
95
- if app.config.defines_setting?(:sass)
96
- app.config[:sass].each { |k, v| ::Sprockets::Sass.options[k] = v }
63
+ def js?(r)
64
+ begin
65
+ r.source_file.start_with?((app.source_dir + app.config[:js_dir]).to_s)
66
+ rescue
67
+ require 'pry'
68
+ binding.pry
97
69
  end
70
+ end
98
71
 
99
- # Intercept requests to /javascripts and /stylesheets and pass to sprockets
100
- our_sprockets = self.environment
72
+ def css?(r)
73
+ r.source_file.start_with?((app.source_dir + app.config[:css_dir]).to_s)
74
+ end
101
75
 
102
- [app.config[:js_dir], app.config[:css_dir], app.config[:images_dir], app.config[:fonts_dir]].each do |dir|
103
- app.map("/#{dir}") { run our_sprockets }
76
+ def check_asset(path)
77
+ if asset = environment[path]
78
+ @inline_asset_references << path
79
+ true
80
+ else
81
+ false
104
82
  end
105
83
  end
106
84
 
107
- # Add sitemap resource for every image in the sprockets load path
108
85
  def manipulate_resource_list(resources)
109
- resources_list = []
110
-
111
- environment.prune_imported_assets!
112
- environment.imported_assets.each do |imported_asset|
113
- asset = Middleman::Sprockets::Asset.new @app, imported_asset.logical_path, environment
86
+ sprockets, non_sprockets = resources.partition do |r|
87
+ base_resource?(r) && (js?(r) || css?(r))
88
+ end
114
89
 
115
- if imported_asset.output_path
116
- destination = imported_asset.output_path
90
+ non_sprockets + sprockets.reduce([]) do |sum, r|
91
+ sprockets_path = if js?(r)
92
+ r.path.sub(%r{^#{app.config[:js_dir]}\/}, '')
117
93
  else
118
- destination = @app.sitemap.extensionless_path( asset.destination_path.to_s )
94
+ r.path.sub(%r{^#{app.config[:css_dir]}\/}, '')
119
95
  end
120
96
 
121
- # next if @app.sitemap.find_resource_by_destination_path destination.to_s
97
+ sprockets_resource = generate_resource(r.path, r.source_file, sprockets_path)
98
+ sum << sprockets_resource
122
99
 
123
- resource = ::Middleman::Sitemap::Resource.new( @app.sitemap, destination.to_s, asset.source_path.to_s )
124
- resource.add_metadata options: { sprockets: { logical_path: imported_asset.logical_path }}
100
+ if sprockets_resource.respond_to?(:sprockets_asset)
101
+ sprockets_resource.sprockets_asset.links.each do |a|
102
+ asset = environment[a]
103
+ path = "#{app.config[:sprockets_imported_asset_path]}/#{asset.logical_path}"
104
+ sum << generate_resource(path, asset.filename, asset.logical_path)
105
+ end
106
+ end
125
107
 
126
- resources_list << resource
108
+ sum
109
+ end + @inline_asset_references.map do |path|
110
+ asset = environment[path]
111
+ path = "#{app.config[:sprockets_imported_asset_path]}/#{asset.logical_path}"
112
+ generate_resource(path, asset.filename, asset.logical_path)
127
113
  end
128
-
129
- resources + resources_list
130
114
  end
131
115
 
132
116
  private
133
117
 
134
- # Add any directories from gems with Rails-like paths to sprockets load path
135
- def append_paths_from_gems
136
- root_paths = rubygems_latest_specs.map(&:full_gem_path) << app.root
137
- base_paths = %w[assets app app/assets vendor vendor/assets lib lib/assets]
138
- asset_dirs = %w[javascripts js stylesheets css images img fonts]
118
+ def generate_resource(path, source_file, sprockets_path)
119
+ begin
120
+ SprocketsResource.new(app.sitemap, path, source_file, sprockets_path, environment)
121
+ rescue Exception => e
122
+ raise e if app.build?
123
+
124
+ ext = File.extname(path)
125
+ error_message = if ext == '.css'
126
+ css_exception_response(e)
127
+ elsif ext == '.js'
128
+ javascript_exception_response(e)
129
+ else
130
+ e.to_s
131
+ end
139
132
 
140
- root_paths.product(base_paths.product(asset_dirs)).each do |root, (base, asset)|
141
- path = File.join(root, base, asset)
142
- environment.append_path(path) if File.directory?(path)
133
+ ::Middleman::Sitemap::StringResource.new(app.sitemap, path, error_message)
143
134
  end
144
135
  end
145
136
 
137
+ # Returns a JavaScript response that re-throws a Ruby exception
138
+ # in the browser
139
+ def javascript_exception_response(exception)
140
+ err = "#{exception.class.name}: #{exception.message}\n (in #{exception.backtrace[0]})"
141
+ "throw Error(#{err.inspect})"
142
+ end
143
+
144
+ # Returns a CSS response that hides all elements on the page and
145
+ # displays the exception
146
+ def css_exception_response(exception)
147
+ message = "\n#{exception.class.name}: #{exception.message}"
148
+ backtrace = "\n #{exception.backtrace.first}"
149
+
150
+ <<-CSS
151
+ html {
152
+ padding: 18px 36px;
153
+ }
154
+
155
+ head {
156
+ display: block;
157
+ }
158
+
159
+ body {
160
+ margin: 0;
161
+ padding: 0;
162
+ }
163
+
164
+ body > * {
165
+ display: none !important;
166
+ }
167
+
168
+ head:after, body:before, body:after {
169
+ display: block !important;
170
+ }
171
+
172
+ head:after {
173
+ font-family: sans-serif;
174
+ font-size: large;
175
+ font-weight: bold;
176
+ content: "Error compiling CSS asset";
177
+ }
178
+
179
+ body:before, body:after {
180
+ font-family: monospace;
181
+ white-space: pre-wrap;
182
+ }
183
+
184
+ body:before {
185
+ font-weight: bold;
186
+ content: "#{escape_css_content(message)}";
187
+ }
188
+
189
+ body:after {
190
+ content: "#{escape_css_content(backtrace)}";
191
+ }
192
+ CSS
193
+ end
194
+
195
+ # Escape special characters for use inside a CSS content("...") string
196
+ def escape_css_content(content)
197
+ content.
198
+ gsub('\\', '\\\\005c ').
199
+ gsub("\n", '\\\\000a ').
200
+ gsub('"', '\\\\0022 ').
201
+ gsub('/', '\\\\002f ')
202
+ end
203
+
146
204
  # Backwards compatible means of finding all the latest gemspecs
147
205
  # available on the system
148
206
  #
@@ -157,17 +215,43 @@ module Middleman
157
215
  end
158
216
  end
159
217
 
160
- def import_images_and_fonts_from_gems
161
- valid_paths = environment.paths
162
- .reject { |p| p.start_with?(app.source_dir.to_s) }
163
- .select { |p| p.end_with?('images') || p.end_with?('fonts') }
218
+ # Add any directories from gems with Rails-like paths to sprockets load path
219
+ def append_paths_from_gems
220
+ root_paths = rubygems_latest_specs.map(&:full_gem_path) << app.root
221
+ base_paths = %w[assets app app/assets vendor vendor/assets lib lib/assets]
222
+ asset_dirs = %w[javascripts js stylesheets css images img fonts]
223
+
224
+ root_paths.product(base_paths.product(asset_dirs)).each do |root, (base, asset)|
225
+ path = File.join(root, base, asset)
226
+ environment.append_path(path) if File.directory?(path)
227
+ end
228
+ end
229
+
230
+ class SprocketsResource < ::Middleman::Sitemap::Resource
231
+ def initialize(store, path, source_file, sprockets_path, environment)
232
+ @path = path
233
+ @sprockets_path = sprockets_path
234
+ @environment = environment
235
+ @source = sprockets_asset.source
164
236
 
165
- environment.files_in_paths(valid_paths).each do |(path, load_path)|
166
- if path.file? && !path.basename.to_s.start_with?('_')
167
- logical_path = path.sub /^#{load_path}/, ''
168
- environment.imported_assets << Middleman::Sprockets::ImportedAsset.new(logical_path)
169
- end
237
+ super(store, path, source_file)
238
+ end
239
+
240
+ def template?
241
+ true
242
+ end
243
+
244
+ def render(*)
245
+ @source
246
+ end
247
+
248
+ def sprockets_asset
249
+ @environment[@sprockets_path]
250
+ end
251
+
252
+ def binary?
253
+ false
170
254
  end
171
255
  end
172
256
  end
173
- end
257
+ end