bpm 1.0.0.beta.8 → 1.0.0.beta.9
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/CHANGELOG.md +9 -0
- data/bpm.gemspec +2 -7
- data/lib/bpm/pipeline/generated_asset.rb +19 -21
- data/lib/bpm/pipeline/plugin_context.rb +7 -7
- data/lib/bpm/pipeline/plugin_processor.rb +11 -20
- data/lib/bpm/pipeline/transport_processor.rb +8 -13
- data/lib/bpm/pipeline.rb +47 -42
- data/lib/bpm/project_generator.rb +2 -2
- data/lib/bpm/version.rb +1 -1
- data/lib/bpm.rb +0 -3
- data/spec/cli/init_spec.rb +48 -48
- data/spec/cli/rebuild_spec.rb +30 -30
- data/spec/fixtures/projects/init_app/assets/bpm_libs.js +1 -1
- data/spec/fixtures/projects/init_app/assets/bpm_styles.css +1 -1
- data/spec/fixtures/projects/init_default/assets/bpm_libs.js +1 -1
- data/spec/fixtures/projects/init_default/assets/bpm_styles.css +1 -1
- data/spec/plugins/minifier_spec.rb +8 -8
- data/templates/project/index.html +0 -2
- data/templates/project/{app → lib}/main.js +0 -0
- metadata +24 -209
- data/.gitmodules +0 -3
- data/vendor/sprockets/.gitignore +0 -7
- data/vendor/sprockets/.travis.yml +0 -7
- data/vendor/sprockets/Gemfile +0 -2
- data/vendor/sprockets/LICENSE +0 -20
- data/vendor/sprockets/README.md +0 -22
- data/vendor/sprockets/Rakefile +0 -8
- data/vendor/sprockets/lib/sprockets/asset.rb +0 -198
- data/vendor/sprockets/lib/sprockets/asset_attributes.rb +0 -178
- data/vendor/sprockets/lib/sprockets/base.rb +0 -134
- data/vendor/sprockets/lib/sprockets/bundled_asset.rb +0 -249
- data/vendor/sprockets/lib/sprockets/cache/file_store.rb +0 -41
- data/vendor/sprockets/lib/sprockets/caching.rb +0 -126
- data/vendor/sprockets/lib/sprockets/charset_normalizer.rb +0 -41
- data/vendor/sprockets/lib/sprockets/context.rb +0 -221
- data/vendor/sprockets/lib/sprockets/digest.rb +0 -73
- data/vendor/sprockets/lib/sprockets/directive_processor.rb +0 -397
- data/vendor/sprockets/lib/sprockets/eco_template.rb +0 -38
- data/vendor/sprockets/lib/sprockets/ejs_template.rb +0 -37
- data/vendor/sprockets/lib/sprockets/engines.rb +0 -117
- data/vendor/sprockets/lib/sprockets/environment.rb +0 -94
- data/vendor/sprockets/lib/sprockets/errors.rb +0 -17
- data/vendor/sprockets/lib/sprockets/index.rb +0 -81
- data/vendor/sprockets/lib/sprockets/jst_processor.rb +0 -26
- data/vendor/sprockets/lib/sprockets/mime.rb +0 -38
- data/vendor/sprockets/lib/sprockets/processing.rb +0 -269
- data/vendor/sprockets/lib/sprockets/processor.rb +0 -32
- data/vendor/sprockets/lib/sprockets/safety_colons.rb +0 -28
- data/vendor/sprockets/lib/sprockets/server.rb +0 -270
- data/vendor/sprockets/lib/sprockets/static_asset.rb +0 -86
- data/vendor/sprockets/lib/sprockets/static_compilation.rb +0 -74
- data/vendor/sprockets/lib/sprockets/trail.rb +0 -123
- data/vendor/sprockets/lib/sprockets/utils.rb +0 -67
- data/vendor/sprockets/lib/sprockets/version.rb +0 -3
- data/vendor/sprockets/lib/sprockets.rb +0 -31
- data/vendor/sprockets/sprockets.gemspec +0 -30
- data/vendor/sprockets/test/fixtures/asset/POW.png +0 -0
- data/vendor/sprockets/test/fixtures/asset/application.js +0 -6
- data/vendor/sprockets/test/fixtures/asset/bar-utf8.css +0 -2
- data/vendor/sprockets/test/fixtures/asset/charset.css +0 -2
- data/vendor/sprockets/test/fixtures/asset/circle/a.js +0 -2
- data/vendor/sprockets/test/fixtures/asset/circle/b.js +0 -2
- data/vendor/sprockets/test/fixtures/asset/circle/c.js +0 -2
- data/vendor/sprockets/test/fixtures/asset/compat.js +0 -4
- data/vendor/sprockets/test/fixtures/asset/constants.js +0 -2
- data/vendor/sprockets/test/fixtures/asset/constants.yml +0 -1
- data/vendor/sprockets/test/fixtures/asset/default_mime_type.js +0 -1
- data/vendor/sprockets/test/fixtures/asset/filename.js.erb +0 -1
- data/vendor/sprockets/test/fixtures/asset/foo-utf8.css +0 -2
- data/vendor/sprockets/test/fixtures/asset/included_header.js +0 -4
- data/vendor/sprockets/test/fixtures/asset/jquery.tmpl.min.js +0 -1
- data/vendor/sprockets/test/fixtures/asset/mismatch.js +0 -1
- data/vendor/sprockets/test/fixtures/asset/multiple.js +0 -2
- data/vendor/sprockets/test/fixtures/asset/multipleengine.js +0 -1
- data/vendor/sprockets/test/fixtures/asset/noengine.js +0 -1
- data/vendor/sprockets/test/fixtures/asset/noformat.coffee +0 -1
- data/vendor/sprockets/test/fixtures/asset/one.css +0 -1
- data/vendor/sprockets/test/fixtures/asset/oneengine.js +0 -1
- data/vendor/sprockets/test/fixtures/asset/project.css +0 -1
- data/vendor/sprockets/test/fixtures/asset/project.js.erb +0 -4
- data/vendor/sprockets/test/fixtures/asset/relative/include.js +0 -4
- data/vendor/sprockets/test/fixtures/asset/relative/require.js +0 -1
- data/vendor/sprockets/test/fixtures/asset/relative/require_outside_path.js +0 -1
- data/vendor/sprockets/test/fixtures/asset/require_self.css +0 -9
- data/vendor/sprockets/test/fixtures/asset/require_self_twice.css +0 -8
- data/vendor/sprockets/test/fixtures/asset/semicolons/bar.js +0 -1
- data/vendor/sprockets/test/fixtures/asset/semicolons/index.js +0 -5
- data/vendor/sprockets/test/fixtures/asset/sprite.css.erb +0 -12
- data/vendor/sprockets/test/fixtures/asset/tree/all/b/c/d.js +0 -2
- data/vendor/sprockets/test/fixtures/asset/tree/all/b/c/e.js +0 -1
- data/vendor/sprockets/test/fixtures/asset/tree/all/b/c.js +0 -1
- data/vendor/sprockets/test/fixtures/asset/tree/all/b.css +0 -2
- data/vendor/sprockets/test/fixtures/asset/tree/all/b.js.erb +0 -1
- data/vendor/sprockets/test/fixtures/asset/tree/all/d/c.js.coffee +0 -1
- data/vendor/sprockets/test/fixtures/asset/tree/all/d/e.js +0 -1
- data/vendor/sprockets/test/fixtures/asset/tree/all_with_require.js +0 -7
- data/vendor/sprockets/test/fixtures/asset/tree/all_with_require_directory.js +0 -1
- data/vendor/sprockets/test/fixtures/asset/tree/all_with_require_tree.js +0 -2
- data/vendor/sprockets/test/fixtures/asset/tree/directory/application.js +0 -2
- data/vendor/sprockets/test/fixtures/asset/tree/directory/bar.js +0 -1
- data/vendor/sprockets/test/fixtures/asset/tree/directory/foo.js +0 -1
- data/vendor/sprockets/test/fixtures/asset/tree/tree/application.js +0 -2
- data/vendor/sprockets/test/fixtures/asset/tree/tree/bar.js +0 -1
- data/vendor/sprockets/test/fixtures/asset/tree/tree/foo.js +0 -1
- data/vendor/sprockets/test/fixtures/asset/tree/with_logical_path/a/a.js +0 -1
- data/vendor/sprockets/test/fixtures/asset/tree/with_logical_path/require_tree_with_logical_path.js +0 -1
- data/vendor/sprockets/test/fixtures/asset/tree/without_argument/a.js +0 -1
- data/vendor/sprockets/test/fixtures/asset/tree/without_argument/b.js +0 -1
- data/vendor/sprockets/test/fixtures/asset/tree/without_argument/require_tree_without_argument.js +0 -1
- data/vendor/sprockets/test/fixtures/asset/two.css +0 -1
- data/vendor/sprockets/test/fixtures/asset/unicode.js +0 -2
- data/vendor/sprockets/test/fixtures/asset/unknownexts.min.js +0 -2
- data/vendor/sprockets/test/fixtures/asset/users.js.erb.str +0 -4
- data/vendor/sprockets/test/fixtures/context/POW.png +0 -0
- data/vendor/sprockets/test/fixtures/context/application.js.yml +0 -3
- data/vendor/sprockets/test/fixtures/context/bar.js +0 -1
- data/vendor/sprockets/test/fixtures/context/foo.js +0 -2
- data/vendor/sprockets/test/fixtures/context/helpers.css.erb +0 -3
- data/vendor/sprockets/test/fixtures/context/properties.js.erb +0 -7
- data/vendor/sprockets/test/fixtures/context/require_glob.js +0 -1
- data/vendor/sprockets/test/fixtures/context/resolve_content_type.js.erb +0 -4
- data/vendor/sprockets/test/fixtures/context/sprite.css.embed +0 -3
- data/vendor/sprockets/test/fixtures/default/application.js.coffee +0 -4
- data/vendor/sprockets/test/fixtures/default/blank.gif +0 -0
- data/vendor/sprockets/test/fixtures/default/coffee/foo.coffee +0 -1
- data/vendor/sprockets/test/fixtures/default/coffee/index.js +0 -3
- data/vendor/sprockets/test/fixtures/default/empty +0 -0
- data/vendor/sprockets/test/fixtures/default/gallery.css.erb +0 -3
- data/vendor/sprockets/test/fixtures/default/gallery.js +0 -1
- data/vendor/sprockets/test/fixtures/default/goodbye.jst.eco +0 -1
- data/vendor/sprockets/test/fixtures/default/hello.jst.ejs +0 -1
- data/vendor/sprockets/test/fixtures/default/hello.txt +0 -1
- data/vendor/sprockets/test/fixtures/default/interpolation.js +0 -1
- data/vendor/sprockets/test/fixtures/default/missing_require.js +0 -1
- data/vendor/sprockets/test/fixtures/default/mobile/a.js +0 -1
- data/vendor/sprockets/test/fixtures/default/mobile/b.js +0 -1
- data/vendor/sprockets/test/fixtures/default/mobile/c.css +0 -1
- data/vendor/sprockets/test/fixtures/default/mobile/d.css +0 -1
- data/vendor/sprockets/test/fixtures/default/mobile/index.css +0 -3
- data/vendor/sprockets/test/fixtures/default/mobile/index.js +0 -1
- data/vendor/sprockets/test/fixtures/default/noreturn.js +0 -1
- data/vendor/sprockets/test/fixtures/default/project.js.coffee.erb +0 -2
- data/vendor/sprockets/test/fixtures/default/with_data_uri.css.erb +0 -3
- data/vendor/sprockets/test/fixtures/directives/code_before_comment +0 -3
- data/vendor/sprockets/test/fixtures/directives/comment_without_directives +0 -6
- data/vendor/sprockets/test/fixtures/directives/directive_word_splitting +0 -6
- data/vendor/sprockets/test/fixtures/directives/directives_after_header +0 -16
- data/vendor/sprockets/test/fixtures/directives/double_slash +0 -9
- data/vendor/sprockets/test/fixtures/directives/hash +0 -8
- data/vendor/sprockets/test/fixtures/directives/no_header +0 -2
- data/vendor/sprockets/test/fixtures/directives/slash_star +0 -10
- data/vendor/sprockets/test/fixtures/directives/slash_star_single +0 -4
- data/vendor/sprockets/test/fixtures/directives/space_between_directive_word +0 -2
- data/vendor/sprockets/test/fixtures/directives/triple_hash +0 -10
- data/vendor/sprockets/test/fixtures/encoding/ascii.js +0 -1
- data/vendor/sprockets/test/fixtures/encoding/ascii_utf8.js +0 -2
- data/vendor/sprockets/test/fixtures/encoding/utf16.js +0 -0
- data/vendor/sprockets/test/fixtures/encoding/utf8.js +0 -1
- data/vendor/sprockets/test/fixtures/encoding/utf8_bom.js +0 -1
- data/vendor/sprockets/test/fixtures/engines/hello.alert +0 -1
- data/vendor/sprockets/test/fixtures/engines/moo.js.str +0 -1
- data/vendor/sprockets/test/fixtures/public/compiled-digest-0aa2105d29558f3eb790d411d7d8fb66.js +0 -3
- data/vendor/sprockets/test/fixtures/public/compiled-digest-1c41eb0cf934a0c76babe875f982f9d1.js +0 -1
- data/vendor/sprockets/test/fixtures/server/app/javascripts/application.js +0 -5
- data/vendor/sprockets/test/fixtures/server/app/javascripts/bar.js +0 -1
- data/vendor/sprockets/test/fixtures/server/app/javascripts/foo.js +0 -1
- data/vendor/sprockets/test/fixtures/server/app/javascripts/hello.txt +0 -2
- data/vendor/sprockets/test/fixtures/server/app/javascripts/tree.js +0 -1
- data/vendor/sprockets/test/fixtures/server/vendor/javascripts/missing_require.js +0 -1
- data/vendor/sprockets/test/fixtures/server/vendor/stylesheets/missing_require.css +0 -1
- data/vendor/sprockets/test/sprockets_test.rb +0 -56
- data/vendor/sprockets/test/test_asset.rb +0 -699
- data/vendor/sprockets/test/test_asset_attributes.rb +0 -150
- data/vendor/sprockets/test/test_caching.rb +0 -62
- data/vendor/sprockets/test/test_context.rb +0 -115
- data/vendor/sprockets/test/test_directive_processor.rb +0 -124
- data/vendor/sprockets/test/test_encoding.rb +0 -65
- data/vendor/sprockets/test/test_engines.rb +0 -73
- data/vendor/sprockets/test/test_environment.rb +0 -587
- data/vendor/sprockets/test/test_server.rb +0 -227
@@ -1,178 +0,0 @@
|
|
1
|
-
require 'pathname'
|
2
|
-
|
3
|
-
module Sprockets
|
4
|
-
# `AssetAttributes` is a wrapper similar to `Pathname` that provides
|
5
|
-
# some helper accessors.
|
6
|
-
#
|
7
|
-
# These methods should be considered internalish.
|
8
|
-
class AssetAttributes
|
9
|
-
attr_reader :environment, :pathname
|
10
|
-
|
11
|
-
def initialize(environment, path)
|
12
|
-
@environment = environment
|
13
|
-
@pathname = path.is_a?(Pathname) ? path : Pathname.new(path.to_s)
|
14
|
-
end
|
15
|
-
|
16
|
-
# Replaces `$root` placeholder with actual environment root.
|
17
|
-
def expand_root
|
18
|
-
pathname.to_s.sub(/^\$root/, environment.root)
|
19
|
-
end
|
20
|
-
|
21
|
-
# Replaces environment root with `$root` placeholder.
|
22
|
-
def relativize_root
|
23
|
-
pathname.to_s.sub(/^#{Regexp.escape(environment.root)}/, '$root')
|
24
|
-
end
|
25
|
-
|
26
|
-
# Strips `$HOME` and environment root for a nicer output.
|
27
|
-
def pretty_path
|
28
|
-
@pretty_path ||= @pathname.
|
29
|
-
sub(/^#{Regexp.escape(ENV['HOME'] || '')}/, '~').
|
30
|
-
sub(/^#{Regexp.escape(environment.root)}\//, '')
|
31
|
-
end
|
32
|
-
|
33
|
-
# Returns paths search the load path for.
|
34
|
-
def search_paths
|
35
|
-
paths = [pathname.to_s]
|
36
|
-
|
37
|
-
if format_extension && engine_extensions.empty?
|
38
|
-
environment.engine_formats(format_extension).each do |ext, engine|
|
39
|
-
paths << pathname.sub(format_extension, ext).to_s
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
if pathname.basename(extensions.join).to_s != 'index'
|
44
|
-
path_without_extensions = extensions.inject(pathname) { |p, ext| p.sub(ext, '') }
|
45
|
-
index_path = path_without_extensions.join("index#{extensions.join}").to_s
|
46
|
-
|
47
|
-
paths << index_path
|
48
|
-
|
49
|
-
if format_extension && engine_extensions.empty?
|
50
|
-
environment.engine_formats(format_extension).each do |ext, engine|
|
51
|
-
paths << index_path.sub(format_extension, ext).to_s
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
paths
|
57
|
-
end
|
58
|
-
|
59
|
-
# Reverse guess logical path for fully expanded path.
|
60
|
-
#
|
61
|
-
# This has some known issues. For an example if a file is
|
62
|
-
# shaddowed in the path, but is required relatively, its logical
|
63
|
-
# path will be incorrect.
|
64
|
-
def logical_path
|
65
|
-
raise ArgumentError unless pathname.absolute?
|
66
|
-
|
67
|
-
if root_path = environment.paths.detect { |path| pathname.to_s[path] }
|
68
|
-
path = pathname.relative_path_from(Pathname.new(root_path)).to_s
|
69
|
-
path = engine_extensions.inject(path) { |p, ext| p.sub(ext, '') }
|
70
|
-
path = "#{path}#{engine_format_extension}" unless format_extension
|
71
|
-
path
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
# Returns `Array` of extension `String`s.
|
76
|
-
#
|
77
|
-
# "foo.js.coffee"
|
78
|
-
# # => [".js", ".coffee"]
|
79
|
-
#
|
80
|
-
def extensions
|
81
|
-
@extensions ||= @pathname.basename.to_s.scan(/\.[^.]+/)
|
82
|
-
end
|
83
|
-
|
84
|
-
# Returns the format extension.
|
85
|
-
#
|
86
|
-
# "foo.js.coffee"
|
87
|
-
# # => ".js"
|
88
|
-
#
|
89
|
-
def format_extension
|
90
|
-
extensions.detect { |ext|
|
91
|
-
@environment.mime_types(ext) && !@environment.engines(ext)
|
92
|
-
}
|
93
|
-
end
|
94
|
-
|
95
|
-
# Returns an `Array` of engine extensions.
|
96
|
-
#
|
97
|
-
# "foo.js.coffee.erb"
|
98
|
-
# # => [".coffee", ".erb"]
|
99
|
-
#
|
100
|
-
def engine_extensions
|
101
|
-
exts = extensions
|
102
|
-
|
103
|
-
if offset = extensions.index(format_extension)
|
104
|
-
exts = extensions[offset+1..-1]
|
105
|
-
end
|
106
|
-
|
107
|
-
exts.select { |ext| @environment.engines(ext) }
|
108
|
-
end
|
109
|
-
|
110
|
-
# Returns engine classes.
|
111
|
-
def engines
|
112
|
-
engine_extensions.map { |ext| @environment.engines(ext) }
|
113
|
-
end
|
114
|
-
|
115
|
-
# Returns all processors to run on the path.
|
116
|
-
def processors
|
117
|
-
environment.preprocessors(content_type) +
|
118
|
-
engines.reverse +
|
119
|
-
environment.postprocessors(content_type)
|
120
|
-
end
|
121
|
-
|
122
|
-
# Returns the content type for the pathname. Falls back to `application/octet-stream`.
|
123
|
-
def content_type
|
124
|
-
@content_type ||= begin
|
125
|
-
if format_extension.nil?
|
126
|
-
engine_content_type || 'application/octet-stream'
|
127
|
-
else
|
128
|
-
@environment.mime_types(format_extension) ||
|
129
|
-
engine_content_type ||
|
130
|
-
'application/octet-stream'
|
131
|
-
end
|
132
|
-
end
|
133
|
-
end
|
134
|
-
|
135
|
-
# Gets digest fingerprint.
|
136
|
-
#
|
137
|
-
# "foo-0aa2105d29558f3eb790d411d7d8fb66.js"
|
138
|
-
# # => "0aa2105d29558f3eb790d411d7d8fb66"
|
139
|
-
#
|
140
|
-
def path_fingerprint
|
141
|
-
pathname.basename(extensions.join).to_s =~ /-([0-9a-f]{7,40})$/ ? $1 : nil
|
142
|
-
end
|
143
|
-
|
144
|
-
# Injects digest fingerprint into path.
|
145
|
-
#
|
146
|
-
# "foo.js"
|
147
|
-
# # => "foo-0aa2105d29558f3eb790d411d7d8fb66.js"
|
148
|
-
#
|
149
|
-
def path_with_fingerprint(digest)
|
150
|
-
if path_fingerprint
|
151
|
-
path.sub($1, digest)
|
152
|
-
else
|
153
|
-
basename = "#{pathname.basename(extensions.join)}-#{digest}#{extensions.join}"
|
154
|
-
pathname.dirname.to_s == '.' ? basename : pathname.dirname.join(basename).to_s
|
155
|
-
end
|
156
|
-
end
|
157
|
-
|
158
|
-
private
|
159
|
-
# Returns implicit engine content type.
|
160
|
-
#
|
161
|
-
# `.coffee` files carry an implicit `application/javascript`
|
162
|
-
# content type.
|
163
|
-
def engine_content_type
|
164
|
-
engines.reverse.each do |engine|
|
165
|
-
if engine.respond_to?(:default_mime_type) && engine.default_mime_type
|
166
|
-
return engine.default_mime_type
|
167
|
-
end
|
168
|
-
end
|
169
|
-
nil
|
170
|
-
end
|
171
|
-
|
172
|
-
def engine_format_extension
|
173
|
-
if content_type = engine_content_type
|
174
|
-
environment.extension_for_mime_type(content_type)
|
175
|
-
end
|
176
|
-
end
|
177
|
-
end
|
178
|
-
end
|
@@ -1,134 +0,0 @@
|
|
1
|
-
require 'sprockets/asset_attributes'
|
2
|
-
require 'sprockets/bundled_asset'
|
3
|
-
require 'sprockets/caching'
|
4
|
-
require 'sprockets/digest'
|
5
|
-
require 'sprockets/processing'
|
6
|
-
require 'sprockets/server'
|
7
|
-
require 'sprockets/static_asset'
|
8
|
-
require 'sprockets/static_compilation'
|
9
|
-
require 'sprockets/trail'
|
10
|
-
require 'pathname'
|
11
|
-
|
12
|
-
module Sprockets
|
13
|
-
# `Base` class for `Environment` and `Index`.
|
14
|
-
class Base
|
15
|
-
include Digest
|
16
|
-
include Caching, Processing, Server, StaticCompilation, Trail
|
17
|
-
|
18
|
-
# Get and set `Logger` instance.
|
19
|
-
attr_accessor :logger
|
20
|
-
|
21
|
-
# Get `Context` class.
|
22
|
-
#
|
23
|
-
# This class maybe mutated and mixed in with custom helpers.
|
24
|
-
#
|
25
|
-
# environment.context_class.instance_eval do
|
26
|
-
# include MyHelpers
|
27
|
-
# def asset_url; end
|
28
|
-
# end
|
29
|
-
#
|
30
|
-
attr_reader :context_class
|
31
|
-
|
32
|
-
# Get persistent cache store
|
33
|
-
attr_reader :cache
|
34
|
-
|
35
|
-
# Set persistent cache store
|
36
|
-
#
|
37
|
-
# The cache store must implement a pair of getters and
|
38
|
-
# setters. Either `get(key)`/`set(key, value)`,
|
39
|
-
# `[key]`/`[key]=value`, `read(key)`/`write(key, value)`.
|
40
|
-
def cache=(cache)
|
41
|
-
expire_index!
|
42
|
-
@cache = cache
|
43
|
-
end
|
44
|
-
|
45
|
-
# Return an `Index`. Must be implemented by the subclass.
|
46
|
-
def index
|
47
|
-
raise NotImplementedError
|
48
|
-
end
|
49
|
-
|
50
|
-
# Works like `Dir.entries`.
|
51
|
-
#
|
52
|
-
# Subclasses may cache this method.
|
53
|
-
def entries(pathname)
|
54
|
-
trail.entries(pathname)
|
55
|
-
end
|
56
|
-
|
57
|
-
# Works like `File.stat`.
|
58
|
-
#
|
59
|
-
# Subclasses may cache this method.
|
60
|
-
def stat(path)
|
61
|
-
trail.stat(path)
|
62
|
-
end
|
63
|
-
|
64
|
-
# Read and compute digest of filename.
|
65
|
-
#
|
66
|
-
# Subclasses may cache this method.
|
67
|
-
def file_digest(path, data = nil)
|
68
|
-
if stat = self.stat(path)
|
69
|
-
# `data` maybe provided
|
70
|
-
if data
|
71
|
-
digest.update(data)
|
72
|
-
|
73
|
-
# If its a file, digest the contents
|
74
|
-
elsif stat.file?
|
75
|
-
digest.file(path)
|
76
|
-
|
77
|
-
# If its a directive, digest the list of filenames
|
78
|
-
elsif stat.directory?
|
79
|
-
contents = self.entries(path).join(',')
|
80
|
-
digest.update(contents)
|
81
|
-
end
|
82
|
-
end
|
83
|
-
end
|
84
|
-
|
85
|
-
# Internal. Return a `AssetAttributes` for `path`.
|
86
|
-
def attributes_for(path)
|
87
|
-
AssetAttributes.new(self, path)
|
88
|
-
end
|
89
|
-
|
90
|
-
# Internal. Return content type of `path`.
|
91
|
-
def content_type_of(path)
|
92
|
-
attributes_for(path).content_type
|
93
|
-
end
|
94
|
-
|
95
|
-
# Find asset by logical path or expanded path.
|
96
|
-
def find_asset(path, options = {})
|
97
|
-
pathname = Pathname.new(path)
|
98
|
-
|
99
|
-
if pathname.absolute?
|
100
|
-
build_asset(attributes_for(pathname).logical_path, pathname, options)
|
101
|
-
else
|
102
|
-
find_asset_in_path(pathname, options)
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
|
-
# Preferred `find_asset` shorthand.
|
107
|
-
#
|
108
|
-
# environment['application.js']
|
109
|
-
#
|
110
|
-
def [](*args)
|
111
|
-
find_asset(*args)
|
112
|
-
end
|
113
|
-
|
114
|
-
protected
|
115
|
-
# Clear index after mutating state. Must be implemented by the subclass.
|
116
|
-
def expire_index!
|
117
|
-
raise NotImplementedError
|
118
|
-
end
|
119
|
-
|
120
|
-
def build_asset(logical_path, pathname, options)
|
121
|
-
pathname = Pathname.new(pathname)
|
122
|
-
|
123
|
-
return unless stat(pathname)
|
124
|
-
|
125
|
-
# If there are any processors to run on the pathname, use
|
126
|
-
# `BundledAsset`. Otherwise use `StaticAsset` and treat is as binary.
|
127
|
-
if attributes_for(pathname).processors.any?
|
128
|
-
BundledAsset.new(self, logical_path, pathname, options)
|
129
|
-
else
|
130
|
-
StaticAsset.new(self, logical_path, pathname)
|
131
|
-
end
|
132
|
-
end
|
133
|
-
end
|
134
|
-
end
|
@@ -1,249 +0,0 @@
|
|
1
|
-
require 'sprockets/asset'
|
2
|
-
require 'sprockets/errors'
|
3
|
-
require 'fileutils'
|
4
|
-
require 'set'
|
5
|
-
require 'zlib'
|
6
|
-
|
7
|
-
module Sprockets
|
8
|
-
# `BundledAsset`s are used for files that need to be processed and
|
9
|
-
# concatenated with other assets. Use for `.js` and `.css` files.
|
10
|
-
class BundledAsset < Asset
|
11
|
-
# Define extra attributes to be serialized.
|
12
|
-
def self.serialized_attributes
|
13
|
-
super + %w( content_type mtime )
|
14
|
-
end
|
15
|
-
|
16
|
-
def initialize(environment, logical_path, pathname, options)
|
17
|
-
super(environment, logical_path, pathname)
|
18
|
-
@options = options || {}
|
19
|
-
end
|
20
|
-
|
21
|
-
# Initialize `BundledAsset` from serialized `Hash`.
|
22
|
-
def init_with(environment, coder)
|
23
|
-
@options = {}
|
24
|
-
|
25
|
-
super
|
26
|
-
|
27
|
-
@body = coder['body']
|
28
|
-
@assets = coder['asset_paths'].map { |p|
|
29
|
-
p = expand_root_path(p)
|
30
|
-
p == pathname.to_s ? self : environment[p, @options]
|
31
|
-
}
|
32
|
-
|
33
|
-
@dependency_paths = coder['dependency_paths'].map { |h|
|
34
|
-
h.merge('path' => expand_root_path(h['path']))
|
35
|
-
}
|
36
|
-
@dependency_paths.each do |dep|
|
37
|
-
dep['mtime'] = Time.parse(dep['mtime']) if dep['mtime'].is_a?(String)
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
# Serialize custom attributes in `BundledAsset`.
|
42
|
-
def encode_with(coder)
|
43
|
-
super
|
44
|
-
|
45
|
-
coder['body'] = body
|
46
|
-
coder['asset_paths'] = to_a.map { |a| relativize_root_path(a.pathname) }
|
47
|
-
coder['dependency_paths'] = dependency_paths.map { |h|
|
48
|
-
h.merge('path' => relativize_root_path(h['path']))
|
49
|
-
}
|
50
|
-
end
|
51
|
-
|
52
|
-
# Get asset's own processed contents. Excludes any of its required
|
53
|
-
# dependencies but does run any processors or engines on the
|
54
|
-
# original file.
|
55
|
-
def body
|
56
|
-
@body ||= build_dependency_context_and_body[1]
|
57
|
-
end
|
58
|
-
|
59
|
-
# Get latest mtime of all its dependencies.
|
60
|
-
def mtime
|
61
|
-
@mtime ||= dependency_paths.map { |h| h['mtime'] }.max
|
62
|
-
end
|
63
|
-
|
64
|
-
# Get size of concatenated source.
|
65
|
-
def length
|
66
|
-
@length ||= build_source['length']
|
67
|
-
end
|
68
|
-
|
69
|
-
# Compute digest of concatenated source.
|
70
|
-
def digest
|
71
|
-
@digest ||= build_source['digest']
|
72
|
-
end
|
73
|
-
|
74
|
-
# Return an `Array` of `Asset` files that are declared dependencies.
|
75
|
-
def dependencies
|
76
|
-
to_a - [self]
|
77
|
-
end
|
78
|
-
|
79
|
-
# Expand asset into an `Array` of parts.
|
80
|
-
def to_a
|
81
|
-
@assets ||= build_dependencies_paths_and_assets[1]
|
82
|
-
end
|
83
|
-
|
84
|
-
# Checks if Asset is stale by comparing the actual mtime and
|
85
|
-
# digest to the inmemory model.
|
86
|
-
def fresh?
|
87
|
-
# Check freshness of all declared dependencies
|
88
|
-
dependency_paths.all? { |h| dependency_fresh?(h) }
|
89
|
-
end
|
90
|
-
|
91
|
-
# Return `String` of concatenated source.
|
92
|
-
def to_s
|
93
|
-
@source ||= build_source['source']
|
94
|
-
end
|
95
|
-
|
96
|
-
# Save asset to disk.
|
97
|
-
def write_to(filename, options = {})
|
98
|
-
# Gzip contents if filename has '.gz'
|
99
|
-
options[:compress] ||= File.extname(filename) == '.gz'
|
100
|
-
|
101
|
-
File.open("#{filename}+", 'wb') do |f|
|
102
|
-
if options[:compress]
|
103
|
-
# Run contents through `Zlib`
|
104
|
-
gz = Zlib::GzipWriter.new(f, Zlib::BEST_COMPRESSION)
|
105
|
-
gz.write to_s
|
106
|
-
gz.close
|
107
|
-
else
|
108
|
-
# Write out as is
|
109
|
-
f.write to_s
|
110
|
-
f.close
|
111
|
-
end
|
112
|
-
end
|
113
|
-
|
114
|
-
# Atomic write
|
115
|
-
FileUtils.mv("#{filename}+", filename)
|
116
|
-
|
117
|
-
# Set mtime correctly
|
118
|
-
File.utime(mtime, mtime, filename)
|
119
|
-
|
120
|
-
nil
|
121
|
-
ensure
|
122
|
-
# Ensure tmp file gets cleaned up
|
123
|
-
FileUtils.rm("#{filename}+") if File.exist?("#{filename}+")
|
124
|
-
end
|
125
|
-
|
126
|
-
protected
|
127
|
-
# Return new blank `Context` to evaluate processors in.
|
128
|
-
def blank_context
|
129
|
-
environment.context_class.new(environment, logical_path.to_s, pathname)
|
130
|
-
end
|
131
|
-
|
132
|
-
# Get `Context` after processors have been ran on it. This
|
133
|
-
# trackes any dependencies that processors have added to it.
|
134
|
-
def dependency_context
|
135
|
-
@dependency_context ||= build_dependency_context_and_body[0]
|
136
|
-
end
|
137
|
-
|
138
|
-
# All paths that this asset depends on. This list may include
|
139
|
-
# non-assets like directories.
|
140
|
-
def dependency_paths
|
141
|
-
@dependency_paths ||= build_dependencies_paths_and_assets[0]
|
142
|
-
end
|
143
|
-
|
144
|
-
private
|
145
|
-
# Check if self has already been required and raise a fast
|
146
|
-
# error. Otherwise you end up with a StackOverflow error.
|
147
|
-
def check_circular_dependency!
|
148
|
-
requires = @options[:_requires] ||= []
|
149
|
-
if requires.include?(pathname.to_s)
|
150
|
-
raise CircularDependencyError, "#{pathname} has already been required"
|
151
|
-
end
|
152
|
-
requires << pathname.to_s
|
153
|
-
end
|
154
|
-
|
155
|
-
def build_dependency_context_and_body
|
156
|
-
context = blank_context
|
157
|
-
|
158
|
-
# Read original data once and pass it along to `Context`
|
159
|
-
data = Sprockets::Utils.read_unicode(pathname)
|
160
|
-
|
161
|
-
# Prime digest cache with data, since we happen to have it
|
162
|
-
environment.file_digest(pathname, data)
|
163
|
-
|
164
|
-
# Runs all processors on `Context`
|
165
|
-
body = context.evaluate(pathname, :data => data)
|
166
|
-
|
167
|
-
@dependency_context, @body = context, body
|
168
|
-
|
169
|
-
return context, body
|
170
|
-
end
|
171
|
-
|
172
|
-
def build_dependencies_paths_and_assets
|
173
|
-
check_circular_dependency!
|
174
|
-
|
175
|
-
paths, assets = {}, []
|
176
|
-
|
177
|
-
# Define an `add_dependency` helper
|
178
|
-
add_dependency = lambda do |asset|
|
179
|
-
unless assets.any? { |a| a.pathname == asset.pathname }
|
180
|
-
assets << asset
|
181
|
-
end
|
182
|
-
end
|
183
|
-
|
184
|
-
# Iterate over all the declared require paths from the `Context`
|
185
|
-
dependency_context._required_paths.each do |required_path|
|
186
|
-
# Catch `require_self`
|
187
|
-
if required_path == pathname.to_s
|
188
|
-
add_dependency.call(self)
|
189
|
-
else
|
190
|
-
# Recursively lookup required asset
|
191
|
-
environment[required_path, @options].to_a.each do |asset|
|
192
|
-
add_dependency.call(asset)
|
193
|
-
end
|
194
|
-
end
|
195
|
-
end
|
196
|
-
|
197
|
-
# Ensure self is added to the dependency list
|
198
|
-
add_dependency.call(self)
|
199
|
-
|
200
|
-
dependency_context._dependency_paths.each do |path|
|
201
|
-
paths[path] ||= {
|
202
|
-
'path' => path,
|
203
|
-
'mtime' => environment.stat(path).mtime,
|
204
|
-
'hexdigest' => environment.file_digest(path).hexdigest
|
205
|
-
}
|
206
|
-
end
|
207
|
-
|
208
|
-
dependency_context._dependency_assets.each do |path|
|
209
|
-
# Skip if depending on self
|
210
|
-
next if path == pathname.to_s
|
211
|
-
|
212
|
-
# Recursively lookup required asset
|
213
|
-
environment[path, @options].to_a.each do |asset|
|
214
|
-
asset.dependency_paths.each do |dep|
|
215
|
-
paths[dep['path']] ||= dep
|
216
|
-
end
|
217
|
-
end
|
218
|
-
end
|
219
|
-
|
220
|
-
@dependency_paths, @assets = paths.values, assets
|
221
|
-
|
222
|
-
return @dependency_paths, @assets
|
223
|
-
end
|
224
|
-
|
225
|
-
def build_source
|
226
|
-
hash = environment.cache_hash("#{pathname}:source", id) do
|
227
|
-
data = ""
|
228
|
-
|
229
|
-
# Explode Asset into parts and gather the dependency bodies
|
230
|
-
to_a.each { |dependency| data << dependency.body }
|
231
|
-
|
232
|
-
# Run bundle processors on concatenated source
|
233
|
-
data = blank_context.evaluate(pathname, :data => data,
|
234
|
-
:processors => environment.bundle_processors(content_type))
|
235
|
-
|
236
|
-
{ 'length' => Rack::Utils.bytesize(data),
|
237
|
-
'digest' => environment.digest.update(data).hexdigest,
|
238
|
-
'source' => data }
|
239
|
-
end
|
240
|
-
hash['length'] = Integer(hash['length']) if hash['length'].is_a?(String)
|
241
|
-
|
242
|
-
@length = hash['length']
|
243
|
-
@digest = hash['digest']
|
244
|
-
@source = hash['source']
|
245
|
-
|
246
|
-
hash
|
247
|
-
end
|
248
|
-
end
|
249
|
-
end
|
@@ -1,41 +0,0 @@
|
|
1
|
-
require 'digest/md5'
|
2
|
-
require 'fileutils'
|
3
|
-
require 'pathname'
|
4
|
-
|
5
|
-
module Sprockets
|
6
|
-
module Cache
|
7
|
-
# A simple file system cache store.
|
8
|
-
#
|
9
|
-
# environment.cache = Sprockets::Cache::FileStore.new("tmp/sprockets")
|
10
|
-
#
|
11
|
-
class FileStore
|
12
|
-
def initialize(root)
|
13
|
-
@root = Pathname.new(root)
|
14
|
-
|
15
|
-
# Ensure directory exists
|
16
|
-
FileUtils.mkdir_p @root
|
17
|
-
end
|
18
|
-
|
19
|
-
# Lookup value in cache
|
20
|
-
def [](key)
|
21
|
-
pathname = path_for(key)
|
22
|
-
pathname.exist? ? pathname.open('rb') { |f| Marshal.load(f) } : nil
|
23
|
-
end
|
24
|
-
|
25
|
-
# Save value to cache
|
26
|
-
def []=(key, value)
|
27
|
-
path_for(key).open('w') { |f| Marshal.dump(value, f)}
|
28
|
-
value
|
29
|
-
end
|
30
|
-
|
31
|
-
private
|
32
|
-
# Returns path for cache key.
|
33
|
-
#
|
34
|
-
# The key may include some funky characters so hash it into
|
35
|
-
# safe hex.
|
36
|
-
def path_for(key)
|
37
|
-
@root.join(::Digest::MD5.hexdigest(key))
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|