bpm 1.0.0.beta.6 → 1.0.0.beta.8
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.
- data/CHANGELOG.md +26 -0
- data/TODO.md +0 -3
- data/lib/bpm/cli/base.rb +3 -3
- data/lib/bpm/default.json +5 -1
- data/lib/bpm/errors.rb +8 -0
- data/lib/bpm/generator.rb +8 -0
- data/lib/bpm/init_generator.rb +1 -1
- data/lib/bpm/package.rb +113 -11
- data/lib/bpm/pipeline/format_processor.rb +28 -0
- data/lib/bpm/pipeline/generated_asset.rb +2 -2
- data/lib/bpm/pipeline/package_pipeline.rb +79 -0
- data/lib/bpm/pipeline/plugin_asset.rb +7 -8
- data/lib/bpm/pipeline/plugin_processor.rb +52 -0
- data/lib/bpm/pipeline.rb +89 -26
- data/lib/bpm/project.rb +55 -29
- data/lib/bpm/version.rb +1 -1
- data/lib/bpm.rb +3 -1
- data/spec/cli/list_spec.rb +1 -0
- data/spec/cli/pack_spec.rb +125 -103
- data/spec/fixtures/projects/coffee/coffee.json +17 -0
- data/spec/fixtures/projects/coffee/index.html.handlebars +1 -0
- data/spec/fixtures/projects/coffee/lib/main.coffee +1 -0
- data/spec/fixtures/projects/coffee/packages/coffee-script/compiler.js +4 -0
- data/spec/fixtures/projects/coffee/packages/coffee-script/lib/main.js +1 -0
- data/spec/fixtures/projects/coffee/packages/coffee-script/package.json +15 -0
- data/spec/fixtures/projects/coffee/packages/handlebars/format.js +6 -0
- data/spec/fixtures/projects/coffee/packages/handlebars/lib/main.js +2 -0
- data/spec/fixtures/projects/coffee/packages/handlebars/package.json +16 -0
- data/spec/fixtures/projects/coffee/packages/spade/lib/main.js +1 -0
- data/spec/fixtures/projects/coffee/packages/spade/package.json +14 -0
- data/spec/fixtures/projects/coffee/packages/spade/transport.js +3 -0
- data/spec/fixtures/projects/coffee/templates/section.handlebars +1 -0
- data/spec/fixtures/projects/minitrans/packages/transport/package.json +5 -1
- data/spec/fixtures/projects/transporter/packages/transport/package.json +5 -1
- data/spec/package_pipeline_spec.rb +30 -0
- data/spec/package_spec.rb +328 -316
- data/spec/plugins/format_spec.rb +38 -0
- data/spec/plugins/transport_spec.rb +1 -1
- data/spec/support/matchers.rb +1 -2
- metadata +57 -24
data/CHANGELOG.md
CHANGED
@@ -1,4 +1,30 @@
|
|
1
1
|
|
2
|
+
* First cut at support for formats.
|
3
|
+
* Also introduces new requirement for defining transport and format plugins
|
4
|
+
in the package.json. Now you must use the "bpm:provides" keyword:
|
5
|
+
|
6
|
+
New format for defining a format or transport plugin:
|
7
|
+
|
8
|
+
"bpm:provides": {
|
9
|
+
"transport": {
|
10
|
+
"main": "path/to/transport/plugin"
|
11
|
+
},
|
12
|
+
|
13
|
+
"format:EXT": {
|
14
|
+
"default:mime": "application/javascript",
|
15
|
+
"main": "path/to/format/plugin"
|
16
|
+
}
|
17
|
+
}
|
18
|
+
|
19
|
+
# 1.0.0.beta.7
|
20
|
+
|
21
|
+
* fixed bug where local packages that are indirect dependencies of other
|
22
|
+
remote packages could cause bpm to error out unable to find dependencies.
|
23
|
+
|
24
|
+
* improved logging slightly
|
25
|
+
|
26
|
+
# 1.0.0.beta.6 (yanked)
|
27
|
+
|
2
28
|
* bpm now passes a context object with build settings and a minify option
|
3
29
|
to plugins - this will allow spade to support string loading.
|
4
30
|
|
data/TODO.md
CHANGED
data/lib/bpm/cli/base.rb
CHANGED
@@ -277,7 +277,7 @@ module BPM
|
|
277
277
|
package = local.pack(File.join(package_path, "package.json"), options[:email])
|
278
278
|
|
279
279
|
if package.errors.empty?
|
280
|
-
|
280
|
+
say "Successfully built package: #{package.file_name}"
|
281
281
|
else
|
282
282
|
failure_message = "BPM encountered the following problems building your package:"
|
283
283
|
package.errors.each do |error|
|
@@ -298,7 +298,7 @@ module BPM
|
|
298
298
|
begin
|
299
299
|
package = local.unpack(path, options[:target])
|
300
300
|
unpack_path = File.expand_path(File.join(Dir.pwd, options[:target], package.full_name))
|
301
|
-
|
301
|
+
say "Unpacked package into: #{unpack_path}"
|
302
302
|
rescue Errno::EACCES, LibGems::FilePermissionError => ex
|
303
303
|
abort "There was a problem unpacking #{path}:\n#{ex.message}"
|
304
304
|
end
|
@@ -391,7 +391,7 @@ module BPM
|
|
391
391
|
abort %{No packages found matching "#{names.join('", "')}".}
|
392
392
|
else
|
393
393
|
packages.each do |name, versions|
|
394
|
-
|
394
|
+
say "#{name} (#{versions.sort.reverse.join(", ")})"
|
395
395
|
end
|
396
396
|
end
|
397
397
|
end
|
data/lib/bpm/default.json
CHANGED
data/lib/bpm/errors.rb
CHANGED
@@ -48,4 +48,12 @@ module BPM
|
|
48
48
|
end
|
49
49
|
end
|
50
50
|
|
51
|
+
class TooManyTransportsError < BPM::Error
|
52
|
+
def format_message(pkg)
|
53
|
+
err = <<EOF
|
54
|
+
#{pkg.name} depends on #{pkg.provided_transports.size} packages that define transport plugins. Select a plugin by adding a `bpm:use:transport` property to the package.json
|
55
|
+
EOF
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
51
59
|
end
|
data/lib/bpm/generator.rb
CHANGED
data/lib/bpm/init_generator.rb
CHANGED
data/lib/bpm/package.rb
CHANGED
@@ -26,10 +26,11 @@ module BPM
|
|
26
26
|
"bpm:formats" => :hash,
|
27
27
|
"bpm:transport" => :string,
|
28
28
|
"bpm:use:transport" => :string,
|
29
|
-
"bpm:minifier" => :string
|
29
|
+
"bpm:minifier" => :string,
|
30
|
+
"bpm:provides" => :hash
|
30
31
|
}
|
31
32
|
|
32
|
-
PLUGIN_FIELDS = %w[bpm:
|
33
|
+
PLUGIN_FIELDS = %w[bpm:minifier]
|
33
34
|
|
34
35
|
# Fields that can be loaded straight into the gemspec
|
35
36
|
SPEC_FIELDS = %w[name email]
|
@@ -75,9 +76,9 @@ module BPM
|
|
75
76
|
spec.licenses = licenses.map{|l| l["type"]}
|
76
77
|
spec.executables = bin_files.map{|p| File.basename(p) } if bin_path
|
77
78
|
|
78
|
-
spec.homepage = homepage || url
|
79
|
-
spec.description = description || summary
|
80
|
-
spec.summary = summary || description
|
79
|
+
spec.homepage = self.homepage || self.url
|
80
|
+
spec.description = self.description || self.summary
|
81
|
+
spec.summary = self.summary || self.description
|
81
82
|
|
82
83
|
metadata = Hash[METADATA_FIELDS.map{|f| [f, send(c2u(f)) ] }]
|
83
84
|
spec.requirements = [metadata.to_json]
|
@@ -124,6 +125,14 @@ module BPM
|
|
124
125
|
as_json.to_json
|
125
126
|
end
|
126
127
|
|
128
|
+
def shell
|
129
|
+
@shell ||= Thor::Base.shell.new
|
130
|
+
end
|
131
|
+
|
132
|
+
def say(*args)
|
133
|
+
shell.say *args
|
134
|
+
end
|
135
|
+
|
127
136
|
def full_name
|
128
137
|
"#{name}-#{version}"
|
129
138
|
end
|
@@ -133,7 +142,10 @@ module BPM
|
|
133
142
|
end
|
134
143
|
|
135
144
|
def directory_files
|
136
|
-
dir_names =
|
145
|
+
dir_names = [bin_path, lib_path, tests_path]
|
146
|
+
dir_names += directories.reject { |k,_| dir_names.include?(k) }.values
|
147
|
+
dir_names.reject! { |t| t == tests_path }
|
148
|
+
|
137
149
|
build_names = bpm_build.values.map do |hash|
|
138
150
|
hash['directories'] || hash['assets']
|
139
151
|
end
|
@@ -144,6 +156,12 @@ module BPM
|
|
144
156
|
val
|
145
157
|
end
|
146
158
|
|
159
|
+
bpm_provides.each do |_,values|
|
160
|
+
val = values['main']
|
161
|
+
val = val && val =~ /^#{name}\// ? val[name.size+1..-1]+'.js' : nil
|
162
|
+
build_names << val if val
|
163
|
+
end
|
164
|
+
|
147
165
|
(dir_names+build_names).flatten.compact.uniq.map do |dir|
|
148
166
|
glob_files(dir)
|
149
167
|
end.flatten
|
@@ -207,6 +225,12 @@ module BPM
|
|
207
225
|
ret.merge! minifier
|
208
226
|
end
|
209
227
|
end
|
228
|
+
|
229
|
+
bpm_provides.each do |_,opts|
|
230
|
+
next unless opts.is_a?(Hash) && opts['dependencies']
|
231
|
+
ret.merge! opts['dependencies']
|
232
|
+
end
|
233
|
+
|
210
234
|
ret
|
211
235
|
end
|
212
236
|
|
@@ -233,12 +257,12 @@ module BPM
|
|
233
257
|
end
|
234
258
|
|
235
259
|
def has_json?
|
236
|
-
File.exist?(json_path)
|
260
|
+
!!json_path && File.exist?(json_path)
|
237
261
|
end
|
238
262
|
|
239
263
|
def validate_name_and_path
|
240
264
|
filename = File.basename(root_path)
|
241
|
-
unless filename==name || filename=="#{name}-#{version}"
|
265
|
+
unless name.nil? || name.empty? || filename==name || filename=="#{name}-#{version}"
|
242
266
|
raise BPM::InvalidPackageNameError.new self
|
243
267
|
end
|
244
268
|
end
|
@@ -276,6 +300,10 @@ module BPM
|
|
276
300
|
self.author = spec.authors.first
|
277
301
|
self.version = spec.version.to_s
|
278
302
|
|
303
|
+
self.description = spec.description
|
304
|
+
self.summary = spec.summary
|
305
|
+
self.homepage = spec.homepage
|
306
|
+
|
279
307
|
metadata = spec.requirements.first
|
280
308
|
if metadata
|
281
309
|
metadata = JSON.parse(metadata)
|
@@ -311,6 +339,69 @@ module BPM
|
|
311
339
|
ret
|
312
340
|
end
|
313
341
|
|
342
|
+
def merged_dependencies(*kinds)
|
343
|
+
kinds.inject({}) do |ret, kind|
|
344
|
+
deps = case kind
|
345
|
+
when :runtime
|
346
|
+
dependencies
|
347
|
+
when :development
|
348
|
+
dependencies_development
|
349
|
+
when :build
|
350
|
+
dependencies_build
|
351
|
+
end
|
352
|
+
ret.merge! deps
|
353
|
+
end
|
354
|
+
end
|
355
|
+
|
356
|
+
def used_dependencies(project)
|
357
|
+
if project.has_local_package?(self.name)
|
358
|
+
merged_dependencies(:runtime, :development)
|
359
|
+
else
|
360
|
+
merged_dependencies(:runtime)
|
361
|
+
end
|
362
|
+
end
|
363
|
+
|
364
|
+
def provided_formats
|
365
|
+
ret = {}
|
366
|
+
bpm_provides.each do | key, opts |
|
367
|
+
ret[key[7..-1]] = opts if key =~ /^format:/
|
368
|
+
end
|
369
|
+
ret
|
370
|
+
end
|
371
|
+
|
372
|
+
def used_formats(project)
|
373
|
+
pkgs=project.map_to_packages used_dependencies(project)
|
374
|
+
pkgs.inject({}) { |ret, pkg| ret.merge!(pkg.provided_formats) }
|
375
|
+
end
|
376
|
+
|
377
|
+
def provided_preprocessors
|
378
|
+
bpm_provides['preprocessors'] || []
|
379
|
+
end
|
380
|
+
|
381
|
+
def used_preprocessors(project)
|
382
|
+
pkgs=project.map_to_packages used_dependencies(project)
|
383
|
+
pkgs.map { |pkg| pkg.provided_postprocessors }.flatten
|
384
|
+
end
|
385
|
+
|
386
|
+
def provided_postprocessors
|
387
|
+
bpm_provides['postprocessors'] || []
|
388
|
+
end
|
389
|
+
|
390
|
+
def used_postprocessors(project)
|
391
|
+
pkgs=project.map_to_packages used_dependencies(project)
|
392
|
+
pkgs.map { |pkg| pkg.provided_postprocessors }.flatten
|
393
|
+
end
|
394
|
+
|
395
|
+
def provided_transport
|
396
|
+
bpm_provides['transport']
|
397
|
+
end
|
398
|
+
|
399
|
+
def used_transports(project)
|
400
|
+
pkgs=project.map_to_packages used_dependencies(project)
|
401
|
+
pkgs.map { |pkg| pkg.provided_transport }.compact.flatten
|
402
|
+
end
|
403
|
+
|
404
|
+
|
314
405
|
# TODO: Make better errors
|
315
406
|
# TODO: This might not work well with conflicting versions
|
316
407
|
def local_deps(search_path=nil)
|
@@ -395,15 +486,26 @@ module BPM
|
|
395
486
|
end
|
396
487
|
|
397
488
|
def validate_summary
|
398
|
-
summary || description
|
489
|
+
if (summary.nil? || summary.empty?) && (description.nil? || description.empty?)
|
490
|
+
add_error "Package requires a 'summary' field"
|
491
|
+
add_error "Package requires a 'description' field"
|
492
|
+
false
|
493
|
+
else
|
494
|
+
true
|
495
|
+
end
|
399
496
|
end
|
400
497
|
|
401
498
|
def validate_homepage
|
402
|
-
homepage || url
|
499
|
+
if (homepage.nil? || homepage.empty?) && (url.nil? || url.empty?)
|
500
|
+
add_error "Package requires a 'homepage' field"
|
501
|
+
false
|
502
|
+
else
|
503
|
+
true
|
504
|
+
end
|
403
505
|
end
|
404
506
|
|
405
507
|
def add_error(message)
|
406
|
-
self.errors << message
|
508
|
+
self.errors << message unless self.errors.include?(message)
|
407
509
|
end
|
408
510
|
|
409
511
|
def glob_files(path)
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'sprockets'
|
2
|
+
|
3
|
+
module BPM
|
4
|
+
|
5
|
+
# A Template that will use a format plugin to compile the content
|
6
|
+
# Register a subclass of the template with the with_plugin
|
7
|
+
class FormatProcessor < BPM::PluginProcessor
|
8
|
+
|
9
|
+
def self.with_plugin(ext, plugin_opts)
|
10
|
+
ret = super plugin_opts, 'compileFormat'
|
11
|
+
ret.instance_eval do
|
12
|
+
@extension = ext
|
13
|
+
end
|
14
|
+
ret
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.extension
|
18
|
+
@extension
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.default_mime_type
|
22
|
+
@plugin_opts["mime:default"]
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
|
@@ -74,9 +74,9 @@ module BPM
|
|
74
74
|
private
|
75
75
|
|
76
76
|
def build_source
|
77
|
-
|
77
|
+
BPM::GeneratedAsset.push_generating_asset self
|
78
78
|
ret = minify super
|
79
|
-
|
79
|
+
BPM::GeneratedAsset.pop_generating_asset
|
80
80
|
ret
|
81
81
|
end
|
82
82
|
|
@@ -0,0 +1,79 @@
|
|
1
|
+
require 'sprockets'
|
2
|
+
|
3
|
+
module BPM
|
4
|
+
|
5
|
+
# A sub-environment created for each package in the project. Requests for
|
6
|
+
# individual assets will usually end up going through one of these
|
7
|
+
# instances. This allows each package to have its own set of processors
|
8
|
+
# for each file.
|
9
|
+
class PackagePipeline < Sprockets::Environment
|
10
|
+
|
11
|
+
attr_reader :pipeline, :package
|
12
|
+
|
13
|
+
def shell
|
14
|
+
@shell ||= Thor::Base.shell.new
|
15
|
+
end
|
16
|
+
|
17
|
+
def initialize(pipeline, package)
|
18
|
+
@pipeline = pipeline
|
19
|
+
@package = package
|
20
|
+
|
21
|
+
super package.root_path
|
22
|
+
|
23
|
+
%w(text/css application/javascript).each do |kind|
|
24
|
+
unregister_processor kind, Sprockets::DirectiveProcessor
|
25
|
+
register_processor kind, BPM::DirectiveProcessor
|
26
|
+
end
|
27
|
+
|
28
|
+
# This gunks things up. I'm not a fan - PDW
|
29
|
+
unregister_postprocessor 'application/javascript', Sprockets::SafetyColons
|
30
|
+
|
31
|
+
package.used_formats(project).each do |ext, opts|
|
32
|
+
register_engine ".#{ext}", BPM::FormatProcessor.with_plugin(ext,opts)
|
33
|
+
end
|
34
|
+
|
35
|
+
package.used_preprocessors(project).each do |opts|
|
36
|
+
register_preprocessor opts['mime'],
|
37
|
+
BPM::PluginProcessor.with_plugin(opts, 'preprocess')
|
38
|
+
end
|
39
|
+
|
40
|
+
package.used_postprocessors(project).each do |opts|
|
41
|
+
register_postprocessor opts['mime'],
|
42
|
+
BPM::PluginProcessor.with_plugin(opts, 'postprocess')
|
43
|
+
end
|
44
|
+
|
45
|
+
opts = package.used_transports(project)
|
46
|
+
raise TooManyTransportsError(package) if opts.size>1
|
47
|
+
if opts.size>0
|
48
|
+
register_postprocessor 'application/javascript',
|
49
|
+
BPM::PluginProcessor.with_plugin(opts.first, 'compileTransport')
|
50
|
+
end
|
51
|
+
|
52
|
+
append_path package.root_path
|
53
|
+
end
|
54
|
+
|
55
|
+
def package_name
|
56
|
+
package.name
|
57
|
+
end
|
58
|
+
|
59
|
+
def project
|
60
|
+
pipeline.project
|
61
|
+
end
|
62
|
+
|
63
|
+
def mode
|
64
|
+
pipeline.mode
|
65
|
+
end
|
66
|
+
|
67
|
+
def plugin_context_for(logical_path)
|
68
|
+
pipeline.plugin_context_for logical_path
|
69
|
+
end
|
70
|
+
|
71
|
+
def resolve(*args)
|
72
|
+
super *args
|
73
|
+
rescue Sprockets::FileNotFound => e
|
74
|
+
raise Sprockets::FileNotFound, "#{e.message} in package '#{package_name}'"
|
75
|
+
end
|
76
|
+
|
77
|
+
|
78
|
+
end
|
79
|
+
end
|
@@ -5,7 +5,7 @@ module BPM
|
|
5
5
|
# Defines an asset that represents a build plugin (such as a transport or
|
6
6
|
# a minifier.) The generated asset will include dependencies of the plugin
|
7
7
|
# module as well as the module itself.
|
8
|
-
class PluginAsset <
|
8
|
+
class PluginAsset < BPM::GeneratedAsset
|
9
9
|
|
10
10
|
def initialize(environment, module_name)
|
11
11
|
pathname = Pathname.new(File.join(environment.project.root_path, '.bpm', 'plugins', module_name+'.js'))
|
@@ -18,15 +18,14 @@ module BPM
|
|
18
18
|
super(environment, module_name, pathname, {})
|
19
19
|
end
|
20
20
|
|
21
|
-
protected
|
22
|
-
|
23
|
-
def dependency_context_and_body
|
24
|
-
@dependency_context_and_body ||= build_dependency_context_and_body
|
25
|
-
end
|
26
|
-
|
27
21
|
private
|
28
22
|
|
29
|
-
#
|
23
|
+
# do not minify plugin assets
|
24
|
+
def minify(hash)
|
25
|
+
hash
|
26
|
+
end
|
27
|
+
|
28
|
+
# Note: logical path must be the module
|
30
29
|
def plugin_module
|
31
30
|
project = environment.project
|
32
31
|
parts = logical_path.split('/')
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'sprockets'
|
2
|
+
|
3
|
+
module BPM
|
4
|
+
|
5
|
+
# A processor that will invoke a JavaScript-based plugin provided by a
|
6
|
+
# package in the system. The passed method name will be invoked on the
|
7
|
+
# plugin.
|
8
|
+
class PluginProcessor < Tilt::Template
|
9
|
+
|
10
|
+
def self.with_plugin(plugin_opts, method_name)
|
11
|
+
ret = Class.new(self)
|
12
|
+
ret.instance_eval do
|
13
|
+
@method_name = method_name
|
14
|
+
@plugin_opts = plugin_opts
|
15
|
+
end
|
16
|
+
ret
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.method_name
|
20
|
+
@method_name
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.plugin_name
|
24
|
+
@plugin_opts["main"]
|
25
|
+
end
|
26
|
+
|
27
|
+
def prepare
|
28
|
+
end
|
29
|
+
|
30
|
+
def evaluate(context, locals, &block)
|
31
|
+
ctx = context.environment.plugin_context_for self.class.plugin_name
|
32
|
+
project = context.environment.project
|
33
|
+
pkg, module_id = project.package_and_module_from_path file
|
34
|
+
|
35
|
+
filepath = file.to_s
|
36
|
+
out = ''
|
37
|
+
|
38
|
+
V8::C::Locker() do
|
39
|
+
ctx["DATA"] = data
|
40
|
+
ctx["CTX"] = BPM::PluginContext.new(pkg, module_id)
|
41
|
+
out = ctx.eval("BPM_PLUGIN.#{self.class.method_name}(DATA, CTX, '#{filepath}');")
|
42
|
+
end
|
43
|
+
|
44
|
+
out
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
|
51
|
+
|
52
|
+
|
data/lib/bpm/pipeline.rb
CHANGED
@@ -5,8 +5,15 @@ module BPM
|
|
5
5
|
|
6
6
|
class Console
|
7
7
|
def log(str)
|
8
|
-
|
8
|
+
shell.say str
|
9
9
|
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def shell
|
14
|
+
@shell ||= Thor::Base.shell.new
|
15
|
+
end
|
16
|
+
|
10
17
|
end
|
11
18
|
|
12
19
|
# A BPM package-aware asset pipeline. Asset lookup respects package.json
|
@@ -17,6 +24,7 @@ module BPM
|
|
17
24
|
|
18
25
|
attr_reader :project
|
19
26
|
attr_reader :mode
|
27
|
+
attr_reader :package_pipelines
|
20
28
|
|
21
29
|
# Pass in the project you want the pipeline to manage.
|
22
30
|
def initialize(project, mode = :debug, include_preview = false)
|
@@ -24,34 +32,84 @@ module BPM
|
|
24
32
|
@project = project
|
25
33
|
@mode = mode
|
26
34
|
@plugin_contexts = {}
|
35
|
+
|
36
|
+
# Create a pipeline for each package. Will be used for searching.
|
37
|
+
@package_pipelines = project.local_deps.map do |pkg|
|
38
|
+
BPM::PackagePipeline.new self, pkg
|
39
|
+
end
|
40
|
+
@package_pipelines << BPM::PackagePipeline.new(self, project)
|
27
41
|
|
28
42
|
project_path = project.root_path
|
29
43
|
|
30
44
|
super project_path
|
31
45
|
|
32
|
-
#
|
46
|
+
# Unregister built-in processors. We want most things served by the
|
47
|
+
# pipeline directly to just pass through. (package pipelines do the
|
48
|
+
# processing)
|
33
49
|
%w(text/css application/javascript).each do |kind|
|
34
50
|
unregister_processor kind, Sprockets::DirectiveProcessor
|
35
|
-
register_processor kind, BPM::DirectiveProcessor
|
36
51
|
end
|
37
|
-
|
38
|
-
register_postprocessor 'application/javascript', BPM::TransportProcessor
|
39
|
-
#register_postprocessor 'application/javascript', BPM::SourceURLProcessor
|
40
|
-
|
41
|
-
# This gunks things up. I'm not a fan - PDW
|
42
52
|
unregister_postprocessor 'application/javascript', Sprockets::SafetyColons
|
43
53
|
|
44
54
|
# configure search paths
|
45
|
-
append_path File.join project_path, '.bpm', 'packages'
|
46
|
-
append_path File.dirname project_path
|
47
55
|
append_path project.assets_root
|
48
56
|
append_path project.preview_root if include_preview
|
49
57
|
end
|
50
|
-
|
51
|
-
|
52
|
-
|
58
|
+
|
59
|
+
# determines the proper pipeline for the path
|
60
|
+
def pipeline_for(path)
|
61
|
+
return nil if magic_paths.include?(path)
|
62
|
+
package_pipelines.find do |cur_pipeline|
|
63
|
+
path.to_s[cur_pipeline.package.root_path.to_s]
|
64
|
+
end
|
53
65
|
end
|
54
66
|
|
67
|
+
def attributes_for(path)
|
68
|
+
if path.to_s[File.join(project.root_path, '.bpm')] || !Pathname.new(path).absolute?
|
69
|
+
return super(path)
|
70
|
+
end
|
71
|
+
|
72
|
+
pipeline = pipeline_for path
|
73
|
+
pipeline ? pipeline.attributes_for(path) : super(path)
|
74
|
+
end
|
75
|
+
|
76
|
+
def resolve(logical_path, options={}, &block)
|
77
|
+
|
78
|
+
magic_path = magic_paths.find do |path|
|
79
|
+
path =~ /#{Regexp.escape logical_path.to_s}(\..+)?$/
|
80
|
+
end
|
81
|
+
|
82
|
+
package_name = logical_path.to_s.sub(/#{Regexp.escape File::SEPARATOR}.+/,'')
|
83
|
+
pipeline = package_pipelines.find do |cur_pipeline|
|
84
|
+
cur_pipeline.package_name == package_name
|
85
|
+
end
|
86
|
+
|
87
|
+
if pipeline && magic_path.nil?
|
88
|
+
logical_path = logical_path.to_s[package_name.size+1..-1]
|
89
|
+
pipeline.resolve Pathname.new(logical_path), options, &block
|
90
|
+
else
|
91
|
+
super logical_path, options, &block
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
95
|
+
|
96
|
+
# Detect whenever we are asked to build some of the magic files and swap
|
97
|
+
# in a custom asset type that can generate the contents.
|
98
|
+
def build_asset(logical_path, pathname, options)
|
99
|
+
if magic_paths.include? pathname.to_s
|
100
|
+
BPM::GeneratedAsset.new(self, logical_path, pathname, options)
|
101
|
+
elsif pipeline = pipeline_for(pathname)
|
102
|
+
pipeline.build_asset logical_path, pathname, options
|
103
|
+
else
|
104
|
+
super logical_path, pathname, options
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
# Paths to files that should be built.
|
109
|
+
def magic_paths
|
110
|
+
@magic_paths ||= build_magic_paths
|
111
|
+
end
|
112
|
+
|
55
113
|
# Returns an array of all the buildable assets in the current directory.
|
56
114
|
# These are the assets that will be built when you compile the project.
|
57
115
|
def buildable_assets
|
@@ -85,29 +143,34 @@ module BPM
|
|
85
143
|
|
86
144
|
ret.sort.map { |x| find_asset x }.compact
|
87
145
|
end
|
146
|
+
|
147
|
+
def plugin_context_for(logical_path)
|
148
|
+
@plugin_contexts[logical_path] ||= build_plugin_context(logical_path)
|
149
|
+
end
|
88
150
|
|
89
|
-
|
90
|
-
|
91
|
-
def
|
151
|
+
protected
|
152
|
+
|
153
|
+
def build_magic_paths
|
92
154
|
magic_paths = project.buildable_asset_filenames(mode).map do |filename|
|
93
155
|
project.assets_root filename
|
94
156
|
end
|
95
|
-
|
157
|
+
|
96
158
|
magic_paths += project.buildable_asset_filenames(mode).map do |filename|
|
97
159
|
project.preview_root filename
|
98
160
|
end
|
99
|
-
|
100
|
-
if magic_paths.include? pathname.to_s
|
101
|
-
BPM::GeneratedAsset.new(self, logical_path, pathname, options)
|
102
|
-
else
|
103
|
-
super logical_path, pathname, options
|
104
|
-
end
|
105
161
|
end
|
106
|
-
|
162
|
+
|
163
|
+
# Pass along to package pipelines
|
164
|
+
def expire_index!
|
165
|
+
super
|
166
|
+
@magic_paths = nil
|
167
|
+
package_pipelines.each { |pipeline| pipeline.expire_index! }
|
168
|
+
end
|
169
|
+
|
107
170
|
private
|
108
171
|
|
109
|
-
def build_plugin_context(
|
110
|
-
asset = BPM::PluginAsset.new(self,
|
172
|
+
def build_plugin_context(logical_path)
|
173
|
+
asset = BPM::PluginAsset.new(self, logical_path)
|
111
174
|
plugin_text = asset.to_s
|
112
175
|
|
113
176
|
ctx = nil
|