condenser 1.2 → 1.3

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 (50) hide show
  1. checksums.yaml +4 -4
  2. data/lib/condenser/asset.rb +19 -16
  3. data/lib/condenser/build_cache.rb +1 -1
  4. data/lib/condenser/context.rb +9 -25
  5. data/lib/condenser/helpers/parse_helpers.rb +1 -1
  6. data/lib/condenser/manifest.rb +3 -1
  7. data/lib/condenser/pipeline.rb +8 -3
  8. data/lib/condenser/processors/babel_processor.rb +1 -1
  9. data/lib/condenser/processors/css_media_combiner_processor.rb +81 -0
  10. data/lib/condenser/processors/js_analyzer.rb +0 -2
  11. data/lib/condenser/processors/purgecss_processor.rb +6 -4
  12. data/lib/condenser/processors/rollup_processor.rb +37 -35
  13. data/lib/condenser/resolve.rb +1 -3
  14. data/lib/condenser/templating_engine/ejs.rb +1 -1
  15. data/lib/condenser/transformers/dart_sass_transformer.rb +285 -0
  16. data/lib/condenser/transformers/jst_transformer.rb +67 -17
  17. data/lib/condenser/transformers/sass/functions.rb +133 -0
  18. data/lib/condenser/transformers/sass/importer.rb +48 -0
  19. data/lib/condenser/transformers/sass.rb +4 -0
  20. data/lib/condenser/transformers/sass_transformer.rb +124 -281
  21. data/lib/condenser/transformers/svg_transformer/base.rb +26 -0
  22. data/lib/condenser/transformers/svg_transformer/tag.rb +54 -0
  23. data/lib/condenser/transformers/svg_transformer/template.rb +151 -0
  24. data/lib/condenser/transformers/svg_transformer/template_error.rb +2 -0
  25. data/lib/condenser/transformers/svg_transformer/value.rb +13 -0
  26. data/lib/condenser/transformers/svg_transformer/var_generator.rb +10 -0
  27. data/lib/condenser/transformers/svg_transformer.rb +19 -0
  28. data/lib/condenser/version.rb +1 -1
  29. data/lib/condenser.rb +17 -5
  30. data/test/cache_test.rb +46 -2
  31. data/test/dependency_test.rb +2 -2
  32. data/test/manifest_test.rb +34 -0
  33. data/test/minifiers/terser_minifier_test.rb +0 -1
  34. data/test/minifiers/uglify_minifier_test.rb +0 -1
  35. data/test/postprocessors/css_media_combiner_test.rb +107 -0
  36. data/test/postprocessors/purgecss_test.rb +62 -0
  37. data/test/preprocessor/babel_test.rb +693 -299
  38. data/test/preprocessor/js_analyzer_test.rb +0 -2
  39. data/test/processors/rollup_test.rb +50 -20
  40. data/test/resolve_test.rb +8 -9
  41. data/test/server_test.rb +6 -1
  42. data/test/templates/ejs_test.rb +2 -11
  43. data/test/templates/erb_test.rb +0 -5
  44. data/test/test_helper.rb +3 -1
  45. data/test/transformers/dart_scss_test.rb +139 -0
  46. data/test/transformers/jst_test.rb +165 -21
  47. data/test/transformers/scss_test.rb +14 -0
  48. data/test/transformers/svg_test.rb +40 -0
  49. metadata +23 -6
  50. data/lib/condenser/transformers/sass_transformer/importer.rb +0 -50
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e2b1dab33dd825d2bf0902e871c68c0334d49ee7af48ee0875132f39adce20d2
4
- data.tar.gz: a3c40f6f19722d0cea00e28592cd2049db5185057b299bf697fc169c9a19c89a
3
+ metadata.gz: 52e335c087aab2b9bb3ef4540e54bfc5b8de0a888cab8f095c2f1dd778458bd4
4
+ data.tar.gz: 566502264a1049f4ff5e33154caa56ef64ed74d14a8d72abd5e31628d59986c1
5
5
  SHA512:
6
- metadata.gz: c1ca10d2f7dff116d1b4d4daeba50302509c7faffed458e2312d40c391b84a407d596487102a4e306abd9a96bd435c39d0fb23add68a3608aa64014b3fffe0d7
7
- data.tar.gz: 3f530d21b0ec272d51aabd96f0218dfc1a02dbb8845dbefd3d92cf1517447bc436785a102415ad9fda696df26d9769f67485f8530445eb66b48dc3318ffd8e72
6
+ metadata.gz: 5c0fdf66cb6b17ff6a519af5205061f37e3af2f12896e45c2798154c46ba2db3dea57e219595b33e5433a82db17751bc8444453c5bc0371fb27013e97157352d
7
+ data.tar.gz: 2486bd59e00c2d70ea683d2f69f1a71b0981b557144a08fd4965f9fe38a0c2da68d79e1c6fcba359718af3f9c26f4978619c3bb651f394cbb0db0172c450096f
@@ -125,7 +125,7 @@ class Condenser
125
125
 
126
126
  def all_process_dependencies
127
127
  f = [@source_file]
128
- all_dependenies(process_dependencies, [], :process_dependencies) do |dep|
128
+ all_dependenies(process_dependencies, Set.new, :process_dependencies) do |dep|
129
129
  f << dep.source_file
130
130
  end
131
131
  f
@@ -133,7 +133,7 @@ class Condenser
133
133
 
134
134
  def all_export_dependencies
135
135
  f = [@source_file]
136
- all_dependenies(export_dependencies, [], :export_dependencies) do |dep|
136
+ all_dependenies(export_dependencies, Set.new, :export_dependencies) do |dep|
137
137
  f << dep.source_file
138
138
  end
139
139
  f
@@ -153,7 +153,7 @@ class Condenser
153
153
  return @pcv if @pcv
154
154
 
155
155
  f = []
156
- all_dependenies(process_dependencies, [], :process_dependencies) do |dep|
156
+ all_dependenies(process_dependencies, Set.new, :process_dependencies) do |dep|
157
157
  f << [
158
158
  @environment.base ? dep.source_file.delete_prefix(@environment.base) : dep.source_file,
159
159
  Digest::SHA256.file(dep.source_file).hexdigest
@@ -167,7 +167,7 @@ class Condenser
167
167
  return @ecv if @ecv
168
168
 
169
169
  f = []
170
- all_dependenies(export_dependencies, [], :export_dependencies) do |dep|
170
+ all_dependenies(export_dependencies, Set.new, :export_dependencies) do |dep|
171
171
  f << [
172
172
  @environment.base ? dep.source_file.delete_prefix(@environment.base) : dep.source_file,
173
173
  Digest::SHA256.file(dep.source_file).hexdigest
@@ -206,9 +206,9 @@ class Condenser
206
206
  content_type: mime_types,
207
207
 
208
208
  map: nil,
209
- linked_assets: [],
210
- process_dependencies: [],
211
- export_dependencies: [],
209
+ linked_assets: Set.new,
210
+ process_dependencies: Set.new,
211
+ export_dependencies: Set.new,
212
212
 
213
213
  processors: Set.new
214
214
  }
@@ -285,15 +285,14 @@ class Condenser
285
285
  @content_types = data[:content_type]
286
286
  @digest = data[:digest]
287
287
  @digest_name = data[:digest_name]
288
- @linked_assets = data[:linked_assets]
289
- @process_dependencies = data[:process_dependencies]
290
- @export_dependencies = data[:export_dependencies]
288
+ @linked_assets = Set.new(data[:linked_assets])
289
+ @process_dependencies = Set.new(data[:process_dependencies])
290
+ @export_dependencies = Set.new(data[:export_dependencies])
291
291
  @default_export = data[:default_export]
292
292
  @exports = data[:exports]
293
293
  @processors = data[:processors]
294
294
  @processors_loaded = true
295
295
  @processed = true
296
-
297
296
  data
298
297
  end
299
298
  end
@@ -304,9 +303,9 @@ class Condenser
304
303
  @content_types = result[:content_type]
305
304
  @digest = result[:digest]
306
305
  @digest_name = result[:digest_name]
307
- @linked_assets = result[:linked_assets]
308
- @process_dependencies = result[:process_dependencies]
309
- @export_dependencies = result[:export_dependencies]
306
+ @linked_assets = Set.new(result[:linked_assets])
307
+ @process_dependencies = Set.new(result[:process_dependencies])
308
+ @export_dependencies = Set.new(result[:export_dependencies])
310
309
  @default_export = result[:default_export]
311
310
  @exports = result[:exports]
312
311
  @processors = result[:processors]
@@ -335,11 +334,15 @@ class Condenser
335
334
  export_dependencies: []
336
335
  }
337
336
 
338
- if exporter = @environment.exporters[content_type]
339
- exporter.call(@environment, data)
337
+ if @environment.exporters.has_key?(content_type)
338
+ @environment.exporters[content_type].each do |exporter|
339
+ @environment.logger.info { "Exporting #{self.filename} with #{exporter.name}" }
340
+ exporter.call(@environment, data)
341
+ end
340
342
  end
341
343
 
342
344
  if minifier = @environment.minifier_for(content_type)
345
+ @environment.logger.info { "Minifing #{self.filename} with #{minifier.name}" }
343
346
  minifier.call(@environment, data)
344
347
  end
345
348
 
@@ -33,7 +33,7 @@ class Condenser
33
33
  end
34
34
 
35
35
  globs = []
36
- (added + removed).each do |file|
36
+ (added + removed + modified).each do |file|
37
37
  globs << file.match(/([^\.]+)(\.|$)/).to_a[1]
38
38
  if path_match = @path.find { |p| file.start_with?(p) }
39
39
  a = file.delete_prefix(path_match).match(/([^\.]+)(\.|$)/).to_a[1]
@@ -35,7 +35,7 @@ class Condenser
35
35
  end
36
36
  end
37
37
 
38
- attr_reader :environment, :filename
38
+ attr_reader :environment, :filename, :links, :dependencies
39
39
 
40
40
  def initialize(environment)
41
41
  @environment = environment
@@ -110,29 +110,14 @@ class Condenser
110
110
  # `depend_on` allows you to state a dependency on a file without
111
111
  # including it.
112
112
  #
113
- # This is used for caching purposes. Any changes made to
114
- # the dependency file will invalidate the cache of the
115
- # source file.
116
- def depend_on(path)
117
- if environment.absolute_path?(path) && environment.stat(path)
118
- @dependencies << environment.build_file_digest_uri(path)
119
- else
120
- resolve(path)
121
- end
122
- nil
123
- end
124
-
125
- # `depend_on_asset` allows you to state an asset dependency
126
- # without including it.
127
- #
128
113
  # This is used for caching purposes. Any changes that would
129
114
  # invalidate the dependency asset will invalidate the source
130
- # file. Unlike `depend_on`, this will recursively include
131
- # the target asset's dependencies.
132
- def depend_on_asset(path)
133
- asset = environment.find!(path)
134
- @dependencies << asset.source_file
135
- asset
115
+ # file.
116
+ def depend_on(path)
117
+ d = environment.decompose_path(path)
118
+ @dependencies << [File.join(*d[0], d[1]), [d[3]]]
119
+
120
+ nil
136
121
  end
137
122
 
138
123
  # `depend_on_env` allows you to state a dependency on an environment
@@ -150,9 +135,8 @@ class Condenser
150
135
  #
151
136
  # Returns an Asset or nil.
152
137
  def link_asset(path)
153
- asset = depend_on_asset(path)
154
- @links << asset.path
155
- asset
138
+ depend_on(path)
139
+ @links << path
156
140
  end
157
141
 
158
142
  # Returns a `data:` URI with the contents of the asset at the specified
@@ -3,7 +3,7 @@ module Condenser::ParseHelpers
3
3
  attr_accessor :matched
4
4
 
5
5
  def eos?
6
- @index >= @source.size
6
+ @index >= (@source.size - 1)
7
7
  end
8
8
 
9
9
  def scan_until(r)
@@ -71,7 +71,9 @@ class Condenser
71
71
 
72
72
  @data[asset.filename] = export.to_json
73
73
  outputs = export.write(@dir)
74
- asset.linked_assets.each { |a| outputs += add_asset(a) }
74
+ asset.linked_assets.each do |la|
75
+ @environment.resolve(la).each { |a| outputs += add_asset(a) }
76
+ end
75
77
  outputs
76
78
  end
77
79
 
@@ -98,11 +98,16 @@ class Condenser
98
98
  end
99
99
 
100
100
  def register_exporter(mime_type, engine)
101
- @exporters[mime_type] = engine
101
+ @exporters[mime_type] ||= []
102
+ @exporters[mime_type] << engine
102
103
  end
103
104
 
104
- def unregister_exporter(mime_type, engine)
105
- @exporters[mime_type] = nil
105
+ def unregister_exporter(mime_type, engine=nil)
106
+ if engine.nil?
107
+ @exporters[mime_type].clear
108
+ else
109
+ @exporters[mime_type]&.reject! { |e| e == engine || e.is_a?(engine) }
110
+ end
106
111
  end
107
112
 
108
113
  def register_minifier(mime_type, engine)
@@ -4,7 +4,7 @@ class Condenser::BabelProcessor < Condenser::NodeProcessor
4
4
 
5
5
  attr_accessor :options
6
6
 
7
- def initialize(dir = nil, options = {})
7
+ def initialize(dir = nil, **options)
8
8
  super(dir)
9
9
 
10
10
  options[:plugins] ||= [
@@ -0,0 +1,81 @@
1
+ class Condenser::CSSMediaCombinerProcessor
2
+
3
+ include Condenser::ParseHelpers
4
+
5
+ def self.setup(env)
6
+ end
7
+
8
+ def self.call(environment, input)
9
+ new.call(environment, input)
10
+ end
11
+
12
+ def reduce_media_query(queries)
13
+ output = ''
14
+ queries.each do |query, contents|
15
+ output << query if query
16
+ output << if contents.is_a?(Hash)
17
+ reduce_media_query(contents)
18
+ else
19
+ contents + '}'
20
+ end
21
+ end
22
+ output
23
+ end
24
+
25
+ def call(environment, input)
26
+ seek(0)
27
+ @sourcefile = input[:source_file]
28
+ @source = input[:source]
29
+ @stack = []
30
+ @selectors = []
31
+ @media_queries = {}
32
+
33
+ input[:source] = ''
34
+ while !eos?
35
+ output = if @selectors.empty?
36
+ input[:source]
37
+ else
38
+ (@selectors[0...-1].reduce(@media_queries) { |hash, selector| hash[selector] ||= {} }[@selectors.last] ||= '')
39
+ end
40
+
41
+ case @stack.last
42
+ when :media_query
43
+ scan_until(/(@media[^\{]*{|\{|\})/)
44
+ case matched
45
+ when '{'
46
+ output << pre_match << matched
47
+ @stack << :statement
48
+ when '}'
49
+ output << pre_match
50
+ @stack.pop
51
+ @selectors.pop
52
+ else
53
+ output << pre_match
54
+ @selectors << matched.squish
55
+ @stack << :media_query
56
+ end
57
+ when :statement
58
+ scan_until(/(\{|\})/)
59
+ output << pre_match << matched
60
+ case matched
61
+ when '{'
62
+ @stack << :statement
63
+ when '}'
64
+ @stack.pop
65
+ end
66
+ else
67
+ case scan_until(/(@media[^\{]*{|\Z)/)
68
+ when ''
69
+ output << pre_match
70
+ else
71
+ output << pre_match
72
+ @selectors << matched.squish
73
+ @stack << :media_query
74
+ end
75
+ end
76
+ end
77
+
78
+ input[:source] << reduce_media_query(@media_queries)
79
+ end
80
+
81
+ end
@@ -1,5 +1,3 @@
1
- require 'condenser/helpers/parse_helpers'
2
-
3
1
  class Condenser::JSAnalyzer
4
2
 
5
3
  include Condenser::ParseHelpers
@@ -34,7 +34,7 @@ class Condenser::PurgeCSSProcessor < Condenser::NodeProcessor
34
34
  const { PurgeCSS } = require("#{File.join(npm_module_path('purgecss'))}")
35
35
  const options = #{@options.to_json}
36
36
  options.css = [{
37
- raw: #{input[:source].inspect}
37
+ raw: #{JSON.dump(input[:source])}
38
38
  }]
39
39
  if(options.safelist) {
40
40
  options.safelist = options.safelist.map(s => {
@@ -44,13 +44,16 @@ class Condenser::PurgeCSSProcessor < Condenser::NodeProcessor
44
44
  return s
45
45
  })
46
46
  }
47
+ if(!options.defaultExtractor) {
48
+ options.defaultExtractor = content => content.match(/[\\w\\-\\/\\:]+(?<!:)/g) || []
49
+ }
47
50
  const result = new PurgeCSS().purge(options)
48
51
  try {
49
52
  result.then(
50
53
  r => console.log(JSON.stringify({
51
54
  success: r[0]
52
55
  })),
53
- function() {console.log(JSON.stringify({'error': arguments}))}
56
+ function(e) {console.log(JSON.stringify({'error': [e.name, e.message, e.stack]}))}
54
57
  )
55
58
  } catch(e) {
56
59
  console.log(JSON.stringify({'error': [e.name, e.message, e.stack]}));
@@ -60,11 +63,10 @@ class Condenser::PurgeCSSProcessor < Condenser::NodeProcessor
60
63
  if result['error'][0] == 'SyntaxError'
61
64
  raise exec_syntax_error(result['error'][1], "/assets/#{input[:filename]}")
62
65
  else
63
- raise exec_runtime_error(result['error'][0] + ': ' + result['error'][1])
66
+ raise exec_runtime_error(result['error']["0"]["name"] + ": " + result['error']["0"]["reason"])
64
67
  end
65
68
  else
66
69
  input[:source] = result["success"]["css"]
67
70
  end
68
71
  end
69
-
70
72
  end
@@ -7,7 +7,7 @@ class Condenser::RollupProcessor < Condenser::NodeProcessor
7
7
 
8
8
  def initialize(dir = nil, options = {})
9
9
  super(dir)
10
- npm_install('rollup', 'rollup-plugin-commonjs', 'rollup-plugin-node-resolve')
10
+ npm_install('rollup', '@rollup/plugin-commonjs', '@rollup/plugin-node-resolve')
11
11
 
12
12
  @options = options.freeze
13
13
  end
@@ -50,7 +50,12 @@ class Condenser::RollupProcessor < Condenser::NodeProcessor
50
50
  return '';
51
51
  } catch(e) {
52
52
  if (e.name === "SyntaxError") {
53
- if (e.message.startsWith('Unexpected token { in JSON at position ')) {
53
+ if (e.message.startsWith('Unexpected non-whitespace character after JSON at position ')) {
54
+ var pos = parseInt(e.message.slice(59));
55
+ emitMessages(buffer.slice(0,pos));
56
+ return emitMessages(buffer.slice(pos));
57
+ } else if (e.message.startsWith('Unexpected token { in JSON at position ')) {
58
+ // This can be removed, once dropping support for node <= v18
54
59
  var pos = parseInt(e.message.slice(39));
55
60
  emitMessages(buffer.slice(0,pos));
56
61
  return emitMessages(buffer.slice(pos));
@@ -70,8 +75,8 @@ class Condenser::RollupProcessor < Condenser::NodeProcessor
70
75
  });
71
76
 
72
77
  const rollup = require("#{npm_module_path('rollup')}");
73
- const commonjs = require("#{npm_module_path('rollup-plugin-commonjs')}");
74
- const nodeResolve = require("#{npm_module_path('rollup-plugin-node-resolve')}");
78
+ const commonjs = require("#{npm_module_path('@rollup/plugin-commonjs')}");
79
+ const nodeResolve = require("#{npm_module_path('@rollup/plugin-node-resolve')}").nodeResolve;
75
80
  var rid = 0;
76
81
  var renderStack = {};
77
82
  var nodeResolver = null;
@@ -95,9 +100,8 @@ class Condenser::RollupProcessor < Condenser::NodeProcessor
95
100
  mainFields: ['module', 'main'],
96
101
  // modulesOnly: true,
97
102
  // preferBuiltins: false,
98
- customResolveOptions: {
99
- moduleDirectory: '#{npm_module_path}'
100
- }
103
+ moduleDirectories: [],
104
+ modulePaths: ['#{npm_module_path}']
101
105
  });
102
106
  }
103
107
 
@@ -105,9 +109,9 @@ class Condenser::RollupProcessor < Condenser::NodeProcessor
105
109
  inputOptions.plugins = [];
106
110
  inputOptions.plugins.push({
107
111
  name: 'condenser',
108
- resolveId: function (importee, importer) {
112
+ resolveId: function (importee, importer, options) {
109
113
  if (importee.startsWith('\\0') || (importer && importer.startsWith('\\0'))) {
110
- return;
114
+ return null;
111
115
  }
112
116
 
113
117
  if (!(importer in renderStack)) {
@@ -115,24 +119,15 @@ class Condenser::RollupProcessor < Condenser::NodeProcessor
115
119
  }
116
120
 
117
121
  return request('resolve', [importee, importer]).then((value) => {
118
- if (nodeResolver && (value === null || value === undefined)) {
119
- return nodeResolver.resolveId.call(this, importee, importer).then((value) => {
120
- if (!(value === null || value === undefined) && !renderStack[importer].includes(value.id)) {
121
- renderStack[importer].push(value.id);
122
- }
123
- return value;
124
- });
125
- }
126
-
127
- if (!(value === null || value === undefined) && !renderStack[importer].includes(value)) {
128
- renderStack[importer].push(value);
129
- }
130
- return value;
122
+ if (!(value === null || value === undefined) && !renderStack[importer].includes(value)) {
123
+ renderStack[importer].push(value);
124
+ }
125
+ return value;
131
126
  });
132
127
  },
133
128
  load: function(id) {
134
129
  if (id.startsWith('\\0')) {
135
- return;
130
+ return null;
136
131
  }
137
132
 
138
133
  return request('load', [id]).then(function(value) {
@@ -140,17 +135,19 @@ class Condenser::RollupProcessor < Condenser::NodeProcessor
140
135
  });
141
136
  }
142
137
  });
138
+
143
139
  inputOptions.plugins.push(nodeResolver);
144
140
  inputOptions.plugins.push(commonjs());
145
141
 
146
- inputOptions.plugins.push({
147
- name: 'nullHanlder',
148
- resolveId: function (importee, importer) {
149
- request('error', ["AssetNotFound", importee, importer, renderStack]).then(function(value) {
150
- process.exit(1);
151
- });
152
- }
153
- });
142
+ // inputOptions.plugins.push({
143
+ // name: 'nullHanlder',
144
+ // resolveId: function (importee, importer, options) {
145
+ // request('log', [importee, importer, options])
146
+ // // request('error', ["AssetNotFound", importee, importer, renderStack]).then(function(value) {
147
+ // // process.exit(1);
148
+ // // });
149
+ // }
150
+ // });
154
151
 
155
152
  const outputOptions = #{JSON.generate(output_options)};
156
153
 
@@ -204,10 +201,16 @@ class Condenser::RollupProcessor < Condenser::NodeProcessor
204
201
  @entry
205
202
  elsif importee.start_with?('@babel/runtime') || importee.start_with?('core-js-pure') || importee.start_with?('regenerator-runtime')
206
203
  x = File.join(npm_module_path, importee.gsub(/^\.\//, File.dirname(importer) + '/')).sub('/node_modules/regenerator-runtime', '/node_modules/regenerator-runtime/runtime.js')
207
- x = "#{x}.js" if !x.end_with?('.js')
204
+ x = "#{x}.js" if !x.end_with?('.js', '.mjs')
205
+ File.file?(x) ? x : (x.delete_suffix('.js') + "/index.js")
206
+ elsif npm_module_path && importee&.start_with?(npm_module_path)
207
+ x = importee.end_with?('.js', '.mjs') ? importee : "#{importee}.js"
208
+ x = (x.delete_suffix('.js') + "/index.js") if !File.file?(x)
209
+ x
210
+ elsif importee.start_with?('.') && importer.start_with?(npm_module_path)
211
+ x = File.expand_path(importee, File.dirname(importer))
212
+ x = "#{x}.js" if !x.end_with?('.js', '.mjs')
208
213
  File.file?(x) ? x : (x.delete_suffix('.js') + "/index.js")
209
- elsif npm_module_path && importer.start_with?(npm_module_path)
210
- nil
211
214
  elsif importee.end_with?('*')
212
215
  File.join(File.dirname(importee), '*')
213
216
  else
@@ -261,7 +264,6 @@ class Condenser::RollupProcessor < Condenser::NodeProcessor
261
264
  # when 'get_cache'
262
265
  # io.write(JSON.generate({rid: message['rid'], return: [(@environment.cache.get('rollup') || '{}')] }))
263
266
  end
264
-
265
267
  io.write(JSON.generate({rid: message['rid'], return: ret}))
266
268
  end
267
269
  end
@@ -38,9 +38,7 @@ class Condenser
38
38
  end
39
39
 
40
40
  paths.each do |path|
41
- glob = path
42
- glob = File.join(glob, dirname) if dirname
43
- glob = File.join(glob, basename)
41
+ glob = File.join(*[path, dirname, basename].compact)
44
42
  glob << '.*' unless glob.end_with?('*')
45
43
 
46
44
  Dir.glob(glob).sort.each do |f|
@@ -1,4 +1,4 @@
1
- class Condenser::EjsTemplare
1
+ class Condenser::EjsTemplate
2
2
 
3
3
  def self.setup(environment)
4
4
  require 'ejs' unless defined?(::EJS)