sprockets 2.3.2 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of sprockets might be problematic. Click here for more details.

Files changed (84) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +2 -2
  3. data/README.md +332 -115
  4. data/bin/sprockets +8 -0
  5. data/lib/rake/sprocketstask.rb +25 -13
  6. data/lib/sprockets/asset.rb +143 -205
  7. data/lib/sprockets/autoload/closure.rb +7 -0
  8. data/lib/sprockets/autoload/coffee_script.rb +7 -0
  9. data/lib/sprockets/autoload/eco.rb +7 -0
  10. data/lib/sprockets/autoload/ejs.rb +7 -0
  11. data/lib/sprockets/autoload/sass.rb +7 -0
  12. data/lib/sprockets/autoload/uglifier.rb +7 -0
  13. data/lib/sprockets/autoload/yui.rb +7 -0
  14. data/lib/sprockets/autoload.rb +11 -0
  15. data/lib/sprockets/base.rb +49 -257
  16. data/lib/sprockets/bower.rb +58 -0
  17. data/lib/sprockets/bundle.rb +65 -0
  18. data/lib/sprockets/cache/file_store.rb +165 -14
  19. data/lib/sprockets/cache/memory_store.rb +66 -0
  20. data/lib/sprockets/cache/null_store.rb +46 -0
  21. data/lib/sprockets/cache.rb +234 -0
  22. data/lib/sprockets/cached_environment.rb +69 -0
  23. data/lib/sprockets/closure_compressor.rb +53 -0
  24. data/lib/sprockets/coffee_script_processor.rb +25 -0
  25. data/lib/sprockets/coffee_script_template.rb +6 -0
  26. data/lib/sprockets/compressing.rb +74 -0
  27. data/lib/sprockets/configuration.rb +83 -0
  28. data/lib/sprockets/context.rb +125 -131
  29. data/lib/sprockets/dependencies.rb +73 -0
  30. data/lib/sprockets/digest_utils.rb +156 -0
  31. data/lib/sprockets/directive_processor.rb +209 -211
  32. data/lib/sprockets/eco_processor.rb +32 -0
  33. data/lib/sprockets/eco_template.rb +3 -35
  34. data/lib/sprockets/ejs_processor.rb +31 -0
  35. data/lib/sprockets/ejs_template.rb +3 -34
  36. data/lib/sprockets/encoding_utils.rb +258 -0
  37. data/lib/sprockets/engines.rb +45 -38
  38. data/lib/sprockets/environment.rb +17 -67
  39. data/lib/sprockets/erb_processor.rb +30 -0
  40. data/lib/sprockets/erb_template.rb +6 -0
  41. data/lib/sprockets/errors.rb +6 -13
  42. data/lib/sprockets/file_reader.rb +15 -0
  43. data/lib/sprockets/http_utils.rb +115 -0
  44. data/lib/sprockets/jst_processor.rb +35 -19
  45. data/lib/sprockets/legacy.rb +314 -0
  46. data/lib/sprockets/legacy_proc_processor.rb +35 -0
  47. data/lib/sprockets/legacy_tilt_processor.rb +29 -0
  48. data/lib/sprockets/loader.rb +176 -0
  49. data/lib/sprockets/manifest.rb +179 -98
  50. data/lib/sprockets/manifest_utils.rb +45 -0
  51. data/lib/sprockets/mime.rb +114 -32
  52. data/lib/sprockets/path_dependency_utils.rb +85 -0
  53. data/lib/sprockets/path_digest_utils.rb +47 -0
  54. data/lib/sprockets/path_utils.rb +282 -0
  55. data/lib/sprockets/paths.rb +81 -0
  56. data/lib/sprockets/processing.rb +157 -189
  57. data/lib/sprockets/processor_utils.rb +103 -0
  58. data/lib/sprockets/resolve.rb +208 -0
  59. data/lib/sprockets/sass_cache_store.rb +19 -15
  60. data/lib/sprockets/sass_compressor.rb +59 -0
  61. data/lib/sprockets/sass_functions.rb +2 -0
  62. data/lib/sprockets/sass_importer.rb +2 -29
  63. data/lib/sprockets/sass_processor.rb +285 -0
  64. data/lib/sprockets/sass_template.rb +4 -44
  65. data/lib/sprockets/server.rb +109 -84
  66. data/lib/sprockets/transformers.rb +145 -0
  67. data/lib/sprockets/uglifier_compressor.rb +63 -0
  68. data/lib/sprockets/uri_utils.rb +190 -0
  69. data/lib/sprockets/utils.rb +193 -44
  70. data/lib/sprockets/version.rb +1 -1
  71. data/lib/sprockets/yui_compressor.rb +65 -0
  72. data/lib/sprockets.rb +144 -53
  73. metadata +248 -238
  74. data/lib/sprockets/asset_attributes.rb +0 -126
  75. data/lib/sprockets/bundled_asset.rb +0 -79
  76. data/lib/sprockets/caching.rb +0 -96
  77. data/lib/sprockets/charset_normalizer.rb +0 -41
  78. data/lib/sprockets/index.rb +0 -99
  79. data/lib/sprockets/processed_asset.rb +0 -152
  80. data/lib/sprockets/processor.rb +0 -32
  81. data/lib/sprockets/safety_colons.rb +0 -28
  82. data/lib/sprockets/scss_template.rb +0 -13
  83. data/lib/sprockets/static_asset.rb +0 -57
  84. data/lib/sprockets/trail.rb +0 -90
@@ -1,79 +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
- attr_reader :source
12
-
13
- def initialize(environment, logical_path, pathname)
14
- super(environment, logical_path, pathname)
15
-
16
- @processed_asset = environment.find_asset(pathname, :bundle => false)
17
- @required_assets = @processed_asset.required_assets
18
-
19
- @source = ""
20
-
21
- # Explode Asset into parts and gather the dependency bodies
22
- to_a.each { |dependency| @source << dependency.to_s }
23
-
24
- # Run bundle processors on concatenated source
25
- context = environment.context_class.new(environment, logical_path, pathname)
26
- @source = context.evaluate(pathname, :data => @source,
27
- :processors => environment.bundle_processors(content_type))
28
-
29
- @mtime = to_a.map(&:mtime).max
30
- @length = Rack::Utils.bytesize(source)
31
- @digest = environment.digest.update(source).hexdigest
32
- end
33
-
34
- # Initialize `BundledAsset` from serialized `Hash`.
35
- def init_with(environment, coder)
36
- super
37
-
38
- @processed_asset = environment.find_asset(pathname, :bundle => false)
39
- @required_assets = @processed_asset.required_assets
40
-
41
- if @processed_asset.dependency_digest != coder['required_assets_digest']
42
- raise UnserializeError, "processed asset belongs to a stale environment"
43
- end
44
-
45
- @source = coder['source']
46
- end
47
-
48
- # Serialize custom attributes in `BundledAsset`.
49
- def encode_with(coder)
50
- super
51
-
52
- coder['source'] = source
53
- coder['required_assets_digest'] = @processed_asset.dependency_digest
54
- end
55
-
56
- # Get asset's own processed contents. Excludes any of its required
57
- # dependencies but does run any processors or engines on the
58
- # original file.
59
- def body
60
- @processed_asset.source
61
- end
62
-
63
- # Return an `Array` of `Asset` files that are declared dependencies.
64
- def dependencies
65
- to_a.reject { |a| a.eql?(@processed_asset) }
66
- end
67
-
68
- # Expand asset into an `Array` of parts.
69
- def to_a
70
- required_assets
71
- end
72
-
73
- # Checks if Asset is stale by comparing the actual mtime and
74
- # digest to the inmemory model.
75
- def fresh?(environment)
76
- @processed_asset.fresh?(environment)
77
- end
78
- end
79
- end
@@ -1,96 +0,0 @@
1
- module Sprockets
2
- # `Caching` is an internal mixin whose public methods are exposed on
3
- # the `Environment` and `Index` classes.
4
- module Caching
5
- # Low level cache getter for `key`. Checks a number of supported
6
- # cache interfaces.
7
- def cache_get(key)
8
- # `Cache#get(key)` for Memcache
9
- if cache.respond_to?(:get)
10
- cache.get(key)
11
-
12
- # `Cache#[key]` so `Hash` can be used
13
- elsif cache.respond_to?(:[])
14
- cache[key]
15
-
16
- # `Cache#read(key)` for `ActiveSupport::Cache` support
17
- elsif cache.respond_to?(:read)
18
- cache.read(key)
19
-
20
- else
21
- nil
22
- end
23
- end
24
-
25
- # Low level cache setter for `key`. Checks a number of supported
26
- # cache interfaces.
27
- def cache_set(key, value)
28
- # `Cache#set(key, value)` for Memcache
29
- if cache.respond_to?(:set)
30
- cache.set(key, value)
31
-
32
- # `Cache#[key]=value` so `Hash` can be used
33
- elsif cache.respond_to?(:[]=)
34
- cache[key] = value
35
-
36
- # `Cache#write(key, value)` for `ActiveSupport::Cache` support
37
- elsif cache.respond_to?(:write)
38
- cache.write(key, value)
39
- end
40
-
41
- value
42
- end
43
-
44
- protected
45
- # Cache helper method. Takes a `path` argument which maybe a
46
- # logical path or fully expanded path. The `&block` is passed
47
- # for finding and building the asset if its not in cache.
48
- def cache_asset(path)
49
- # If `cache` is not set, return fast
50
- if cache.nil?
51
- yield
52
-
53
- # Check cache for `path`
54
- elsif (asset = Asset.from_hash(self, cache_get_hash(path.to_s))) && asset.fresh?(self)
55
- asset
56
-
57
- # Otherwise yield block that slowly finds and builds the asset
58
- elsif asset = yield
59
- hash = {}
60
- asset.encode_with(hash)
61
-
62
- # Save the asset to its path
63
- cache_set_hash(path.to_s, hash)
64
-
65
- # Since path maybe a logical or full pathname, save the
66
- # asset its its full path too
67
- if path.to_s != asset.pathname.to_s
68
- cache_set_hash(asset.pathname.to_s, hash)
69
- end
70
-
71
- asset
72
- end
73
- end
74
-
75
- private
76
- # Strips `Environment#root` from key to make the key work
77
- # consisently across different servers. The key is also hashed
78
- # so it does not exceed 250 characters.
79
- def expand_cache_key(key)
80
- File.join('sprockets', digest_class.hexdigest(key.sub(root, '')))
81
- end
82
-
83
- def cache_get_hash(key)
84
- hash = cache_get(expand_cache_key(key))
85
- if hash.is_a?(Hash) && digest.hexdigest == hash['_version']
86
- hash
87
- end
88
- end
89
-
90
- def cache_set_hash(key, hash)
91
- hash['_version'] = digest.hexdigest
92
- cache_set(expand_cache_key(key), hash)
93
- hash
94
- end
95
- end
96
- end
@@ -1,41 +0,0 @@
1
- require 'tilt'
2
-
3
- module Sprockets
4
- # Some browsers have issues with stylesheets that contain multiple
5
- # `@charset` definitions. The issue surfaces while using Sass since
6
- # it inserts a `@charset` at the top of each file. Then Sprockets
7
- # concatenates them together.
8
- #
9
- # The `CharsetNormalizer` processor strips out multiple `@charset`
10
- # definitions.
11
- #
12
- # The current implementation is naive. It picks the first `@charset`
13
- # it sees and strips the others. This works for most people because
14
- # the other definitions are usually `UTF-8`. A more sophisticated
15
- # approach would be to re-encode stylesheets with mixed encodings.
16
- #
17
- # This behavior can be disabled with:
18
- #
19
- # environment.unregister_bundle_processor 'text/css', Sprockets::CharsetNormalizer
20
- #
21
- class CharsetNormalizer < Tilt::Template
22
- def prepare
23
- end
24
-
25
- def evaluate(context, locals, &block)
26
- charset = nil
27
-
28
- # Find and strip out any `@charset` definitions
29
- filtered_data = data.gsub(/^@charset "([^"]+)";$/) {
30
- charset ||= $1; ""
31
- }
32
-
33
- if charset
34
- # If there was a charset, move it to the top
35
- "@charset \"#{charset}\";#{filtered_data}"
36
- else
37
- data
38
- end
39
- end
40
- end
41
- end
@@ -1,99 +0,0 @@
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
- @environment = environment
16
-
17
- if environment.respond_to?(:default_external_encoding)
18
- @default_external_encoding = environment.default_external_encoding
19
- end
20
-
21
- # Copy environment attributes
22
- @logger = environment.logger
23
- @context_class = environment.context_class
24
- @cache = environment.cache
25
- @trail = environment.trail.index
26
- @digest = environment.digest
27
- @digest_class = environment.digest_class
28
- @version = environment.version
29
- @mime_types = environment.mime_types
30
- @engines = environment.engines
31
- @preprocessors = environment.preprocessors
32
- @postprocessors = environment.postprocessors
33
- @bundle_processors = environment.bundle_processors
34
-
35
- # Initialize caches
36
- @assets = {}
37
- @digests = {}
38
- end
39
-
40
- # No-op return self as index
41
- def index
42
- self
43
- end
44
-
45
- # Cache calls to `file_digest`
46
- def file_digest(pathname)
47
- key = pathname.to_s
48
- if @digests.key?(key)
49
- @digests[key]
50
- else
51
- @digests[key] = super
52
- end
53
- end
54
-
55
- # Cache `find_asset` calls
56
- def find_asset(path, options = {})
57
- options[:bundle] = true unless options.key?(:bundle)
58
- if asset = @assets[cache_key_for(path, options)]
59
- asset
60
- elsif asset = super
61
- logical_path_cache_key = cache_key_for(path, options)
62
- full_path_cache_key = cache_key_for(asset.pathname, options)
63
-
64
- # Cache on Index
65
- @assets[logical_path_cache_key] = @assets[full_path_cache_key] = asset
66
-
67
- # Push cache upstream to Environment
68
- @environment.instance_eval do
69
- @assets[logical_path_cache_key] = @assets[full_path_cache_key] = asset
70
- end
71
-
72
- asset
73
- end
74
- end
75
-
76
- protected
77
- # Index is immutable, any methods that try to clear the cache
78
- # should bomb.
79
- def expire_index!
80
- raise TypeError, "can't modify immutable index"
81
- end
82
-
83
- # Cache asset building in memory and in persisted cache.
84
- def build_asset(path, pathname, options)
85
- # Memory cache
86
- key = cache_key_for(pathname, options)
87
- if @assets.key?(key)
88
- @assets[key]
89
- else
90
- @assets[key] = begin
91
- # Persisted cache
92
- cache_asset(key) do
93
- super
94
- end
95
- end
96
- end
97
- end
98
- end
99
- end
@@ -1,152 +0,0 @@
1
- require 'sprockets/asset'
2
- require 'sprockets/utils'
3
-
4
- module Sprockets
5
- class ProcessedAsset < Asset
6
- def initialize(environment, logical_path, pathname)
7
- super
8
-
9
- start_time = Time.now.to_f
10
-
11
- context = environment.context_class.new(environment, logical_path, pathname)
12
- @source = context.evaluate(pathname)
13
- @length = Rack::Utils.bytesize(source)
14
- @digest = environment.digest.update(source).hexdigest
15
-
16
- build_required_assets(environment, context)
17
- build_dependency_paths(environment, context)
18
-
19
- @dependency_digest = compute_dependency_digest(environment)
20
-
21
- elapsed_time = ((Time.now.to_f - start_time) * 1000).to_i
22
- environment.logger.info "Compiled #{logical_path} (#{elapsed_time}ms) (pid #{Process.pid})"
23
- end
24
-
25
- # Interal: Used to check equality
26
- attr_reader :dependency_digest
27
-
28
- attr_reader :source
29
-
30
- # Initialize `BundledAsset` from serialized `Hash`.
31
- def init_with(environment, coder)
32
- super
33
-
34
- @source = coder['source']
35
- @dependency_digest = coder['dependency_digest']
36
-
37
- @required_assets = coder['required_paths'].map { |p|
38
- p = expand_root_path(p)
39
-
40
- unless environment.paths.detect { |path| p[path] }
41
- raise UnserializeError, "#{p} isn't in paths"
42
- end
43
-
44
- p == pathname.to_s ? self : environment.find_asset(p, :bundle => false)
45
- }
46
- @dependency_paths = coder['dependency_paths'].map { |h|
47
- DependencyFile.new(expand_root_path(h['path']), h['mtime'], h['digest'])
48
- }
49
- end
50
-
51
- # Serialize custom attributes in `BundledAsset`.
52
- def encode_with(coder)
53
- super
54
-
55
- coder['source'] = source
56
- coder['dependency_digest'] = dependency_digest
57
-
58
- coder['required_paths'] = required_assets.map { |a|
59
- relativize_root_path(a.pathname).to_s
60
- }
61
- coder['dependency_paths'] = dependency_paths.map { |d|
62
- { 'path' => relativize_root_path(d.pathname).to_s,
63
- 'mtime' => d.mtime.iso8601,
64
- 'digest' => d.digest }
65
- }
66
- end
67
-
68
- # Checks if Asset is stale by comparing the actual mtime and
69
- # digest to the inmemory model.
70
- def fresh?(environment)
71
- # Check freshness of all declared dependencies
72
- @dependency_paths.all? { |dep| dependency_fresh?(environment, dep) }
73
- end
74
-
75
- protected
76
- class DependencyFile < Struct.new(:pathname, :mtime, :digest)
77
- def initialize(pathname, mtime, digest)
78
- pathname = Pathname.new(pathname) unless pathname.is_a?(Pathname)
79
- mtime = Time.parse(mtime) if mtime.is_a?(String)
80
- super
81
- end
82
-
83
- def eql?(other)
84
- other.is_a?(DependencyFile) &&
85
- pathname.eql?(other.pathname) &&
86
- mtime.eql?(other.mtime) &&
87
- digest.eql?(other.digest)
88
- end
89
-
90
- def hash
91
- pathname.to_s.hash
92
- end
93
- end
94
-
95
- private
96
- def build_required_assets(environment, context)
97
- @required_assets = resolve_dependencies(environment, context._required_paths + [pathname.to_s]) -
98
- resolve_dependencies(environment, context._stubbed_assets.to_a)
99
- end
100
-
101
- def resolve_dependencies(environment, paths)
102
- assets = []
103
- cache = {}
104
-
105
- paths.each do |path|
106
- if path == self.pathname.to_s
107
- unless cache[self]
108
- cache[self] = true
109
- assets << self
110
- end
111
- elsif asset = environment.find_asset(path, :bundle => false)
112
- asset.required_assets.each do |asset_dependency|
113
- unless cache[asset_dependency]
114
- cache[asset_dependency] = true
115
- assets << asset_dependency
116
- end
117
- end
118
- end
119
- end
120
-
121
- assets
122
- end
123
-
124
- def build_dependency_paths(environment, context)
125
- dependency_paths = {}
126
-
127
- context._dependency_paths.each do |path|
128
- dep = DependencyFile.new(path, environment.stat(path).mtime, environment.file_digest(path).hexdigest)
129
- dependency_paths[dep] = true
130
- end
131
-
132
- context._dependency_assets.each do |path|
133
- if path == self.pathname.to_s
134
- dep = DependencyFile.new(pathname, environment.stat(path).mtime, environment.file_digest(path).hexdigest)
135
- dependency_paths[dep] = true
136
- elsif asset = environment.find_asset(path, :bundle => false)
137
- asset.dependency_paths.each do |d|
138
- dependency_paths[d] = true
139
- end
140
- end
141
- end
142
-
143
- @dependency_paths = dependency_paths.keys
144
- end
145
-
146
- def compute_dependency_digest(environment)
147
- required_assets.inject(environment.digest) { |digest, asset|
148
- digest.update asset.digest
149
- }.hexdigest
150
- end
151
- end
152
- end
@@ -1,32 +0,0 @@
1
- require 'tilt'
2
-
3
- module Sprockets
4
- # `Processor` creates an anonymous processor class from a block.
5
- #
6
- # register_preprocessor :my_processor do |context, data|
7
- # # ...
8
- # end
9
- #
10
- class Processor < Tilt::Template
11
- # `processor` is a lambda or block
12
- def self.processor
13
- @processor
14
- end
15
-
16
- def self.name
17
- "Sprockets::Processor (#{@name})"
18
- end
19
-
20
- def self.to_s
21
- name
22
- end
23
-
24
- def prepare
25
- end
26
-
27
- # Call processor block with `context` and `data`.
28
- def evaluate(context, locals)
29
- self.class.processor.call(context, data)
30
- end
31
- end
32
- end
@@ -1,28 +0,0 @@
1
- require 'tilt'
2
-
3
- module Sprockets
4
- # For JS developers who are colonfobic, concatenating JS files using
5
- # the module pattern usually leads to syntax errors.
6
- #
7
- # The `SafetyColons` processor will insert missing semicolons to the
8
- # end of the file.
9
- #
10
- # This behavior can be disabled with:
11
- #
12
- # environment.unregister_postprocessor 'application/javascript', Sprockets::SafetyColons
13
- #
14
- class SafetyColons < Tilt::Template
15
- def prepare
16
- end
17
-
18
- def evaluate(context, locals, &block)
19
- # If the file is blank or ends in a semicolon, leave it as is
20
- if data =~ /\A\s*\Z/m || data =~ /;\s*\Z/m
21
- data
22
- else
23
- # Otherwise, append a semicolon and newline
24
- "#{data};\n"
25
- end
26
- end
27
- end
28
- end
@@ -1,13 +0,0 @@
1
- require 'sprockets/sass_template'
2
-
3
- module Sprockets
4
- # Scss handler to replace Tilt's builtin one. See `SassTemplate` and
5
- # `SassImporter` for more infomation.
6
- class ScssTemplate < SassTemplate
7
- self.default_mime_type = 'text/css'
8
-
9
- def syntax
10
- :scss
11
- end
12
- end
13
- end
@@ -1,57 +0,0 @@
1
- require 'sprockets/asset'
2
- require 'fileutils'
3
- require 'zlib'
4
-
5
- module Sprockets
6
- # `StaticAsset`s are used for files that are served verbatim without
7
- # any processing or concatenation. These are typical images and
8
- # other binary files.
9
- class StaticAsset < Asset
10
- # Returns file contents as its `source`.
11
- def source
12
- # File is read everytime to avoid memory bloat of large binary files
13
- pathname.open('rb') { |f| f.read }
14
- end
15
-
16
- # Implemented for Rack SendFile support.
17
- def to_path
18
- pathname.to_s
19
- end
20
-
21
- # Save asset to disk.
22
- def write_to(filename, options = {})
23
- # Gzip contents if filename has '.gz'
24
- options[:compress] ||= File.extname(filename) == '.gz'
25
-
26
- FileUtils.mkdir_p File.dirname(filename)
27
-
28
- if options[:compress]
29
- # Open file and run it through `Zlib`
30
- pathname.open('rb') do |rd|
31
- File.open("#{filename}+", 'wb') do |wr|
32
- gz = Zlib::GzipWriter.new(wr, Zlib::BEST_COMPRESSION)
33
- buf = ""
34
- while rd.read(16384, buf)
35
- gz.write(buf)
36
- end
37
- gz.close
38
- end
39
- end
40
- else
41
- # If no compression needs to be done, we can just copy it into place.
42
- FileUtils.cp(pathname, "#{filename}+")
43
- end
44
-
45
- # Atomic write
46
- FileUtils.mv("#{filename}+", filename)
47
-
48
- # Set mtime correctly
49
- File.utime(mtime, mtime, filename)
50
-
51
- nil
52
- ensure
53
- # Ensure tmp file gets cleaned up
54
- FileUtils.rm("#{filename}+") if File.exist?("#{filename}+")
55
- end
56
- end
57
- end
@@ -1,90 +0,0 @@
1
- require 'sprockets/errors'
2
- require 'pathname'
3
-
4
- module Sprockets
5
- # `Trail` is an internal mixin whose public methods are exposed on
6
- # the `Environment` and `Index` classes.
7
- module Trail
8
- # Returns `Environment` root.
9
- #
10
- # All relative paths are expanded with root as its base. To be
11
- # useful set this to your applications root directory. (`Rails.root`)
12
- def root
13
- trail.root.dup
14
- end
15
-
16
- # Returns an `Array` of path `String`s.
17
- #
18
- # These paths will be used for asset logical path lookups.
19
- #
20
- # Note that a copy of the `Array` is returned so mutating will
21
- # have no affect on the environment. See `append_path`,
22
- # `prepend_path`, and `clear_paths`.
23
- def paths
24
- trail.paths.dup
25
- end
26
-
27
- # Prepend a `path` to the `paths` list.
28
- #
29
- # Paths at the end of the `Array` have the least priority.
30
- def prepend_path(path)
31
- expire_index!
32
- @trail.prepend_path(path)
33
- end
34
-
35
- # Append a `path` to the `paths` list.
36
- #
37
- # Paths at the beginning of the `Array` have a higher priority.
38
- def append_path(path)
39
- expire_index!
40
- @trail.append_path(path)
41
- end
42
-
43
- # Clear all paths and start fresh.
44
- #
45
- # There is no mechanism for reordering paths, so its best to
46
- # completely wipe the paths list and reappend them in the order
47
- # you want.
48
- def clear_paths
49
- expire_index!
50
- @trail.paths.dup.each { |path| @trail.remove_path(path) }
51
- end
52
-
53
- # Returns an `Array` of extensions.
54
- #
55
- # These extensions maybe omitted from logical path searches.
56
- #
57
- # # => [".js", ".css", ".coffee", ".sass", ...]
58
- #
59
- def extensions
60
- trail.extensions.dup
61
- end
62
-
63
- # Finds the expanded real path for a given logical path by
64
- # searching the environment's paths.
65
- #
66
- # resolve("application.js")
67
- # # => "/path/to/app/javascripts/application.js.coffee"
68
- #
69
- # A `FileNotFound` exception is raised if the file does not exist.
70
- def resolve(logical_path, options = {})
71
- # If a block is given, preform an iterable search
72
- if block_given?
73
- args = attributes_for(logical_path).search_paths + [options]
74
- trail.find(*args) do |path|
75
- yield Pathname.new(path)
76
- end
77
- else
78
- resolve(logical_path, options) do |pathname|
79
- return pathname
80
- end
81
- raise FileNotFound, "couldn't find file '#{logical_path}'"
82
- end
83
- end
84
-
85
- protected
86
- def trail
87
- @trail
88
- end
89
- end
90
- end