bpm 0.1.0 → 0.1.2

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.
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