middleman-sprockets-cj 3.3.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (154) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +11 -0
  3. data/.rspec +2 -0
  4. data/.simplecov +9 -0
  5. data/.travis.yml +15 -0
  6. data/CHANGELOG.md +71 -0
  7. data/CONTRIBUTING.md +43 -0
  8. data/Gemfile +32 -0
  9. data/LICENSE.md +20 -0
  10. data/README.md +104 -0
  11. data/Rakefile +45 -0
  12. data/features/asset_hash-3.0.feature +105 -0
  13. data/features/asset_hash.feature +107 -0
  14. data/features/bower.feature +37 -0
  15. data/features/jst.feature +14 -0
  16. data/features/long_filenames.feature +17 -0
  17. data/features/sass_globs.feature +9 -0
  18. data/features/sass_partials.feature +36 -0
  19. data/features/sprockets.feature +129 -0
  20. data/features/sprockets_gems.feature +67 -0
  21. data/features/step_definitions/server_steps.rb +7 -0
  22. data/features/support/env.rb +18 -0
  23. data/fixtures/asset-hash-app/config.rb +7 -0
  24. data/fixtures/asset-hash-app/source/images/100px.gif +0 -0
  25. data/fixtures/asset-hash-app/source/images/100px.jpg +0 -0
  26. data/fixtures/asset-hash-app/source/images/100px.png +0 -0
  27. data/fixtures/asset-hash-app/source/index.html.erb +308 -0
  28. data/fixtures/asset-hash-app/source/javascripts/application.js +8 -0
  29. data/fixtures/asset-hash-app/source/javascripts/sprockets_base.js +5 -0
  30. data/fixtures/asset-hash-app/source/javascripts/sprockets_sub.js +3 -0
  31. data/fixtures/asset-hash-app/source/layout.erb +19 -0
  32. data/fixtures/asset-hash-app/source/other.html.erb +2 -0
  33. data/fixtures/asset-hash-app/source/partials.html.erb +2 -0
  34. data/fixtures/asset-hash-app/source/stylesheets/_partial.sass +2 -0
  35. data/fixtures/asset-hash-app/source/stylesheets/jquery-mobile.css.scss +1 -0
  36. data/fixtures/asset-hash-app/source/stylesheets/site.css.scss +4 -0
  37. data/fixtures/asset-hash-app/source/stylesheets/uses_partials.css.sass +4 -0
  38. data/fixtures/asset-hash-app/source/subdir/index.html.erb +308 -0
  39. data/fixtures/asset-hash-host-app/config.rb +6 -0
  40. data/fixtures/asset-hash-host-app/source/images/100px.gif +0 -0
  41. data/fixtures/asset-hash-host-app/source/images/100px.jpg +0 -0
  42. data/fixtures/asset-hash-host-app/source/images/100px.png +0 -0
  43. data/fixtures/asset-hash-host-app/source/index.html.erb +6 -0
  44. data/fixtures/asset-hash-host-app/source/layout.erb +17 -0
  45. data/fixtures/asset-hash-host-app/source/other.html.erb +2 -0
  46. data/fixtures/asset-hash-host-app/source/stylesheets/site.css.scss +4 -0
  47. data/fixtures/asset-hash-host-app/source/subdir/index.html.erb +6 -0
  48. data/fixtures/asset-paths-app/config.rb +4 -0
  49. data/fixtures/asset-paths-app/derp/javascripts/vendored_js.js +1 -0
  50. data/fixtures/asset-paths-app/source/javascripts/vendored_include.js +1 -0
  51. data/fixtures/bower-app/bower.json +7 -0
  52. data/fixtures/bower-app/bower_components/underscore/bower.json +8 -0
  53. data/fixtures/bower-app/bower_components/underscore/underscore.js +1343 -0
  54. data/fixtures/bower-app/config.rb +3 -0
  55. data/fixtures/bower-app/source/javascripts/application.js +1 -0
  56. data/fixtures/bower-individual-outputdir-app/bower.json +7 -0
  57. data/fixtures/bower-individual-outputdir-app/bower_components/underscore/bower.json +8 -0
  58. data/fixtures/bower-individual-outputdir-app/bower_components/underscore/underscore.js +1343 -0
  59. data/fixtures/bower-individual-outputdir-app/config.rb +6 -0
  60. data/fixtures/bower-individual-outputdir-app/source/javascripts/application.js +1 -0
  61. data/fixtures/bower-individual-outputdir-app/vendor/assets/components/lightbox2/.bower.json +34 -0
  62. data/fixtures/bower-individual-outputdir-app/vendor/assets/components/lightbox2/bower.json +26 -0
  63. data/fixtures/bower-individual-outputdir-app/vendor/assets/components/lightbox2/img/close.png +0 -0
  64. data/fixtures/bower-individual-outputdir-app/vendor/assets/components/lightbox2/js/lightbox.js +2 -0
  65. data/fixtures/bower-individual-outputdir-app/vendor/assets/components/lightbox2/package.json +37 -0
  66. data/fixtures/bower-json-app/config.rb +1 -0
  67. data/fixtures/bower-json-app/source/javascripts/application.js.coffee +1 -0
  68. data/fixtures/bower-json-app/source/javascripts/bower.json +5 -0
  69. data/fixtures/bower-multiple-assets-app/.bowerrc +4 -0
  70. data/fixtures/bower-multiple-assets-app/bower.json +7 -0
  71. data/fixtures/bower-multiple-assets-app/config.rb +7 -0
  72. data/fixtures/bower-multiple-assets-app/vendor/assets/components/lightbox2/.bower.json +34 -0
  73. data/fixtures/bower-multiple-assets-app/vendor/assets/components/lightbox2/bower.json +26 -0
  74. data/fixtures/bower-multiple-assets-app/vendor/assets/components/lightbox2/img/close.png +0 -0
  75. data/fixtures/bower-multiple-assets-app/vendor/assets/components/lightbox2/js/lightbox.js +2 -0
  76. data/fixtures/bower-multiple-assets-app/vendor/assets/components/lightbox2/package.json +37 -0
  77. data/fixtures/glob-app/config.rb +0 -0
  78. data/fixtures/glob-app/source/stylesheets/main.css.scss +1 -0
  79. data/fixtures/glob-app/source/stylesheets/module1/_i-am-mod.scss +3 -0
  80. data/fixtures/glob-app/source/stylesheets/module2/_derp.sass +2 -0
  81. data/fixtures/glob-app/source/stylesheets/shared/3rd-party/bootstrap.sass +2 -0
  82. data/fixtures/glob-app/source/stylesheets/shared/shared.scss +3 -0
  83. data/fixtures/jquery-mobile-app/config.rb +0 -0
  84. data/fixtures/jquery-mobile-app/source/stylesheets/base.css.scss +2 -0
  85. data/fixtures/long-filenames-app/config.rb +0 -0
  86. data/fixtures/long-filenames-app/source/images/00000000-0000-0000-0000-000000.svg +3 -0
  87. data/fixtures/long-filenames-app/source/images/00000000-0000-0000-0000-0000001.svg +3 -0
  88. data/fixtures/preview-app/config.rb +0 -0
  89. data/fixtures/preview-app/source/content.html.erb +1 -0
  90. data/fixtures/preview-app/source/layout.erb +1 -0
  91. data/fixtures/preview-app/source/stylesheets/_partial.sass +2 -0
  92. data/fixtures/preview-app/source/stylesheets/_partial2.css.sass +2 -0
  93. data/fixtures/preview-app/source/stylesheets/main.css.sass +4 -0
  94. data/fixtures/preview-app/source/stylesheets/main2.css.sass +4 -0
  95. data/fixtures/preview-app/source/stylesheets/plain.css.sass +2 -0
  96. data/fixtures/sprockets-app-debug-assets/config.rb +1 -0
  97. data/fixtures/sprockets-app-debug-assets/source/index.html.erb +8 -0
  98. data/fixtures/sprockets-app-debug-assets/source/javascripts/dependency1.js +3 -0
  99. data/fixtures/sprockets-app-debug-assets/source/javascripts/dependency2.js +1 -0
  100. data/fixtures/sprockets-app-debug-assets/source/javascripts/main.js +4 -0
  101. data/fixtures/sprockets-app-debug-assets/source/stylesheets/app.css.scss +4 -0
  102. data/fixtures/sprockets-app-debug-assets/source/stylesheets/dependency1.css +0 -0
  103. data/fixtures/sprockets-app-debug-assets/source/stylesheets/dependency2.css.scss +0 -0
  104. data/fixtures/sprockets-app/config.rb +7 -0
  105. data/fixtures/sprockets-app/source/index.html.erb +6 -0
  106. data/fixtures/sprockets-app/source/library/css/bootstrap_include.css.scss +1 -0
  107. data/fixtures/sprockets-app/source/library/css/plain.css +3 -0
  108. data/fixtures/sprockets-app/source/library/css/sprockets_base1.css.scss +1 -0
  109. data/fixtures/sprockets-app/source/library/css/sprockets_base2.css.scss +1 -0
  110. data/fixtures/sprockets-app/source/library/css/sprockets_sub.css.scss +1 -0
  111. data/fixtures/sprockets-app/source/library/js/jquery_include.js +1 -0
  112. data/fixtures/sprockets-app/source/library/js/plain.js +3 -0
  113. data/fixtures/sprockets-app/source/library/js/sprockets_base.js +5 -0
  114. data/fixtures/sprockets-app/source/library/js/sprockets_sub.js +3 -0
  115. data/fixtures/sprockets-app/source/library/js/vendored_include.js +1 -0
  116. data/fixtures/sprockets-app/vendor/assets/javascripts/coffee.js.coffee +2 -0
  117. data/fixtures/sprockets-app/vendor/assets/javascripts/vendored_js.js +1 -0
  118. data/fixtures/sprockets-app/vendor/assets/stylesheets/vendored.css.scss +4 -0
  119. data/fixtures/sprockets-app2/config.rb +0 -0
  120. data/fixtures/sprockets-app2/data/test.yml +4 -0
  121. data/fixtures/sprockets-app2/data/test2.json +4 -0
  122. data/fixtures/sprockets-app2/source/javascripts/_templates/test.jst.ejs +1 -0
  123. data/fixtures/sprockets-app2/source/javascripts/_templates/test2.jst.eco +1 -0
  124. data/fixtures/sprockets-app2/source/javascripts/asset_path.js.erb +3 -0
  125. data/fixtures/sprockets-app2/source/javascripts/multiple_engines.js.coffee.erb +1 -0
  126. data/fixtures/sprockets-app2/source/javascripts/sprockets_base.js +5 -0
  127. data/fixtures/sprockets-app2/source/javascripts/sprockets_sub.js +3 -0
  128. data/fixtures/sprockets-app2/source/javascripts/templates.js +1 -0
  129. data/fixtures/sprockets-app2/source/stylesheets/sprockets_base1.css.scss +1 -0
  130. data/fixtures/sprockets-app2/source/stylesheets/sprockets_base2.css.scss +1 -0
  131. data/fixtures/sprockets-app2/source/stylesheets/sprockets_sub.css.scss +1 -0
  132. data/fixtures/sprockets-images-app/config.rb +1 -0
  133. data/fixtures/sprockets-images-app/source/index.html.erb +10 -0
  134. data/fixtures/sprockets-images-app/source/library/images/cat.jpg +0 -0
  135. data/fixtures/sprockets-images-app/vendor/assets/images/cat-2.jpg +0 -0
  136. data/lib/middleman-sprockets.rb +6 -0
  137. data/lib/middleman-sprockets/asset.rb +185 -0
  138. data/lib/middleman-sprockets/asset_list.rb +41 -0
  139. data/lib/middleman-sprockets/asset_tag_helpers.rb +54 -0
  140. data/lib/middleman-sprockets/config_only_environment.rb +50 -0
  141. data/lib/middleman-sprockets/environment.rb +228 -0
  142. data/lib/middleman-sprockets/extension.rb +145 -0
  143. data/lib/middleman-sprockets/imported_asset.rb +57 -0
  144. data/lib/middleman-sprockets/pathname_extensions.rb +10 -0
  145. data/lib/middleman-sprockets/sass_function_hack.rb +9 -0
  146. data/lib/middleman-sprockets/version.rb +5 -0
  147. data/middleman-sprockets.gemspec +22 -0
  148. data/spec/asset_list_spec.rb +38 -0
  149. data/spec/asset_spec.rb +116 -0
  150. data/spec/imported_asset_spec.rb +72 -0
  151. data/spec/spec_helper.rb +16 -0
  152. data/spec/support/aruba.rb +18 -0
  153. data/spec/support/rspec.rb +17 -0
  154. metadata +257 -0
@@ -0,0 +1 @@
1
+ //= require "vendored_js"
@@ -0,0 +1,2 @@
1
+ foo = ->
2
+ console.log "bar"
@@ -0,0 +1 @@
1
+ var vendored_js_included = true;
@@ -0,0 +1,4 @@
1
+ $color: brown;
2
+ body {
3
+ background: $color;
4
+ }
File without changes
@@ -0,0 +1,4 @@
1
+ -
2
+ title: "One"
3
+ -
4
+ title: "Two"
@@ -0,0 +1,4 @@
1
+ [
2
+ { "title": "One" },
3
+ { "title": "Two" }
4
+ ]
@@ -0,0 +1,3 @@
1
+ //= require_self
2
+
3
+ templatesURL = "<%= asset_path(:js, :templates) %>";
@@ -0,0 +1 @@
1
+ alert "Hello <%= data.test[0].title %>"
@@ -0,0 +1,5 @@
1
+ //= require "sprockets_sub"
2
+
3
+ function base() {
4
+
5
+ }
@@ -0,0 +1,3 @@
1
+ function sprockets_sub_function() {
2
+
3
+ }
@@ -0,0 +1 @@
1
+ //= require_tree "./_templates"
@@ -0,0 +1 @@
1
+ //= require "sprockets_sub"
@@ -0,0 +1 @@
1
+ @import "sprockets_sub";
@@ -0,0 +1 @@
1
+ hello { world: "hi"; }
@@ -0,0 +1 @@
1
+ set :images_dir, "library/images"
@@ -0,0 +1,10 @@
1
+ <!doctype html>
2
+ <html>
3
+ <head>
4
+ <%= javascript_include_tag :plain, :data => { :name => "plain" } %>
5
+ </head>
6
+ <body>
7
+ <%= image_tag('cat.jpg') %>
8
+ <%= image_tag('cat-2.jpg') %>
9
+ </body>
10
+ </html>
@@ -0,0 +1,6 @@
1
+ require "middleman-core"
2
+
3
+ Middleman::Extensions.register(:sprockets) do
4
+ require "middleman-sprockets/extension"
5
+ Middleman::SprocketsExtension
6
+ end
@@ -0,0 +1,185 @@
1
+ # encoding: utf-8
2
+ module Middleman
3
+ module Sprockets
4
+ # Asset
5
+ class Asset
6
+
7
+ private
8
+
9
+ attr_reader :relative_source_path, :base_name, :destination_directory, :source_directory
10
+
11
+ public
12
+
13
+ attr_reader :source_path
14
+
15
+ # Create instance
16
+ #
17
+ # @param [Pathname] logical_path
18
+ # The logical path to the asset given in config.rb
19
+ #
20
+ # @param [proc] output_dir
21
+ # An individual output directory for that particular asset
22
+ def initialize(source_path, options)
23
+ source_directory = options.fetch(:source_directory, nil)
24
+
25
+ fail ArgumentError, 'Missing argument source_directory' unless source_directory
26
+
27
+ @source_directory = source_directory
28
+
29
+ @source_path = Pathname.new(source_path)
30
+ @relative_source_path = @source_path.relative_path_from(Pathname.new(source_directory))
31
+ @base_name = @source_path.basename
32
+ @import_it = false
33
+ end
34
+
35
+ # Should the asset imported?
36
+ #
37
+ # @return [true, false]
38
+ # Is true if it should be imported
39
+ def import?
40
+ valid? && (in_trusted_source_directory? || import_it?)
41
+ end
42
+
43
+ # Check on file type
44
+ #
45
+ # @return [true, false]
46
+ # Is true if has type
47
+ def has_type?(t)
48
+ type == t
49
+ end
50
+
51
+ # Path where the asset should be stored
52
+ #
53
+ # @return [Pathname]
54
+ # Returns `destination_path` if set, otherwise build result: destination_directory + relative_source_path
55
+ #
56
+ # @raise [::Sprockets::FileNotFound]
57
+ # Raise error if destination_directory was not set previously from outside
58
+ def destination_path
59
+ return @destination_path if @destination_path
60
+
61
+ fail ::Sprockets::FileNotFound, "Couldn't find an appropriate output directory for '#{destination_directory}' - halting because it was explicitly requested via 'import_asset'" unless destination_directory
62
+
63
+ destination_directory + relative_source_path
64
+ end
65
+
66
+ # Sets the destination_path
67
+ #
68
+ # @param [String,Pathname] path
69
+ # The output path for asset as string or pathname. It will be converted
70
+ # to `Pathname`.
71
+ def destination_path=(path)
72
+ @destination_path = Pathname.new path
73
+ end
74
+
75
+ # Set destination directory
76
+ #
77
+ # @param [String] path
78
+ # The path to the destination directory
79
+ #
80
+ # @return [Pathname]
81
+ # The path as pathname
82
+ def destination_directory=(path)
83
+ @destination_directory = Pathname.new path
84
+ end
85
+
86
+ # Check if given path matches source_path
87
+ #
88
+ # @param [String] path
89
+ # The path to be checked
90
+ # @return [true, false]
91
+ # The result of check
92
+ def match?(path)
93
+ source_path == Pathname.new(path)
94
+ end
95
+
96
+ # Tell asset that it is importable
97
+ def import_it
98
+ @import_it = true # single =
99
+ end
100
+
101
+ private
102
+
103
+ def in_trusted_source_directory?
104
+ is_in_images_directory? || is_in_fonts_directory?
105
+ end
106
+
107
+ def type
108
+ if is_in_images_directory? or is_image?
109
+ :image
110
+ elsif is_in_scripts_directory? or is_script?
111
+ :script
112
+ elsif is_in_stylesheets_directory? or is_stylesheet?
113
+ :stylesheet
114
+ elsif is_in_fonts_directory? or is_font?
115
+ :font
116
+ else
117
+ :unknown
118
+ end
119
+ end
120
+
121
+ def file?
122
+ source_path.file?
123
+ end
124
+
125
+ def partial?
126
+ base_name.start_with? '_'
127
+ end
128
+
129
+ # Is it a valid asset
130
+ # @return [true, false]
131
+ # If the asset is valid return true
132
+ def valid?
133
+ file? && !partial?
134
+ end
135
+
136
+ def import_it?
137
+ @import_it == true # double =
138
+ end
139
+
140
+ def has_extname?(*exts)
141
+ exts.any? { |e| extname == e }
142
+ end
143
+
144
+ def extname
145
+ source_path.extname
146
+ end
147
+
148
+ def has_real_path?(path)
149
+ real_path == path
150
+ end
151
+
152
+ def is_in_images_directory?
153
+ source_directory.end_with?('images', 'img')
154
+ end
155
+
156
+ def is_in_fonts_directory?
157
+ source_directory.end_with?('fonts')
158
+ end
159
+
160
+ def is_in_scripts_directory?
161
+ source_directory.end_with?('javascripts', 'js')
162
+ end
163
+
164
+ def is_in_stylesheets_directory?
165
+ source_directory.end_with?('stylesheets', 'css')
166
+ end
167
+
168
+ def is_image?
169
+ has_extname?('.gif', '.png', '.jpg', '.jpeg', '.svg', '.svg.gz')
170
+ end
171
+
172
+ def is_stylesheet?
173
+ has_extname?('.css', '.sass', '.scss', '.styl', '.less')
174
+ end
175
+
176
+ def is_font?
177
+ has_extname?('.ttf', '.woff', '.eot', '.otf')
178
+ end
179
+
180
+ def is_script?
181
+ has_extname?('.js', '.coffee')
182
+ end
183
+ end
184
+ end
185
+ end
@@ -0,0 +1,41 @@
1
+ # encoding: utf-8
2
+ module Middleman
3
+ module Sprockets
4
+ class AssetList
5
+ private
6
+
7
+ attr_reader :assets
8
+
9
+ public
10
+
11
+ def initialize(assets = [])
12
+ @assets = Array(assets)
13
+ end
14
+
15
+ # Find candidate in list
16
+ #
17
+ # @param [#source_path] candidate
18
+ # The candidate to search for
19
+ #
20
+ # @yield
21
+ # This blocks gets the candidate found
22
+ def lookup(candidate, &block)
23
+ found_asset = assets.find { |a| a.match? candidate.source_path }
24
+
25
+ block.call(candidate, found_asset) if block_given? && found_asset
26
+
27
+ found_asset
28
+ end
29
+
30
+ # Append asset to list
31
+ #
32
+ # @param [Asset]
33
+ # The asset to be appended
34
+ def add(asset)
35
+ assets << asset
36
+ end
37
+ alias_method :<<, :add
38
+
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,54 @@
1
+ module Middleman
2
+ module Sprockets
3
+ module AssetTagHelpers
4
+
5
+ # extend padrinos javascript_include_tag with debug functionality
6
+ # splits up script dependencies in individual files when
7
+ # configuration variable :debug_assets is set to true
8
+ def javascript_include_tag(*sources)
9
+ if sprockets.debug_assets
10
+ options = sources.extract_options!.symbolize_keys
11
+ sources.map do |source|
12
+ super(dependencies_paths('.js', source), options)
13
+ end.join("").gsub("body=1.js", "body=1")
14
+ else
15
+ super
16
+ end
17
+ end
18
+
19
+ # extend padrinos stylesheet_link_tag with debug functionality
20
+ # splits up stylesheets dependencies in individual files when
21
+ # configuration variable :debug_assets is set to true
22
+ def stylesheet_link_tag(*sources)
23
+ if sprockets.debug_assets
24
+ options = sources.extract_options!.symbolize_keys
25
+ sources.map do |source|
26
+ super(dependencies_paths('.css', source), options)
27
+ end.join("").gsub("body=1.css", "body=1")
28
+ else
29
+ super
30
+ end
31
+ end
32
+
33
+ private
34
+
35
+ # Find the paths for all the dependencies of a given source file.
36
+ def dependencies_paths(extension, source)
37
+ source_file_name = source.to_s
38
+
39
+ if source_file_name.start_with?('//', 'http')
40
+ # Don't touch external sources
41
+ source_file_name
42
+ else
43
+ source_file_name << extension unless source_file_name.end_with?(extension)
44
+
45
+ dependencies_paths = sprockets[source_file_name].to_a.map do |dependency|
46
+ # if sprockets sees "?body=1" it only gives back the body
47
+ # of the script without the dependencies included
48
+ dependency.logical_path + "?body=1"
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,50 @@
1
+ module Middleman
2
+ module Sprockets
3
+ # A fake Sprockets environment that just exposes the
4
+ # waits to create the environment until asked, but can still
5
+ # service most of the interesting configuration methods. This
6
+ # allows sprockets to be configured any time in config.rb, rather
7
+ # than having to use an after_configuration block.
8
+ class ConfigOnlyEnvironment
9
+ attr_reader :imported_assets
10
+ attr_reader :appended_paths
11
+ attr_reader :prepended_paths
12
+
13
+ def initialize(options={})
14
+ @imported_assets = []
15
+ @appended_paths = []
16
+ @prepended_paths = []
17
+ end
18
+
19
+ def method_missing?(method)
20
+ raise NoMethodError, "The Sprockets environment is not ready yet, so you can't call #{method} on it. If you need to call this method do it in a 'ready' block."
21
+ end
22
+
23
+ def apply_to_environment(environment)
24
+ @imported_assets.each do |(path, directory)|
25
+ environment.import_asset path, &directory
26
+ end
27
+
28
+ @appended_paths.each do |path|
29
+ environment.append_path path
30
+ end
31
+
32
+ @prepended_paths.each do |path|
33
+ environment.prepend_path path
34
+ end
35
+ end
36
+
37
+ def import_asset(asset_logical_path, &output_directory)
38
+ @imported_assets << [asset_logical_path, output_directory]
39
+ end
40
+
41
+ def append_path(path)
42
+ @appended_paths << path
43
+ end
44
+
45
+ def prepend_path(path)
46
+ @prepended_paths << path
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,228 @@
1
+ module Middleman
2
+ module Sprockets
3
+ # Generic Middleman Sprockets env
4
+ class Environment < ::Sprockets::Environment
5
+ # Whether or not we should debug assets by splitting them all out into individual includes
6
+ attr_reader :debug_assets
7
+
8
+ # A list of Sprockets logical paths for assets that should be brought into the
9
+ # Middleman application and built.
10
+ attr_reader :imported_assets
11
+
12
+ # The current path, useful when inside helper methods
13
+ attr_reader :last_request_path
14
+
15
+ # Setup
16
+ def initialize(app, options={})
17
+ @imported_assets = []
18
+ @app = app
19
+ @debug_assets = options.fetch(:debug_assets, false)
20
+
21
+ super app.source_dir
22
+
23
+ # By default, sprockets has no cache! Give it an in-memory one using a Hash
24
+ # There is also a Sprockets::Cache::FileStore option, but it is fraught with cache-invalidation
25
+ # peril, so we choose not to use it.
26
+ @cache = {}
27
+
28
+ enhance_context_class!
29
+
30
+ # Remove compressors, we handle these with middleware
31
+ unregister_bundle_processor 'application/javascript', :js_compressor
32
+ unregister_bundle_processor 'text/css', :css_compressor
33
+
34
+ # configure search paths
35
+ append_path app.config[:js_dir]
36
+ append_path app.config[:css_dir]
37
+ append_path app.config[:images_dir]
38
+ append_path app.config[:fonts_dir]
39
+
40
+ if app.config.respond_to?(:bower_dir)
41
+ warn ":bower_dir is deprecated. Call sprockets.append_path from a 'ready' block instead."
42
+ append_path app.config[:bower_dir]
43
+ end
44
+
45
+ # add custom assets paths to the scope
46
+ app.config[:js_assets_paths].each do |p|
47
+ warn ":js_assets_paths is deprecated. Call sprockets.append_path from a 'ready' block instead."
48
+ append_path p
49
+ end if app.config.respond_to?(:js_assets_paths)
50
+
51
+ # Stylus support
52
+ if defined?(::Stylus)
53
+ require 'stylus/sprockets'
54
+ ::Stylus.setup(self, app.config[:styl])
55
+ end
56
+ end
57
+
58
+ # Add our own customizations to the Sprockets context class
59
+ def enhance_context_class!
60
+ app = @app
61
+ env = self
62
+
63
+ # Make the app context available to Sprockets
64
+ context_class.send(:define_method, :app) { app }
65
+ context_class.send(:define_method, :env) { env }
66
+
67
+ context_class.class_eval do
68
+ def asset_path(path, options={})
69
+ # Handle people calling with the Middleman/Padrino asset path signature
70
+ if path.is_a?(::Symbol) && !options.is_a?(::Hash)
71
+ kind = path
72
+ path = options
73
+ else
74
+
75
+ kind = case options[:type]
76
+ when :image then :images
77
+ when :font then :fonts
78
+ when :javascript then :js
79
+ when :stylesheet then :css
80
+ else options[:type]
81
+ end
82
+ end
83
+
84
+ # If Middleman v4, we don't have a global for current path, so pass it in.
85
+ if self.env.last_request_path
86
+ app.asset_path(kind, path, {
87
+ :current_resource => app.sitemap.find_resource_by_destination_path(
88
+ self.env.last_request_path
89
+ )
90
+ })
91
+ else
92
+ app.asset_path(kind, path)
93
+ end
94
+ end
95
+
96
+ # These helpers are already defined in later versions of Sprockets, but we define
97
+ # them ourself to help older versions and to provide extra options that Sass wants.
98
+
99
+ # Expand logical image asset path.
100
+ def image_path(path, options={})
101
+ asset_path(path, :type => :image)
102
+ end
103
+
104
+ # Expand logical font asset path.
105
+ def font_path(path, options={})
106
+ # Knock .fonts off the end, because Middleman < 3.1 doesn't handle fonts
107
+ # in asset_path
108
+ asset_path(path, :type => :font).sub(/\.fonts$/, '')
109
+ end
110
+
111
+ # Expand logical javascript asset path.
112
+ def javascript_path(path, options={})
113
+ asset_path(path, :type => :javascript)
114
+ end
115
+
116
+ # Expand logical stylesheet asset path.
117
+ def stylesheet_path(path, options={})
118
+ asset_path(path, :type => :stylesheet)
119
+ end
120
+
121
+ def method_missing(*args)
122
+ name = args.first
123
+ if app.respond_to?(name)
124
+ app.send(*args)
125
+ else
126
+ super
127
+ end
128
+ end
129
+
130
+ # Needed so that method_missing makes sense
131
+ def respond_to?(method, include_private = false)
132
+ super || app.respond_to?(method, include_private)
133
+ end
134
+ end
135
+ end
136
+ private :enhance_context_class!
137
+
138
+ # Override Sprockets' default digest function to *not*
139
+ # change depending on the exact Sprockets version. It still takes
140
+ # into account "version" which is a user-suppliable version
141
+ # number that can be used to force assets to have a new
142
+ # hash.
143
+ def digest
144
+ @digest ||= Digest::SHA1.new.update(version.to_s)
145
+ @digest.dup
146
+ end
147
+
148
+ # Strip our custom 8-char hex/sha
149
+ def path_fingerprint(path)
150
+ path[/-([0-9a-f]{8})\.[^.]+$/, 1]
151
+ end
152
+
153
+ # Invalidate sitemap when users mess with the sprockets load paths
154
+ def append_path(path)
155
+ @app.sitemap.rebuild_resource_list!(:sprockets_paths)
156
+
157
+ super
158
+ end
159
+
160
+ def prepend_path(path)
161
+ @app.sitemap.rebuild_resource_list!(:sprockets_paths)
162
+
163
+ super
164
+ end
165
+
166
+ def clear_paths
167
+ @app.sitemap.rebuild_resource_list!(:sprockets_paths)
168
+ super
169
+ end
170
+
171
+ def css_exception_response(exception)
172
+ raise exception if @app.build?
173
+ super
174
+ end
175
+
176
+ def javascript_exception_response(exception)
177
+ raise exception if @app.build?
178
+ super
179
+ end
180
+
181
+ def call(env)
182
+ # Set the app current path based on the full URL so that helpers work
183
+ request_path = URI.decode(File.join(env['SCRIPT_NAME'], env['PATH_INFO']))
184
+ if request_path.respond_to? :force_encoding
185
+ request_path.force_encoding('UTF-8')
186
+ end
187
+ resource = @app.sitemap.find_resource_by_destination_path(request_path)
188
+
189
+ if !resource && !debug_assets
190
+ response = ::Rack::Response.new
191
+ response.status = 404
192
+ response.write """<html><body><h1>File Not Found</h1><p>#{request_path}</p>
193
+ <p>If this is an an asset from a gem, add <tt>sprockets.import_asset '#{File.basename(request_path)}'</tt>
194
+ to your <tt>config.rb</tt>.</body>"""
195
+ return response.finish
196
+ end
197
+
198
+ if @app.respond_to?(:current_path=)
199
+ @app.current_path = request_path
200
+ else
201
+ @last_request_path = request_path
202
+ end
203
+
204
+ # Fix https://github.com/sstephenson/sprockets/issues/533
205
+ if resource && File.basename(resource.path) == 'bower.json'
206
+ file = ::Rack::File.new nil
207
+ file.path = resource.source_file
208
+ response = file.serving({})
209
+ response[1]['Content-Type'] = resource.content_type
210
+ return response
211
+ end
212
+
213
+ super
214
+ end
215
+
216
+ # Tell Middleman to build this asset, referenced as a logical path.
217
+ def import_asset(asset_logical_path, &determine_output_dir)
218
+ args = []
219
+ args << asset_logical_path
220
+ args << determine_output_dir if block_given?
221
+
222
+ imported_assets << ImportedAsset.new(*args)
223
+
224
+ @app.sitemap.rebuild_resource_list!(:sprockets_import_asset)
225
+ end
226
+ end
227
+ end
228
+ end