Module: Condenser::Resolve
- Included in:
- Condenser
- Defined in:
- lib/condenser/resolve.rb
Instance Method Summary collapse
- #[](filename) ⇒ Object
- #build ⇒ Object
- #decompose_path(path, base = nil) ⇒ Object
- #find(filename, base = nil, accept: nil, ignore: []) ⇒ Object
- #find!(filename, base = nil, **kargs) ⇒ Object
- #find_export(filename, base = nil, **kargs) ⇒ Object
- #initialize(*args) ⇒ Object
-
#match_mime_type?(value, matcher) ⇒ Boolean
Public: Test mime type against mime range.
- #match_mime_types?(value, matcher) ⇒ Boolean
- #mime_type_match_accept?(value, accept) ⇒ Boolean
- #resolve(filename, base = nil, accept: nil, ignore: []) ⇒ Object
- #resolve!(filename, base = nil, **kargs) ⇒ Object
- #reverse_mapping ⇒ Object
- #writers_for_mime_type(mime_type) ⇒ Object
Instance Method Details
#[](filename) ⇒ Object
110 111 112 113 114 |
# File 'lib/condenser/resolve.rb', line 110 def [](filename) build do find!(filename).export end end |
#build ⇒ Object
123 124 125 126 127 128 129 130 131 132 133 134 |
# File 'lib/condenser/resolve.rb', line 123 def build @build_cc += 1 if @build_cc == 1 @build_cache = {} end yield ensure @build_cc -= 1 if @build_cc == 0 @build_cache = nil end end |
#decompose_path(path, base = nil) ⇒ Object
136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 |
# File 'lib/condenser/resolve.rb', line 136 def decompose_path(path, base=nil) dirname = path.index('/') ? File.dirname(path) : nil if base && path&.start_with?('.') dirname = File.(dirname, base) end _, star, basename, extensions = path.match(/(([^\.\/]+)(\.[^\/]+)|\*|[^\/]+)$/).to_a if extensions == '.*' extensions = nil end if basename.nil? && extensions.nil? basename = star end if extensions.nil? && basename == '*' extensions = nil mime_types = [] elsif extensions.nil? mime_types = [] else exts = [] while !extensions.empty? matching_extensions = @extensions.keys.select { |e| extensions.end_with?(e) } if matching_extensions.empty? basename << extensions break # raise 'unkown mime' else matching_extensions.sort_by! { |e| -e.length } exts.unshift(matching_extensions.first) extensions.delete_suffix!(matching_extensions.first) end end extensions = exts mime_types = extensions.map { |k| @extensions[k] } end [ dirname, basename, extensions, mime_types ] end |
#find(filename, base = nil, accept: nil, ignore: []) ⇒ Object
98 99 100 101 102 |
# File 'lib/condenser/resolve.rb', line 98 def find(filename, base=nil, accept: nil, ignore: []) build do @build_cache["find/#{[filename, base, accept].join('-')}"] ||= resolve(filename, base, accept: accept, ignore: ignore).first end end |
#find!(filename, base = nil, **kargs) ⇒ Object
104 105 106 107 108 |
# File 'lib/condenser/resolve.rb', line 104 def find!(filename, base=nil, **kargs) build do resolve!(filename, base, **kargs).first end end |
#find_export(filename, base = nil, **kargs) ⇒ Object
116 117 118 119 120 121 |
# File 'lib/condenser/resolve.rb', line 116 def find_export(filename, base=nil, **kargs) build do asset = resolve(filename, base, **kargs).first asset&.export end end |
#initialize(*args) ⇒ Object
4 5 6 7 |
# File 'lib/condenser/resolve.rb', line 4 def initialize(*args) @reverse_mapping = nil super end |
#match_mime_type?(value, matcher) ⇒ Boolean
Public: Test mime type against mime range.
match_mime_type?('text/html', 'text/*') => true
match_mime_type?('text/plain', '*') => true
match_mime_type?('text/html', 'application/json') => false
Returns true if the given value is a mime match for the given mime match specification, false otherwise.
229 230 231 232 233 |
# File 'lib/condenser/resolve.rb', line 229 def match_mime_type?(value, matcher) v1, v2 = value.split('/'.freeze, 2) m1, m2 = matcher.split('/'.freeze, 2) (m1 == '*'.freeze || v1 == m1) && (m2.nil? || m2 == '*'.freeze || m2 == v2) end |
#match_mime_types?(value, matcher) ⇒ Boolean
204 205 206 207 208 209 210 211 212 213 |
# File 'lib/condenser/resolve.rb', line 204 def match_mime_types?(value, matcher) matcher = Array(matcher) value = Array(value) if matcher.length == 1 && matcher.last == '*/*' true else value.length == matcher.length && value.zip(matcher).all? { |v, m| match_mime_type?(v, m) } end end |
#mime_type_match_accept?(value, accept) ⇒ Boolean
215 216 217 218 219 |
# File 'lib/condenser/resolve.rb', line 215 def mime_type_match_accept?(value, accept) accept.any? do |a| match_mime_types?(value, Array(a)) end end |
#resolve(filename, base = nil, accept: nil, ignore: []) ⇒ Object
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 |
# File 'lib/condenser/resolve.rb', line 9 def resolve(filename, base=nil, accept: nil, ignore: []) filename = filename.delete_prefix("/") if path.none? { |p| filename.start_with?(p) } build do dirname, basename, extensions, mime_types = decompose_path(filename, base) results = [] accept ||= mime_types.empty? ? ['*/*'] : mime_types accept = Array(accept) paths = if dirname&.start_with?('/') if pat = path.find { |pa| dirname.start_with?(pa) } dirname.delete_prefix!(pat) dirname.delete_prefix!('/') [pat] else [] end else path end paths.each do |path| glob = path glob = File.join(glob, dirname) if dirname glob = File.join(glob, basename) glob << '.*' unless glob.end_with?('*') Dir.glob(glob).sort.each do |f| next if !File.file?(f) || ignore.include?(f) f_dirname, f_basename, f_extensions, f_mime_types = decompose_path(f) if (basename == '*' || basename == f_basename) if accept == ['*/*'] || mime_type_match_accept?(f_mime_types, accept) asset_dir = f_dirname.delete_prefix(path).delete_prefix('/') asset_basename = f_basename + f_extensions.join('') asset_filename = asset_dir.empty? ? asset_basename : File.join(asset_dir, asset_basename) @build_cache[asset_filename] ||= Asset.new(self, { filename: asset_filename, content_types: f_mime_types, source_file: f, source_path: path }) results << @build_cache[asset_filename] else reverse_mapping[f_mime_types]&.each do |derivative_mime_types| if accept == ['*/*'] || mime_type_match_accept?(derivative_mime_types, accept) asset_dir = f_dirname.delete_prefix(path).delete_prefix('/') asset_basename = f_basename + derivative_mime_types.map { |t| @mime_types[t][:extensions].first }.join('') asset_filename = asset_dir.empty? ? asset_basename : File.join(asset_dir, asset_basename) @build_cache[asset_filename] ||= Asset.new(self, { filename: asset_filename, content_types: derivative_mime_types, source_file: f, source_path: path }) results << @build_cache[asset_filename] end end end end end end results = results.group_by do |a| accept.find_index { |m| match_mime_types?(a.content_types, m) } end results = results.keys.sort.reduce([]) do |c, key| c += results[key].sort_by(&:filename) end results.sort_by(&:filename) end end |
#resolve!(filename, base = nil, **kargs) ⇒ Object
87 88 89 90 91 92 93 94 95 96 |
# File 'lib/condenser/resolve.rb', line 87 def resolve!(filename, base=nil, **kargs) build do assets = resolve(filename, base, **kargs) if assets.empty? raise FileNotFound, "couldn't find file '#{filename}'" else assets end end end |
#reverse_mapping ⇒ Object
177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 |
# File 'lib/condenser/resolve.rb', line 177 def reverse_mapping return @reverse_mapping if @reverse_mapping map = {} @mime_types.each_key do |source_mime_type| to_mime_type = source_mime_type ([nil] + (@transformers[source_mime_type]&.keys || [])).each do |transform_mime_type| to_mime_type = transform_mime_type if transform_mime_type ([nil] + @templates.keys).each do |template_mime_type| from_mimes = [source_mime_type, template_mime_type].compact to_mime_types = [to_mime_type].compact if from_mimes != to_mime_types map[from_mimes] ||= Set.new map[from_mimes] << to_mime_types end end end end $map = map end |
#writers_for_mime_type(mime_type) ⇒ Object
200 201 202 |
# File 'lib/condenser/resolve.rb', line 200 def writers_for_mime_type(mime_type) @writers.select { |m, e| match_mime_type?(mime_type, m) }.values.reduce(&:+) end |