bpm 0.1.0 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (213) hide show
  1. data/.gitmodules +3 -0
  2. data/Gemfile +0 -13
  3. data/TODO.md +1 -0
  4. data/bpm.gemspec +8 -3
  5. data/lib/bpm/cli/base.rb +22 -20
  6. data/lib/bpm/generator.rb +3 -3
  7. data/lib/bpm/libgems_ext/dependency_installer.rb +4 -4
  8. data/lib/bpm/libgems_ext/installer.rb +1 -1
  9. data/lib/bpm/package.rb +13 -9
  10. data/lib/bpm/pipeline/generated_asset.rb +30 -3
  11. data/lib/bpm/pipeline/transport_processor.rb +20 -12
  12. data/lib/bpm/pipeline.rb +17 -9
  13. data/lib/bpm/project.rb +42 -10
  14. data/lib/bpm/server.rb +5 -0
  15. data/lib/bpm/version.rb +1 -1
  16. data/lib/bpm.rb +2 -0
  17. data/lib/vendored_sprockets.rb +7 -0
  18. data/spec/cli/add_spec.rb +40 -37
  19. data/spec/cli/build_spec.rb +5 -5
  20. data/spec/cli/new_spec.rb +49 -23
  21. data/spec/cli/push_spec.rb +5 -5
  22. data/spec/cli/unpack_spec.rb +14 -14
  23. data/spec/fixtures/{badrake-0.8.7.spd → badrake-0.8.7.bpkg} +0 -0
  24. data/spec/fixtures/{builder-3.0.0.spd → builder-3.0.0.bpkg} +0 -0
  25. data/spec/fixtures/{bundler-1.1.pre.spd → bundler-1.1.pre.bpkg} +0 -0
  26. data/spec/fixtures/{coffee-1.0.1.pre.spd → coffee-1.0.1.pre.bpkg} +0 -0
  27. data/spec/fixtures/{core-test-0.4.9.spd → core-test-0.4.9.bpkg} +0 -0
  28. data/spec/fixtures/{custom_generator-1.0.spd → custom_generator-1.0.bpkg} +0 -0
  29. data/spec/fixtures/custom_name/MyProject.json +4 -0
  30. data/spec/fixtures/hello_world/css/dummy.css +3 -0
  31. data/spec/fixtures/{highline-1.6.1.spd → highline-1.6.1.bpkg} +0 -0
  32. data/spec/fixtures/{ivory-0.0.1.spd → ivory-0.0.1.bpkg} +0 -0
  33. data/spec/fixtures/{jquery-1.4.3.spd → jquery-1.4.3.bpkg} +0 -0
  34. data/spec/fixtures/minitest/assets/bpm_packages.js +1 -0
  35. data/spec/fixtures/minitest/assets/bpm_styles.css +0 -0
  36. data/spec/fixtures/minitest/assets/minitest/app_package.js +1 -0
  37. data/spec/fixtures/minitest/lib/main.js +1 -0
  38. data/spec/fixtures/minitest/minitest.json +22 -0
  39. data/spec/fixtures/minitest/packages/uglyduck/lib/main.js +1 -0
  40. data/spec/fixtures/minitest/packages/uglyduck/minifier/main.js +4 -0
  41. data/spec/fixtures/minitest/packages/uglyduck/package.json +21 -0
  42. data/spec/fixtures/{optparse-1.0.1.spd → optparse-1.0.1.bpkg} +0 -0
  43. data/spec/fixtures/{rake-0.8.6.spd → rake-0.8.6.bpkg} +0 -0
  44. data/spec/fixtures/{rake-0.8.7.spd → rake-0.8.7.bpkg} +0 -0
  45. data/spec/fixtures/{spade-0.5.0.spd → spade-0.5.0.bpkg} +0 -0
  46. data/spec/fixtures/transporter/packages/transport/lib/main.js +1 -0
  47. data/spec/fixtures/transporter/packages/transport/package.json +1 -1
  48. data/spec/fixtures/transporter/packages/transport/transports/wrapper.js +5 -0
  49. data/spec/gauntlet_spec.rb +2 -2
  50. data/spec/package_spec.rb +3 -3
  51. data/spec/pipeline_spec.rb +175 -54
  52. data/spec/project_spec.rb +19 -3
  53. data/spec/support/fake_gem_server.rb +4 -4
  54. data/templates/init/project.json +3 -1
  55. data/templates/project/index.html +1 -1
  56. data/vendor/sprockets/.gitignore +7 -0
  57. data/vendor/sprockets/.travis.yml +6 -0
  58. data/vendor/sprockets/Gemfile +8 -0
  59. data/vendor/sprockets/LICENSE +20 -0
  60. data/vendor/sprockets/README.md +22 -0
  61. data/vendor/sprockets/Rakefile +8 -0
  62. data/vendor/sprockets/lib/sprockets/asset.rb +203 -0
  63. data/vendor/sprockets/lib/sprockets/asset_attributes.rb +161 -0
  64. data/vendor/sprockets/lib/sprockets/base.rb +147 -0
  65. data/vendor/sprockets/lib/sprockets/bundled_asset.rb +222 -0
  66. data/vendor/sprockets/lib/sprockets/cache/file_store.rb +41 -0
  67. data/vendor/sprockets/lib/sprockets/caching.rb +121 -0
  68. data/vendor/sprockets/lib/sprockets/charset_normalizer.rb +41 -0
  69. data/vendor/sprockets/lib/sprockets/context.rb +191 -0
  70. data/vendor/sprockets/lib/sprockets/digest.rb +73 -0
  71. data/vendor/sprockets/lib/sprockets/directive_processor.rb +380 -0
  72. data/vendor/sprockets/lib/sprockets/eco_template.rb +39 -0
  73. data/vendor/sprockets/lib/sprockets/ejs_template.rb +38 -0
  74. data/vendor/sprockets/lib/sprockets/engines.rb +92 -0
  75. data/vendor/sprockets/lib/sprockets/environment.rb +93 -0
  76. data/vendor/sprockets/lib/sprockets/errors.rb +17 -0
  77. data/vendor/sprockets/lib/sprockets/index.rb +80 -0
  78. data/vendor/sprockets/lib/sprockets/jst_processor.rb +26 -0
  79. data/vendor/sprockets/lib/sprockets/processing.rb +310 -0
  80. data/vendor/sprockets/lib/sprockets/processor.rb +32 -0
  81. data/vendor/sprockets/lib/sprockets/safety_colons.rb +28 -0
  82. data/vendor/sprockets/lib/sprockets/server.rb +270 -0
  83. data/vendor/sprockets/lib/sprockets/static_asset.rb +87 -0
  84. data/vendor/sprockets/lib/sprockets/static_compilation.rb +82 -0
  85. data/vendor/sprockets/lib/sprockets/trail.rb +122 -0
  86. data/vendor/sprockets/lib/sprockets/utils.rb +67 -0
  87. data/vendor/sprockets/lib/sprockets/version.rb +3 -0
  88. data/vendor/sprockets/lib/sprockets.rb +31 -0
  89. data/vendor/sprockets/sprockets.gemspec +30 -0
  90. data/vendor/sprockets/test/fixtures/asset/POW.png +0 -0
  91. data/vendor/sprockets/test/fixtures/asset/application.js +6 -0
  92. data/vendor/sprockets/test/fixtures/asset/bar-utf8.css +2 -0
  93. data/vendor/sprockets/test/fixtures/asset/charset.css +2 -0
  94. data/vendor/sprockets/test/fixtures/asset/circle/a.js +2 -0
  95. data/vendor/sprockets/test/fixtures/asset/circle/b.js +2 -0
  96. data/vendor/sprockets/test/fixtures/asset/circle/c.js +2 -0
  97. data/vendor/sprockets/test/fixtures/asset/compat.js +4 -0
  98. data/vendor/sprockets/test/fixtures/asset/constants.js +2 -0
  99. data/vendor/sprockets/test/fixtures/asset/constants.yml +1 -0
  100. data/vendor/sprockets/test/fixtures/asset/default_mime_type.js +1 -0
  101. data/vendor/sprockets/test/fixtures/asset/filename.js.erb +1 -0
  102. data/vendor/sprockets/test/fixtures/asset/foo-utf8.css +2 -0
  103. data/vendor/sprockets/test/fixtures/asset/included_header.js +4 -0
  104. data/vendor/sprockets/test/fixtures/asset/jquery.tmpl.min.js +1 -0
  105. data/vendor/sprockets/test/fixtures/asset/mismatch.js +1 -0
  106. data/vendor/sprockets/test/fixtures/asset/multiple.js +2 -0
  107. data/vendor/sprockets/test/fixtures/asset/multipleengine.js +1 -0
  108. data/vendor/sprockets/test/fixtures/asset/noengine.js +1 -0
  109. data/vendor/sprockets/test/fixtures/asset/noformat.coffee +1 -0
  110. data/vendor/sprockets/test/fixtures/asset/one.css +1 -0
  111. data/vendor/sprockets/test/fixtures/asset/oneengine.js +1 -0
  112. data/vendor/sprockets/test/fixtures/asset/project.css +1 -0
  113. data/vendor/sprockets/test/fixtures/asset/project.js.erb +4 -0
  114. data/vendor/sprockets/test/fixtures/asset/relative/include.js +4 -0
  115. data/vendor/sprockets/test/fixtures/asset/relative/require.js +1 -0
  116. data/vendor/sprockets/test/fixtures/asset/relative/require_outside_path.js +1 -0
  117. data/vendor/sprockets/test/fixtures/asset/require_self.css +9 -0
  118. data/vendor/sprockets/test/fixtures/asset/require_self_twice.css +8 -0
  119. data/vendor/sprockets/test/fixtures/asset/semicolons/bar.js +1 -0
  120. data/vendor/sprockets/test/fixtures/asset/semicolons/index.js +5 -0
  121. data/vendor/sprockets/test/fixtures/asset/sprite.css.erb +12 -0
  122. data/vendor/sprockets/test/fixtures/asset/tree/all/b/c/d.js +2 -0
  123. data/vendor/sprockets/test/fixtures/asset/tree/all/b/c/e.js +1 -0
  124. data/vendor/sprockets/test/fixtures/asset/tree/all/b/c.js +1 -0
  125. data/vendor/sprockets/test/fixtures/asset/tree/all/b.css +2 -0
  126. data/vendor/sprockets/test/fixtures/asset/tree/all/b.js.erb +1 -0
  127. data/vendor/sprockets/test/fixtures/asset/tree/all/d/c.js.coffee +1 -0
  128. data/vendor/sprockets/test/fixtures/asset/tree/all/d/e.js +1 -0
  129. data/vendor/sprockets/test/fixtures/asset/tree/all_with_require.js +7 -0
  130. data/vendor/sprockets/test/fixtures/asset/tree/all_with_require_directory.js +1 -0
  131. data/vendor/sprockets/test/fixtures/asset/tree/all_with_require_tree.js +2 -0
  132. data/vendor/sprockets/test/fixtures/asset/tree/directory/application.js +2 -0
  133. data/vendor/sprockets/test/fixtures/asset/tree/directory/bar.js +1 -0
  134. data/vendor/sprockets/test/fixtures/asset/tree/directory/foo.js +1 -0
  135. data/vendor/sprockets/test/fixtures/asset/tree/tree/application.js +2 -0
  136. data/vendor/sprockets/test/fixtures/asset/tree/tree/bar.js +1 -0
  137. data/vendor/sprockets/test/fixtures/asset/tree/tree/foo.js +1 -0
  138. data/vendor/sprockets/test/fixtures/asset/tree/with_logical_path/a/a.js +1 -0
  139. data/vendor/sprockets/test/fixtures/asset/tree/with_logical_path/require_tree_with_logical_path.js +1 -0
  140. data/vendor/sprockets/test/fixtures/asset/tree/without_argument/a.js +1 -0
  141. data/vendor/sprockets/test/fixtures/asset/tree/without_argument/b.js +1 -0
  142. data/vendor/sprockets/test/fixtures/asset/tree/without_argument/require_tree_without_argument.js +1 -0
  143. data/vendor/sprockets/test/fixtures/asset/two.css +1 -0
  144. data/vendor/sprockets/test/fixtures/asset/unicode.js +2 -0
  145. data/vendor/sprockets/test/fixtures/asset/unknownexts.min.js +2 -0
  146. data/vendor/sprockets/test/fixtures/asset/users.js.erb.str +4 -0
  147. data/vendor/sprockets/test/fixtures/context/POW.png +0 -0
  148. data/vendor/sprockets/test/fixtures/context/application.js.yml +3 -0
  149. data/vendor/sprockets/test/fixtures/context/bar.js +1 -0
  150. data/vendor/sprockets/test/fixtures/context/foo.js +2 -0
  151. data/vendor/sprockets/test/fixtures/context/helpers.css.erb +3 -0
  152. data/vendor/sprockets/test/fixtures/context/properties.js.erb +7 -0
  153. data/vendor/sprockets/test/fixtures/context/require_glob.js +1 -0
  154. data/vendor/sprockets/test/fixtures/context/resolve_content_type.js.erb +4 -0
  155. data/vendor/sprockets/test/fixtures/context/sprite.css.embed +3 -0
  156. data/vendor/sprockets/test/fixtures/default/application.js.coffee +4 -0
  157. data/vendor/sprockets/test/fixtures/default/coffee/foo.coffee +1 -0
  158. data/vendor/sprockets/test/fixtures/default/coffee/index.js +3 -0
  159. data/vendor/sprockets/test/fixtures/default/empty +0 -0
  160. data/vendor/sprockets/test/fixtures/default/gallery.css.erb +3 -0
  161. data/vendor/sprockets/test/fixtures/default/gallery.js +1 -0
  162. data/vendor/sprockets/test/fixtures/default/goodbye.jst.eco +1 -0
  163. data/vendor/sprockets/test/fixtures/default/hello.jst.ejs +1 -0
  164. data/vendor/sprockets/test/fixtures/default/hello.txt +1 -0
  165. data/vendor/sprockets/test/fixtures/default/interpolation.js +1 -0
  166. data/vendor/sprockets/test/fixtures/default/missing_require.js +1 -0
  167. data/vendor/sprockets/test/fixtures/default/mobile/a.js +1 -0
  168. data/vendor/sprockets/test/fixtures/default/mobile/b.js +1 -0
  169. data/vendor/sprockets/test/fixtures/default/mobile/c.css +1 -0
  170. data/vendor/sprockets/test/fixtures/default/mobile/d.css +1 -0
  171. data/vendor/sprockets/test/fixtures/default/mobile/index.css +3 -0
  172. data/vendor/sprockets/test/fixtures/default/mobile/index.js +1 -0
  173. data/vendor/sprockets/test/fixtures/default/noreturn.js +1 -0
  174. data/vendor/sprockets/test/fixtures/default/project.js.coffee.erb +2 -0
  175. data/vendor/sprockets/test/fixtures/directives/code_before_comment +3 -0
  176. data/vendor/sprockets/test/fixtures/directives/comment_without_directives +6 -0
  177. data/vendor/sprockets/test/fixtures/directives/directive_word_splitting +6 -0
  178. data/vendor/sprockets/test/fixtures/directives/directives_after_header +16 -0
  179. data/vendor/sprockets/test/fixtures/directives/double_slash +9 -0
  180. data/vendor/sprockets/test/fixtures/directives/hash +8 -0
  181. data/vendor/sprockets/test/fixtures/directives/no_header +2 -0
  182. data/vendor/sprockets/test/fixtures/directives/slash_star +10 -0
  183. data/vendor/sprockets/test/fixtures/directives/slash_star_single +4 -0
  184. data/vendor/sprockets/test/fixtures/directives/space_between_directive_word +2 -0
  185. data/vendor/sprockets/test/fixtures/directives/triple_hash +10 -0
  186. data/vendor/sprockets/test/fixtures/encoding/ascii.js +1 -0
  187. data/vendor/sprockets/test/fixtures/encoding/ascii_utf8.js +2 -0
  188. data/vendor/sprockets/test/fixtures/encoding/utf16.js +0 -0
  189. data/vendor/sprockets/test/fixtures/encoding/utf8.js +1 -0
  190. data/vendor/sprockets/test/fixtures/encoding/utf8_bom.js +1 -0
  191. data/vendor/sprockets/test/fixtures/engines/hello.alert +1 -0
  192. data/vendor/sprockets/test/fixtures/engines/moo.js.str +1 -0
  193. data/vendor/sprockets/test/fixtures/public/compiled-digest-0aa2105d29558f3eb790d411d7d8fb66.js +3 -0
  194. data/vendor/sprockets/test/fixtures/public/compiled-digest-1c41eb0cf934a0c76babe875f982f9d1.js +1 -0
  195. data/vendor/sprockets/test/fixtures/server/app/javascripts/application.js +5 -0
  196. data/vendor/sprockets/test/fixtures/server/app/javascripts/bar.js +1 -0
  197. data/vendor/sprockets/test/fixtures/server/app/javascripts/foo.js +1 -0
  198. data/vendor/sprockets/test/fixtures/server/app/javascripts/hello.txt +2 -0
  199. data/vendor/sprockets/test/fixtures/server/app/javascripts/tree.js +1 -0
  200. data/vendor/sprockets/test/fixtures/server/vendor/javascripts/missing_require.js +1 -0
  201. data/vendor/sprockets/test/fixtures/server/vendor/stylesheets/missing_require.css +1 -0
  202. data/vendor/sprockets/test/sprockets_test.rb +56 -0
  203. data/vendor/sprockets/test/test_asset.rb +593 -0
  204. data/vendor/sprockets/test/test_asset_attributes.rb +86 -0
  205. data/vendor/sprockets/test/test_caching.rb +62 -0
  206. data/vendor/sprockets/test/test_context.rb +115 -0
  207. data/vendor/sprockets/test/test_directive_processor.rb +124 -0
  208. data/vendor/sprockets/test/test_encoding.rb +65 -0
  209. data/vendor/sprockets/test/test_engines.rb +73 -0
  210. data/vendor/sprockets/test/test_environment.rb +610 -0
  211. data/vendor/sprockets/test/test_server.rb +227 -0
  212. metadata +258 -54
  213. data/spec/fixtures/transporter/packages/transport/lib/wrapper.js +0 -5
@@ -0,0 +1,39 @@
1
+ require 'tilt'
2
+
3
+ module Sprockets
4
+ # Tilt engine class for the Eco compiler. Depends on the `eco` gem.
5
+ #
6
+ # For more infomation see:
7
+ #
8
+ # https://github.com/sstephenson/ruby-eco
9
+ # https://github.com/sstephenson/eco
10
+ #
11
+ class EcoTemplate < Tilt::Template
12
+ # Eco templates always produced compiled JS. We can set Tilt's
13
+ # default mime type hint.
14
+ def self.default_mime_type
15
+ 'application/javascript'
16
+ end
17
+
18
+ # Autoload eco library. If the library isn't loaded, Tilt will produce
19
+ # a thread safetly warning. If you intend to use `.eco` files, you
20
+ # should explicitly require it.
21
+ def initialize_engine
22
+ require_template_library 'eco'
23
+ end
24
+
25
+ def prepare
26
+ end
27
+
28
+ # Compile template data with Eco compiler.
29
+ #
30
+ # Returns a JS function definition String. The result should be
31
+ # assigned to a JS variable.
32
+ #
33
+ # # => "function(...) {...}"
34
+ #
35
+ def evaluate(scope, locals, &block)
36
+ Eco.compile(data)
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,38 @@
1
+ require 'tilt'
2
+
3
+ module Sprockets
4
+ # Tilt engine class for the EJS compiler. Depends on the `ejs` gem.
5
+ #
6
+ # For more infomation see:
7
+ #
8
+ # https://github.com/sstephenson/ruby-ejs
9
+ #
10
+ class EjsTemplate < Tilt::Template
11
+ # EJS templates always produced compiled JS. We can set Tilt's
12
+ # default mime type hint.
13
+ def self.default_mime_type
14
+ 'application/javascript'
15
+ end
16
+
17
+ # Autoload ejs library. If the library isn't loaded, Tilt will produce
18
+ # a thread safetly warning. If you intend to use `.ejs` files, you
19
+ # should explicitly require it.
20
+ def initialize_engine
21
+ require_template_library 'ejs'
22
+ end
23
+
24
+ def prepare
25
+ end
26
+
27
+ # Compile template data with EJS compiler.
28
+ #
29
+ # Returns a JS function definition String. The result should be
30
+ # assigned to a JS variable.
31
+ #
32
+ # # => "function(obj){...}"
33
+ #
34
+ def evaluate(scope, locals, &block)
35
+ EJS.compile(data)
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,92 @@
1
+ require 'sprockets/eco_template'
2
+ require 'sprockets/ejs_template'
3
+ require 'sprockets/jst_processor'
4
+ require 'sprockets/utils'
5
+ require 'tilt'
6
+
7
+ module Sprockets
8
+ # `Engines` provides a global and `Environment` instance registry.
9
+ #
10
+ # An engine is a type of processor that is bound to an filename
11
+ # extension. `application.js.coffee` indicates that the
12
+ # `CoffeeScriptTemplate` engine will be ran on the file.
13
+ #
14
+ # Extensions can be stacked and will be evaulated from right to
15
+ # left. `application.js.coffee.erb` will first run `ERBTemplate`
16
+ # then `CoffeeScriptTemplate`.
17
+ #
18
+ # All `Engine`s must follow the `Tilt::Template` interface. It is
19
+ # recommended to subclass `Tilt::Template`.
20
+ #
21
+ # Its recommended that you register engine changes on your local
22
+ # `Environment` instance.
23
+ #
24
+ # environment.register_engine '.foo', FooProcessor
25
+ #
26
+ # The global registry is exposed for plugins to register themselves.
27
+ #
28
+ # Sprockets.register_engine '.sass', SassTemplate
29
+ #
30
+ module Engines
31
+ # Returns an `Array` of `Engine`s registered on the
32
+ # `Environment`. If an `ext` argument is supplied, the `Engine`
33
+ # register under that extension will be returned.
34
+ #
35
+ # environment.engines
36
+ # # => [CoffeeScriptTemplate, SassTemplate, ...]
37
+ #
38
+ # environment.engines('.coffee')
39
+ # # => CoffeeScriptTemplate
40
+ #
41
+ def engines(ext = nil)
42
+ if ext
43
+ ext = Sprockets::Utils.normalize_extension(ext)
44
+ @engines[ext]
45
+ else
46
+ @engines.dup
47
+ end
48
+ end
49
+
50
+ # Returns an `Array` of engine extension `String`s.
51
+ #
52
+ # environment.engine_extensions
53
+ # # => ['.coffee', '.sass', ...]
54
+ def engine_extensions
55
+ @engines.keys
56
+ end
57
+
58
+ # Registers a new Engine `klass` for `ext`. If the `ext` already
59
+ # has an engine registered, it will be overridden.
60
+ #
61
+ # environment.register_engine '.coffee', CoffeeScriptTemplate
62
+ #
63
+ def register_engine(ext, klass)
64
+ ext = Sprockets::Utils.normalize_extension(ext)
65
+ @engines ||= {}
66
+ @engines[ext] = klass
67
+ end
68
+ end
69
+
70
+ # Extend Sprockets module to provide global registry
71
+ extend Engines
72
+
73
+ # Cherry pick the default Tilt engines that make sense for
74
+ # Sprockets. We don't need ones that only generate html like HAML.
75
+
76
+ # Mmm, CoffeeScript
77
+ register_engine '.coffee', Tilt::CoffeeScriptTemplate
78
+
79
+ # JST engines
80
+ register_engine '.jst', JstProcessor
81
+ register_engine '.eco', EcoTemplate
82
+ register_engine '.ejs', EjsTemplate
83
+
84
+ # CSS engines
85
+ register_engine '.less', Tilt::LessTemplate
86
+ register_engine '.sass', Tilt::SassTemplate
87
+ register_engine '.scss', Tilt::ScssTemplate
88
+
89
+ # Other
90
+ register_engine '.erb', Tilt::ERBTemplate
91
+ register_engine '.str', Tilt::StringTemplate
92
+ end
@@ -0,0 +1,93 @@
1
+ require 'sprockets/base'
2
+ require 'sprockets/charset_normalizer'
3
+ require 'sprockets/context'
4
+ require 'sprockets/directive_processor'
5
+ require 'sprockets/index'
6
+ require 'sprockets/safety_colons'
7
+
8
+ require 'hike'
9
+ require 'logger'
10
+ require 'pathname'
11
+ require 'tilt'
12
+
13
+ module Sprockets
14
+ class Environment < Base
15
+ # `Environment` should initialized with your application's root
16
+ # directory. This should be the same as your Rails or Rack root.
17
+ #
18
+ # env = Environment.new(Rails.root)
19
+ #
20
+ def initialize(root = ".")
21
+ @trail = Hike::Trail.new(root)
22
+
23
+ self.logger = Logger.new($stderr)
24
+ self.logger.level = Logger::FATAL
25
+
26
+ # Create a safe `Context` subclass to mutate
27
+ @context_class = Class.new(Context)
28
+
29
+ # Set MD5 as the default digest
30
+ require 'digest/md5'
31
+ @digest_class = ::Digest::MD5
32
+ @version = ''
33
+
34
+ @static_root = nil
35
+
36
+ @engines = Sprockets.engines
37
+ @trail.extensions.replace(engine_extensions)
38
+
39
+ @mime_types = {}
40
+ @preprocessors = Hash.new { |h, k| h[k] = [] }
41
+ @postprocessors = Hash.new { |h, k| h[k] = [] }
42
+ @bundle_processors = Hash.new { |h, k| h[k] = [] }
43
+
44
+ register_mime_type 'text/css', '.css'
45
+ register_mime_type 'application/javascript', '.js'
46
+
47
+ register_preprocessor 'text/css', DirectiveProcessor
48
+ register_preprocessor 'application/javascript', DirectiveProcessor
49
+
50
+ register_postprocessor 'application/javascript', SafetyColons
51
+ register_bundle_processor 'text/css', CharsetNormalizer
52
+
53
+ expire_index!
54
+
55
+ yield self if block_given?
56
+ end
57
+
58
+ # Returns a cached version of the environment.
59
+ #
60
+ # All its file system calls are cached which makes `index` much
61
+ # faster. This behavior is ideal in production since the file
62
+ # system only changes between deploys.
63
+ def index
64
+ Index.new(self)
65
+ end
66
+
67
+ # Cache `find_asset` calls
68
+ def find_asset(path, options = {})
69
+ # Ensure inmemory cached assets are still fresh on every lookup
70
+ if (asset = @assets[path.to_s]) && asset.fresh?
71
+ asset
72
+ elsif asset = super
73
+ @assets[path.to_s] = @assets[asset.pathname.to_s] = asset
74
+ asset
75
+ end
76
+ end
77
+
78
+ protected
79
+ # Cache asset building in persisted cache.
80
+ def build_asset(path, pathname, options)
81
+ # Persisted cache
82
+ cache_asset(pathname.to_s) do
83
+ super
84
+ end
85
+ end
86
+
87
+ def expire_index!
88
+ # Clear digest to be recomputed
89
+ @digest = nil
90
+ @assets = {}
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,17 @@
1
+ # Define some basic Sprockets error classes
2
+ module Sprockets
3
+ class Error < StandardError; end
4
+ class ArgumentError < Error; end
5
+ class CircularDependencyError < Error; end
6
+ class ContentTypeMismatch < Error; end
7
+ class EncodingError < Error; end
8
+ class FileNotFound < Error; end
9
+
10
+ module EngineError
11
+ attr_accessor :sprockets_annotation
12
+
13
+ def message
14
+ [super, sprockets_annotation].compact.join("\n")
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,80 @@
1
+ require 'sprockets/base'
2
+
3
+ module Sprockets
4
+ # `Index` is a special cached version of `Environment`.
5
+ #
6
+ # The expection is that all of its file system methods are cached
7
+ # for the instances lifetime. This makes `Index` much faster. This
8
+ # behavior is ideal in production environments where the file system
9
+ # is immutable.
10
+ #
11
+ # `Index` should not be initialized directly. Instead use
12
+ # `Environment#index`.
13
+ class Index < Base
14
+ def initialize(environment)
15
+ # Copy environment attributes
16
+ @logger = environment.logger
17
+ @context_class = environment.context_class
18
+ @cache = environment.cache
19
+ @trail = environment.trail.index
20
+ @static_root = environment.static_root
21
+ @digest = environment.digest
22
+ @digest_class = environment.digest_class
23
+ @version = environment.version
24
+ @mime_types = environment.mime_types
25
+ @engines = environment.engines
26
+ @preprocessors = environment.preprocessors
27
+ @postprocessors = environment.postprocessors
28
+ @bundle_processors = environment.bundle_processors
29
+
30
+ # Initialize caches
31
+ @assets = {}
32
+ @digests = {}
33
+ end
34
+
35
+ # No-op return self as index
36
+ def index
37
+ self
38
+ end
39
+
40
+ # Cache calls to `file_digest`
41
+ def file_digest(pathname, data = nil)
42
+ memoize(@digests, pathname.to_s) { super }
43
+ end
44
+
45
+ # Cache `find_asset` calls
46
+ def find_asset(path, options = {})
47
+ if asset = @assets[path.to_s]
48
+ asset
49
+ elsif asset = super
50
+ # Cache at logical path and expanded path
51
+ @assets[path.to_s] = @assets[asset.pathname.to_s] = asset
52
+ asset
53
+ end
54
+ end
55
+
56
+ protected
57
+ # Index is immutable, any methods that try to clear the cache
58
+ # should bomb.
59
+ def expire_index!
60
+ raise TypeError, "can't modify immutable index"
61
+ end
62
+
63
+ # Cache asset building in memory and in persisted cache.
64
+ def build_asset(path, pathname, options)
65
+ # Memory cache
66
+ memoize(@assets, pathname.to_s) do
67
+ # Persisted cache
68
+ cache_asset(pathname.to_s) do
69
+ super
70
+ end
71
+ end
72
+ end
73
+
74
+ private
75
+ # Simple memoize helper that stores `nil` values
76
+ def memoize(hash, key)
77
+ hash.key?(key) ? hash[key] : hash[key] = yield
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,26 @@
1
+ require 'tilt'
2
+
3
+ module Sprockets
4
+ class JstProcessor < Tilt::Template
5
+ def self.default_mime_type
6
+ 'application/javascript'
7
+ end
8
+
9
+ def prepare
10
+ end
11
+
12
+ def evaluate(scope, locals, &block)
13
+ <<-JST
14
+ (function() {
15
+ this.JST || (this.JST = {});
16
+ this.JST[#{scope.logical_path.inspect}] = #{indent(data)};
17
+ }).call(this);
18
+ JST
19
+ end
20
+
21
+ private
22
+ def indent(string)
23
+ string.gsub(/$(.)/m, "\\1 ").strip
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,310 @@
1
+ require 'sprockets/engines'
2
+ require 'sprockets/processor'
3
+ require 'sprockets/utils'
4
+ require 'rack/mime'
5
+
6
+ module Sprockets
7
+ # `Processing` is an internal mixin whose public methods are exposed on
8
+ # the `Environment` and `Index` classes.
9
+ module Processing
10
+ include Engines
11
+
12
+ # Returns a `Hash` of registered mime types registered on the
13
+ # environment and those part of `Rack::Mime`.
14
+ #
15
+ # If an `ext` is given, it will lookup the mime type for that extension.
16
+ def mime_types(ext = nil)
17
+ if ext.nil?
18
+ Rack::Mime::MIME_TYPES.merge(@mime_types)
19
+ else
20
+ ext = Sprockets::Utils.normalize_extension(ext)
21
+ @mime_types[ext] || Rack::Mime::MIME_TYPES[ext]
22
+ end
23
+ end
24
+
25
+ # Register a new mime type.
26
+ def register_mime_type(mime_type, ext)
27
+ expire_index!
28
+ ext = Sprockets::Utils.normalize_extension(ext)
29
+ @trail.extensions << ext
30
+ @mime_types[ext] = mime_type
31
+ end
32
+
33
+ # Returns an `Array` of format extension `String`s.
34
+ #
35
+ # format_extensions
36
+ # # => ['.js', '.css']
37
+ #
38
+ def format_extensions
39
+ @trail.extensions - @engines.keys
40
+ end
41
+
42
+ # Registers a new Engine `klass` for `ext`.
43
+ def register_engine(ext, klass)
44
+ # Overrides the global behavior to expire the index
45
+ expire_index!
46
+ @trail.extensions << ext.to_s
47
+ super
48
+ end
49
+
50
+ # Deprecated alias for `preprocessors`.
51
+ def processors(*args)
52
+ preprocessors(*args)
53
+ end
54
+
55
+ # Returns an `Array` of `Processor` classes. If a `mime_type`
56
+ # argument is supplied, the processors registered under that
57
+ # extension will be returned.
58
+ #
59
+ # Preprocessors are ran before Postprocessors and Engine
60
+ # processors.
61
+ #
62
+ # All `Processor`s must follow the `Tilt::Template` interface. It is
63
+ # recommended to subclass `Tilt::Template`.
64
+ def preprocessors(mime_type = nil)
65
+ if mime_type
66
+ @preprocessors[mime_type].dup
67
+ else
68
+ deep_copy_hash(@preprocessors)
69
+ end
70
+ end
71
+
72
+ # Returns an `Array` of `Processor` classes. If a `mime_type`
73
+ # argument is supplied, the processors registered under that
74
+ # extension will be returned.
75
+ #
76
+ # Postprocessors are ran after Postprocessors and Engine processors.
77
+ #
78
+ # All `Processor`s must follow the `Tilt::Template` interface. It is
79
+ # recommended to subclass `Tilt::Template`.
80
+ def postprocessors(mime_type = nil)
81
+ if mime_type
82
+ @postprocessors[mime_type].dup
83
+ else
84
+ deep_copy_hash(@postprocessors)
85
+ end
86
+ end
87
+
88
+ # Deprecated alias for `register_preprocessor`.
89
+ def register_processor(*args, &block)
90
+ register_preprocessor(*args, &block)
91
+ end
92
+
93
+ # Registers a new Preprocessor `klass` for `mime_type`.
94
+ #
95
+ # register_preprocessor 'text/css', Sprockets::DirectiveProcessor
96
+ #
97
+ # A block can be passed for to create a shorthand processor.
98
+ #
99
+ # register_preprocessor :my_processor do |context, data|
100
+ # data.gsub(...)
101
+ # end
102
+ #
103
+ def register_preprocessor(mime_type, klass, &block)
104
+ expire_index!
105
+
106
+ if block_given?
107
+ name = klass.to_s
108
+ klass = Class.new(Processor) do
109
+ @name = name
110
+ @processor = block
111
+ end
112
+ end
113
+
114
+ @preprocessors[mime_type].push(klass)
115
+ end
116
+
117
+ # Registers a new Postprocessor `klass` for `mime_type`.
118
+ #
119
+ # register_postprocessor 'text/css', Sprockets::CharsetNormalizer
120
+ #
121
+ # A block can be passed for to create a shorthand processor.
122
+ #
123
+ # register_postprocessor :my_processor do |context, data|
124
+ # data.gsub(...)
125
+ # end
126
+ #
127
+ def register_postprocessor(mime_type, klass, &block)
128
+ expire_index!
129
+
130
+ if block_given?
131
+ name = klass.to_s
132
+ klass = Class.new(Processor) do
133
+ @name = name
134
+ @processor = block
135
+ end
136
+ end
137
+
138
+ @postprocessors[mime_type].push(klass)
139
+ end
140
+
141
+ # Deprecated alias for `unregister_preprocessor`.
142
+ def unregister_processor(*args)
143
+ unregister_preprocessor(*args)
144
+ end
145
+
146
+ # Remove Preprocessor `klass` for `mime_type`.
147
+ #
148
+ # unregister_preprocessor 'text/css', Sprockets::DirectiveProcessor
149
+ #
150
+ def unregister_preprocessor(mime_type, klass)
151
+ expire_index!
152
+
153
+ if klass.is_a?(String) || klass.is_a?(Symbol)
154
+ klass = @preprocessors[mime_type].detect { |cls|
155
+ cls.respond_to?(:name) &&
156
+ cls.name == "Sprockets::Processor (#{klass})"
157
+ }
158
+ end
159
+
160
+ @preprocessors[mime_type].delete(klass)
161
+ end
162
+
163
+ # Remove Postprocessor `klass` for `mime_type`.
164
+ #
165
+ # unregister_postprocessor 'text/css', Sprockets::DirectiveProcessor
166
+ #
167
+ def unregister_postprocessor(mime_type, klass)
168
+ expire_index!
169
+
170
+ if klass.is_a?(String) || klass.is_a?(Symbol)
171
+ klass = @postprocessors[mime_type].detect { |cls|
172
+ cls.respond_to?(:name) &&
173
+ cls.name == "Sprockets::Processor (#{klass})"
174
+ }
175
+ end
176
+
177
+ @postprocessors[mime_type].delete(klass)
178
+ end
179
+
180
+ # Returns an `Array` of `Processor` classes. If a `mime_type`
181
+ # argument is supplied, the processors registered under that
182
+ # extension will be returned.
183
+ #
184
+ # Bundle Processors are ran on concatenated assets rather than
185
+ # individual files.
186
+ #
187
+ # All `Processor`s must follow the `Tilt::Template` interface. It is
188
+ # recommended to subclass `Tilt::Template`.
189
+ def bundle_processors(mime_type = nil)
190
+ if mime_type
191
+ @bundle_processors[mime_type].dup
192
+ else
193
+ deep_copy_hash(@bundle_processors)
194
+ end
195
+ end
196
+
197
+ # Registers a new Bundle Processor `klass` for `mime_type`.
198
+ #
199
+ # register_bundle_processor 'text/css', Sprockets::CharsetNormalizer
200
+ #
201
+ # A block can be passed for to create a shorthand processor.
202
+ #
203
+ # register_bundle_processor :my_processor do |context, data|
204
+ # data.gsub(...)
205
+ # end
206
+ #
207
+ def register_bundle_processor(mime_type, klass, &block)
208
+ expire_index!
209
+
210
+ if block_given?
211
+ name = klass.to_s
212
+ klass = Class.new(Processor) do
213
+ @name = name
214
+ @processor = block
215
+ end
216
+ end
217
+
218
+ @bundle_processors[mime_type].push(klass)
219
+ end
220
+
221
+ # Remove Bundle Processor `klass` for `mime_type`.
222
+ #
223
+ # unregister_bundle_processor 'text/css', Sprockets::CharsetNormalizer
224
+ #
225
+ def unregister_bundle_processor(mime_type, klass)
226
+ expire_index!
227
+
228
+ if klass.is_a?(String) || klass.is_a?(Symbol)
229
+ klass = @bundle_processors[mime_type].detect { |cls|
230
+ cls.respond_to?(:name) &&
231
+ cls.name == "Sprockets::Processor (#{klass})"
232
+ }
233
+ end
234
+
235
+ @bundle_processors[mime_type].delete(klass)
236
+ end
237
+
238
+ # Return CSS compressor or nil if none is set
239
+ def css_compressor
240
+ bundle_processors('text/css').detect { |klass|
241
+ klass.respond_to?(:name) &&
242
+ klass.name == 'Sprockets::Processor (css_compressor)'
243
+ }
244
+ end
245
+
246
+ # Assign a compressor to run on `text/css` assets.
247
+ #
248
+ # The compressor object must respond to `compress` or `compile`.
249
+ def css_compressor=(compressor)
250
+ expire_index!
251
+
252
+ unregister_bundle_processor 'text/css', :css_compressor
253
+ return unless compressor
254
+
255
+ register_bundle_processor 'text/css', :css_compressor do |context, data|
256
+ compressor.compress(data)
257
+ end
258
+ end
259
+
260
+ # Return JS compressor or nil if none is set
261
+ def js_compressor
262
+ bundle_processors('application/javascript').detect { |klass|
263
+ klass.respond_to?(:name) &&
264
+ klass.name == 'Sprockets::Processor (js_compressor)'
265
+ }
266
+ end
267
+
268
+ # Assign a compressor to run on `application/javascript` assets.
269
+ #
270
+ # The compressor object must respond to `compress` or `compile`.
271
+ def js_compressor=(compressor)
272
+ expire_index!
273
+
274
+ unregister_bundle_processor 'application/javascript', :js_compressor
275
+ return unless compressor
276
+
277
+ register_bundle_processor 'application/javascript', :js_compressor do |context, data|
278
+ compressor.compress(data)
279
+ end
280
+ end
281
+
282
+ protected
283
+ def compute_digest
284
+ digest = super
285
+
286
+ # Add mime types to environment digest
287
+ digest << @mime_types.keys.join(',')
288
+
289
+ # Add engines to environment digest
290
+ digest << @engines.map { |e, k| "#{e}:#{k.name}" }.join(',')
291
+
292
+ # Add preprocessors to environment digest
293
+ digest << @preprocessors.map { |m, a| "#{m}:#{a.map(&:name)}" }.join(',')
294
+
295
+ # Add postprocessors to environment digest
296
+ digest << @postprocessors.map { |m, a| "#{m}:#{a.map(&:name)}" }.join(',')
297
+
298
+ # Add bundle processors to environment digest
299
+ digest << @bundle_processors.map { |m, a| "#{m}:#{a.map(&:name)}" }.join(',')
300
+
301
+ digest
302
+ end
303
+
304
+ private
305
+ def deep_copy_hash(hash)
306
+ initial = Hash.new { |h, k| h[k] = [] }
307
+ hash.inject(initial) { |h, (k, a)| h[k] = a.dup; h }
308
+ end
309
+ end
310
+ end