condenser 1.3 → 1.5

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 (63) hide show
  1. checksums.yaml +4 -4
  2. data/lib/condenser/asset.rb +103 -25
  3. data/lib/condenser/build_cache.rb +23 -8
  4. data/lib/condenser/cache/file_store.rb +1 -0
  5. data/lib/condenser/cache/memory_store.rb +1 -0
  6. data/lib/condenser/cache/null_store.rb +1 -0
  7. data/lib/condenser/cache_store.rb +1 -0
  8. data/lib/condenser/context.rb +1 -0
  9. data/lib/condenser/encoding_utils.rb +2 -0
  10. data/lib/condenser/environment.rb +2 -0
  11. data/lib/condenser/errors.rb +2 -0
  12. data/lib/condenser/export.rb +11 -6
  13. data/lib/condenser/helpers/parse_helpers.rb +23 -1
  14. data/lib/condenser/manifest.rb +3 -1
  15. data/lib/condenser/minifiers/sass_minifier.rb +2 -0
  16. data/lib/condenser/minifiers/terser_minifier.rb +2 -0
  17. data/lib/condenser/minifiers/uglify_minifier.rb +2 -0
  18. data/lib/condenser/pipeline.rb +2 -0
  19. data/lib/condenser/processors/babel_processor.rb +19 -16
  20. data/lib/condenser/processors/css_media_combiner_processor.rb +7 -5
  21. data/lib/condenser/processors/js_analyzer.rb +149 -42
  22. data/lib/condenser/processors/node_processor.rb +3 -0
  23. data/lib/condenser/processors/purgecss_processor.rb +2 -0
  24. data/lib/condenser/processors/rollup_processor.rb +289 -136
  25. data/lib/condenser/resolve.rb +41 -10
  26. data/lib/condenser/server.rb +22 -20
  27. data/lib/condenser/templating_engine/ejs.rb +2 -0
  28. data/lib/condenser/templating_engine/erb.rb +2 -0
  29. data/lib/condenser/transformers/dart_sass_transformer.rb +5 -3
  30. data/lib/condenser/transformers/jst_transformer.rb +2 -0
  31. data/lib/condenser/transformers/sass/functions.rb +2 -0
  32. data/lib/condenser/transformers/sass/importer.rb +2 -0
  33. data/lib/condenser/transformers/sass.rb +2 -0
  34. data/lib/condenser/transformers/sass_transformer.rb +2 -0
  35. data/lib/condenser/transformers/svg_transformer/base.rb +2 -0
  36. data/lib/condenser/transformers/svg_transformer/tag.rb +2 -0
  37. data/lib/condenser/transformers/svg_transformer/template.rb +3 -1
  38. data/lib/condenser/transformers/svg_transformer/template_error.rb +2 -0
  39. data/lib/condenser/transformers/svg_transformer/value.rb +2 -0
  40. data/lib/condenser/transformers/svg_transformer/var_generator.rb +2 -0
  41. data/lib/condenser/transformers/svg_transformer.rb +2 -0
  42. data/lib/condenser/utils.rb +2 -0
  43. data/lib/condenser/version.rb +3 -1
  44. data/lib/condenser/writers/brotli_writer.rb +2 -0
  45. data/lib/condenser/writers/file_writer.rb +2 -0
  46. data/lib/condenser/writers/zlib_writer.rb +2 -0
  47. data/lib/condenser.rb +2 -0
  48. data/lib/rake/condensertask.rb +2 -0
  49. data/test/cache_test.rb +115 -20
  50. data/test/dependency_test.rb +51 -2
  51. data/test/manifest_test.rb +17 -2
  52. data/test/postprocessors/css_media_combiner_test.rb +9 -12
  53. data/test/preprocessor/babel_test.rb +876 -349
  54. data/test/preprocessor/js_analyzer_test.rb +208 -4
  55. data/test/processors/rollup/dynamic_import_test.rb +358 -0
  56. data/test/processors/rollup_test.rb +37 -56
  57. data/test/resolve_test.rb +14 -9
  58. data/test/server_test.rb +10 -9
  59. data/test/test_helper.rb +6 -3
  60. data/test/transformers/dart_scss_test.rb +2 -2
  61. data/test/transformers/scss_test.rb +2 -2
  62. metadata +6 -11
  63. data/lib/condenser/minifiers/package-lock.json +0 -25
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'set'
2
4
  require 'time'
3
5
  require 'rack/utils'
@@ -67,7 +69,7 @@ class Condenser
67
69
  end
68
70
 
69
71
  # Look up the asset.
70
- asset = @condenser.find_export(path)
72
+ asset = @condenser.find_export(path, npm: true)
71
73
  if asset.nil?
72
74
  status = :not_found
73
75
  elsif fingerprint && asset.etag != fingerprint
@@ -142,39 +144,39 @@ class Condenser
142
144
  # Returns a 400 Forbidden response tuple
143
145
  def bad_request_response(env)
144
146
  if head_request?(env)
145
- [ 400, { "Content-Type" => "text/plain", "Content-Length" => "0" }, [] ]
147
+ [ 400, { "content-type" => "text/plain", "content-length" => "0" }, [] ]
146
148
  else
147
- [ 400, { "Content-Type" => "text/plain", "Content-Length" => "11" }, [ "Bad Request" ] ]
149
+ [ 400, { "content-type" => "text/plain", "content-length" => "11" }, [ "Bad Request" ] ]
148
150
  end
149
151
  end
150
152
 
151
153
  # Returns a 403 Forbidden response tuple
152
154
  def forbidden_response(env)
153
155
  if head_request?(env)
154
- [ 403, { "Content-Type" => "text/plain", "Content-Length" => "0" }, [] ]
156
+ [ 403, { "content-type" => "text/plain", "content-length" => "0" }, [] ]
155
157
  else
156
- [ 403, { "Content-Type" => "text/plain", "Content-Length" => "9" }, [ "Forbidden" ] ]
158
+ [ 403, { "content-type" => "text/plain", "content-length" => "9" }, [ "Forbidden" ] ]
157
159
  end
158
160
  end
159
161
 
160
162
  # Returns a 404 Not Found response tuple
161
163
  def not_found_response(env)
162
164
  if head_request?(env)
163
- [ 404, { "Content-Type" => "text/plain", "Content-Length" => "0", "X-Cascade" => "pass" }, [] ]
165
+ [ 404, { "content-type" => "text/plain", "content-length" => "0", "x-cascade" => "pass" }, [] ]
164
166
  else
165
- [ 404, { "Content-Type" => "text/plain", "Content-Length" => "9", "X-Cascade" => "pass" }, [ "Not found" ] ]
167
+ [ 404, { "content-type" => "text/plain", "content-length" => "9", "x-cascade" => "pass" }, [ "Not found" ] ]
166
168
  end
167
169
  end
168
170
 
169
171
  def method_not_allowed_response
170
- [ 405, { "Content-Type" => "text/plain", "Content-Length" => "18" }, [ "Method Not Allowed" ] ]
172
+ [ 405, { "content-type" => "text/plain", "content-length" => "18" }, [ "Method Not Allowed" ] ]
171
173
  end
172
174
 
173
175
  def precondition_failed_response(env)
174
176
  if head_request?(env)
175
- [ 412, { "Content-Type" => "text/plain", "Content-Length" => "0", "X-Cascade" => "pass" }, [] ]
177
+ [ 412, { "content-type" => "text/plain", "content-length" => "0", "x-cascade" => "pass" }, [] ]
176
178
  else
177
- [ 412, { "Content-Type" => "text/plain", "Content-Length" => "19", "X-Cascade" => "pass" }, [ "Precondition Failed" ] ]
179
+ [ 412, { "content-type" => "text/plain", "content-length" => "19", "x-cascade" => "pass" }, [ "Precondition Failed" ] ]
178
180
  end
179
181
  end
180
182
 
@@ -183,7 +185,7 @@ class Condenser
183
185
  def javascript_exception_response(exception)
184
186
  err = "#{exception.class.name}: #{exception.message}\n (in #{exception.backtrace[0]})"
185
187
  body = "throw Error(#{err.inspect})"
186
- [ 200, { "Content-Type" => "application/javascript", "Content-Length" => body.bytesize.to_s }, [ body ] ]
188
+ [ 200, { "content-type" => "application/javascript", "content-length" => body.bytesize.to_s }, [ body ] ]
187
189
  end
188
190
 
189
191
  # Returns a CSS response that hides all elements on the page and
@@ -236,7 +238,7 @@ class Condenser
236
238
  }
237
239
  CSS
238
240
 
239
- [ 200, { "Content-Type" => "text/css; charset=utf-8", "Content-Length" => body.bytesize.to_s }, [ body ] ]
241
+ [ 200, { "content-type" => "text/css; charset=utf-8", "content-length" => body.bytesize.to_s }, [ body ] ]
240
242
  end
241
243
 
242
244
  # Escape special characters for use inside a CSS content("...") string
@@ -252,18 +254,18 @@ class Condenser
252
254
  headers = {}
253
255
 
254
256
  # Set caching headers
255
- headers["Cache-Control"] = String.new("public")
256
- headers["ETag"] = %("#{etag}")
257
+ headers["cache-control"] = String.new("public")
258
+ headers["etag"] = %("#{etag}")
257
259
 
258
260
  # If the request url contains a fingerprint, set a long
259
261
  # expires on the response
260
262
  if path_fingerprint(env["PATH_INFO"])
261
- headers["Cache-Control"] << ", max-age=31536000, immutable"
263
+ headers["cache-control"] << ", max-age=31536000, immutable"
262
264
 
263
265
  # Otherwise set `must-revalidate` since the asset could be modified.
264
266
  else
265
- headers["Cache-Control"] << ", must-revalidate"
266
- headers["Vary"] = "Accept-Encoding"
267
+ headers["cache-control"] << ", must-revalidate"
268
+ headers["vary"] = "Accept-Encoding"
267
269
  end
268
270
 
269
271
  headers
@@ -273,10 +275,10 @@ class Condenser
273
275
  headers = {}
274
276
 
275
277
  # Set content length header
276
- headers["Content-Length"] = length.to_s
278
+ headers["content-length"] = length.to_s
277
279
 
278
280
  if asset&.sourcemap
279
- headers['SourceMap'] = env['SCRIPT_NAME'] + env['PATH_INFO'] + '.map'
281
+ headers['sourcemap'] = env['SCRIPT_NAME'] + env['PATH_INFO'] + '.map'
280
282
  end
281
283
 
282
284
  # Set content type header
@@ -285,7 +287,7 @@ class Condenser
285
287
  if type.start_with?("text/") && asset.charset
286
288
  type += "; charset=#{asset.charset}"
287
289
  end
288
- headers["Content-Type"] = type
290
+ headers["content-type"] = type
289
291
  end
290
292
 
291
293
  headers.merge(cache_headers(env, asset.etag))
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Condenser::EjsTemplate
2
4
 
3
5
  def self.setup(environment)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Condenser::Erubi
2
4
 
3
5
  def self.setup(environment)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Condenser::DartSassTransformer < Condenser::NodeProcessor
2
4
 
3
5
  @@helper_methods = Set.new
@@ -196,14 +198,14 @@ class Condenser::DartSassTransformer < Condenser::NodeProcessor
196
198
 
197
199
  def exec_runtime(script)
198
200
  io = IO.popen([binary, '-e', script], 'r+')
199
- buffer = ''
201
+ buffer = String.new
200
202
  result = nil
201
203
 
202
204
  begin
203
205
  while IO.select([io]) && io_read = io.read_nonblock(1_024)
204
206
  buffer << io_read
205
207
  messages = buffer.split("\n\n")
206
- buffer = buffer.end_with?("\n\n") ? '' : messages.pop
208
+ buffer = buffer.end_with?("\n\n") ? String.new : messages.pop
207
209
 
208
210
  messages.each do |message|
209
211
  message = JSON.parse(message)
@@ -218,7 +220,7 @@ class Condenser::DartSassTransformer < Condenser::NodeProcessor
218
220
 
219
221
  if importee.end_with?('*')
220
222
  @context.depend_on(importee)
221
- code = ""
223
+ code = String.new
222
224
  resolve(importee, importer).each do |f, i|
223
225
  code << "@import '#{f.filename}';\n"
224
226
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Condenser::JstTransformer < Condenser::NodeProcessor
2
4
 
3
5
  def initialize(dir = nil)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Public: Functions injected into Sass context during Condenser evaluation.
2
4
  #
3
5
  # This module may be extended to add global functionality to all Condenser
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "sassc"
2
4
 
3
5
  class Condenser::Sass::Importer < SassC::Importer
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Condenser::Sass
2
4
  autoload :Functions, 'condenser/transformers/sass/functions'
3
5
  autoload :Importer, 'condenser/transformers/sass/importer'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Transformer engine class for the SASS/SCSS compiler. Depends on the `sass`
2
4
  # gem.
3
5
  #
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Condenser::SVGTransformer::Base
2
4
 
3
5
  attr_accessor :children
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Condenser::SVGTransformer::Tag
2
4
 
3
5
  attr_accessor :tag_name, :attrs, :children, :namespace
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Condenser::SVGTransformer::Template
2
4
 
3
5
  include Condenser::ParseHelpers
@@ -107,7 +109,7 @@ class Condenser::SVGTransformer::Template
107
109
  @tree.last.attrs << { key => matched }
108
110
  end
109
111
  when :tag_attr_value_double_quoted
110
- quoted_value = ''
112
+ quoted_value = String.new
111
113
  scan_until(/"/)
112
114
  quoted_value << pre_match if !pre_match.strip.empty?
113
115
  rewind(1)
@@ -1,2 +1,4 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Condenser::SVGTransformer::TemplateError < StandardError
2
4
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'json'
2
4
 
3
5
  class Condenser::SVGTransformer::Value
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Condenser::SVGTransformer::VarGenerator
2
4
  def initialize
3
5
  @current = nil
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Condenser::SVGTransformer
2
4
 
3
5
  autoload :Base, File.expand_path('../svg_transformer/base', __FILE__)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Condenser
2
4
  module Utils
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Condenser
2
- VERSION = '1.3'
4
+ VERSION = '1.5'
3
5
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'brotli'
2
4
  require 'condenser/utils'
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'condenser/utils'
2
4
 
3
5
  # Writes an asset file to disk
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'zlib'
2
4
  require 'condenser/utils'
3
5
 
data/lib/condenser.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'logger'
2
4
  require 'active_support'
3
5
  require 'active_support/core_ext'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'rake'
2
4
  require 'rake/tasklib'
3
5
 
data/test/cache_test.rb CHANGED
@@ -60,6 +60,19 @@ class CacheTest < ActiveSupport::TestCase
60
60
  CSS
61
61
  end
62
62
 
63
+ test 'changing a source file on calls needs_reprocessing! and needs_reexporting! once' do
64
+ file 'test.txt.erb', "1<%= 1 + 1 %>3\n"
65
+ assert_file 'test.txt', 'text/plain', <<~CSS
66
+ 123
67
+ CSS
68
+
69
+ asset = @env.find('test.txt')
70
+
71
+ asset.expects(:needs_reprocessing!).once
72
+ asset.expects(:needs_reexporting!).once
73
+ file 'test.txt.erb', "1<%= 1 + 2 %>5\n"
74
+ end
75
+
63
76
  test 'changing a js dependency reflects in the next call' do
64
77
  file 'main.js', <<-JS
65
78
  import { cube } from 'math';
@@ -73,13 +86,13 @@ class CacheTest < ActiveSupport::TestCase
73
86
  }
74
87
  JS
75
88
 
76
- assert_exported_file 'main.js', 'application/javascript', <<~CSS
77
- !function(){"use strict";var o;console.log((o=5)*o)}();
78
- CSS
89
+ assert_exported_file 'main.js', 'application/javascript', <<~JS
90
+ function cube(c){return c*c}console.log(cube(5));
91
+ JS
79
92
 
80
- assert_exported_file 'main.js', 'application/javascript', <<~CSS
81
- !function(){"use strict";var o;console.log((o=5)*o)}();
82
- CSS
93
+ assert_exported_file 'main.js', 'application/javascript', <<~JS
94
+ function cube(c){return c*c}console.log(cube(5));
95
+ JS
83
96
 
84
97
  file 'math.js', <<-JS
85
98
  export function cube ( x ) {
@@ -88,7 +101,7 @@ class CacheTest < ActiveSupport::TestCase
88
101
  JS
89
102
 
90
103
  assert_exported_file 'main.js', 'application/javascript', <<~CSS
91
- !function(){"use strict";var o;console.log((o=5)*o*o)}();
104
+ function cube(c){return c*c*c}console.log(cube(5));
92
105
  CSS
93
106
  end
94
107
 
@@ -123,10 +136,10 @@ class CacheTest < ActiveSupport::TestCase
123
136
  JS
124
137
 
125
138
  assert_exported_file 'a.js', 'application/javascript', <<~JS
126
- !function(){"use strict";console.log(5)}();
139
+ console.log(5);
127
140
  JS
128
141
  assert_exported_file 'b.js', 'application/javascript', <<~JS
129
- !function(){"use strict";console.log(5)}();
142
+ console.log(5);
130
143
  JS
131
144
 
132
145
  file 'dep.js', <<-JS
@@ -134,12 +147,11 @@ class CacheTest < ActiveSupport::TestCase
134
147
  JS
135
148
 
136
149
  assert_exported_file 'a.js', 'application/javascript', <<~JS
137
- !function(){"use strict";console.log(10)}();
150
+ console.log(10);
138
151
  JS
139
152
  assert_exported_file 'b.js', 'application/javascript', <<~JS
140
- !function(){"use strict";console.log(10)}();
153
+ console.log(10);
141
154
  JS
142
-
143
155
  end
144
156
 
145
157
  test 'a dependency is superceeded by a new file' do
@@ -158,7 +170,7 @@ class CacheTest < ActiveSupport::TestCase
158
170
  JS
159
171
 
160
172
  assert_exported_file 'a.js', 'application/javascript', <<~JS
161
- !function(){"use strict";console.log(5)}();
173
+ console.log(5);
162
174
  JS
163
175
 
164
176
  file 'a/dep.js', <<-JS
@@ -166,7 +178,7 @@ class CacheTest < ActiveSupport::TestCase
166
178
  JS
167
179
 
168
180
  assert_exported_file 'a.js', 'application/javascript', <<~JS
169
- !function(){"use strict";console.log(10)}();
181
+ console.log(10);
170
182
  JS
171
183
  end
172
184
 
@@ -186,7 +198,7 @@ class CacheTest < ActiveSupport::TestCase
186
198
  JS
187
199
 
188
200
  assert_exported_file 'a.js', 'application/javascript', <<~JS
189
- !function(){"use strict";console.log(5)}();
201
+ console.log(5);
190
202
  JS
191
203
 
192
204
  file 'a/deps/dep.js', <<-JS
@@ -194,7 +206,7 @@ class CacheTest < ActiveSupport::TestCase
194
206
  JS
195
207
 
196
208
  assert_exported_file 'a.js', 'application/javascript', <<~JS
197
- !function(){"use strict";console.log(10)}();
209
+ console.log(10);
198
210
  JS
199
211
 
200
212
  file 'a/deps/dep.js', <<-JS
@@ -202,7 +214,7 @@ class CacheTest < ActiveSupport::TestCase
202
214
  JS
203
215
 
204
216
  assert_exported_file 'a.js', 'application/javascript', <<~JS
205
- !function(){"use strict";console.log(20)}();
217
+ console.log(20);
206
218
  JS
207
219
  end
208
220
 
@@ -259,7 +271,7 @@ class CacheTest < ActiveSupport::TestCase
259
271
  JS
260
272
 
261
273
  assert_exported_file 'a.js', 'application/javascript', <<~JS
262
- !function(){"use strict";console.log("a")}();
274
+ console.log("a");
263
275
  JS
264
276
 
265
277
  file 'a.js', <<~JS
@@ -269,7 +281,7 @@ class CacheTest < ActiveSupport::TestCase
269
281
  JS
270
282
 
271
283
  assert_exported_file 'a.js', 'application/javascript', <<~JS
272
- !function(){"use strict";console.log("a"),console.log("b")}();
284
+ function b(){console.log("b")}console.log("a"),b();
273
285
  JS
274
286
 
275
287
  file 'b.js', <<~JS
@@ -277,7 +289,7 @@ class CacheTest < ActiveSupport::TestCase
277
289
  JS
278
290
 
279
291
  assert_exported_file 'a.js', 'application/javascript', <<~JS
280
- !function(){"use strict";console.log("a"),console.log("c")}();
292
+ function b(){console.log("c")}console.log("a"),b();
281
293
  JS
282
294
  end
283
295
 
@@ -308,5 +320,88 @@ class CacheTest < ActiveSupport::TestCase
308
320
  body{background:green}body{background:aqua}
309
321
  JS
310
322
  end
323
+
324
+ test 'ensure the build cache only walks the dependency tree once' do
325
+ # a
326
+ # | |
327
+ # b c
328
+ # |
329
+ # d
330
+
331
+ file 'd.js', "export default function d () { console.log('d'); }\n"
332
+ file 'b.js', "export default function b () { console.log('b'); }\n"
333
+ file 'c.js', <<~JS
334
+ import d from 'd';
335
+
336
+ export default function c () { console.log('c'); d(); }
337
+ JS
338
+ file 'a.js', <<~JS
339
+ import b from 'b';
340
+ import c from 'c';
341
+
342
+ console.log('a'); b(); c();
343
+ JS
344
+
345
+ assert_exported_file 'a.js', 'application/javascript', <<~JS
346
+ function b(){console.log("b")}function d(){console.log("d")}function c(){console.log("c"),d()}console.log("a"),b(),c();
347
+ JS
311
348
 
349
+ file 'd.js', "export default function e () { console.log('e'); }\n"
350
+
351
+ pd = @env.build_cache.instance_variable_get(:@process_dependencies)
352
+ pd["#{@path}/a.js"] ||= Set.new
353
+ pd["#{@path}/b.js"] ||= Set.new
354
+ pd["#{@path}/c.js"] ||= Set.new
355
+ pd["#{@path}/d.js"] ||= Set.new
356
+ pd["#{@path}/a.js"].expects(:<<).with { |a| a.source_file == "#{@path}/a.js" }.once
357
+ pd["#{@path}/b.js"].expects(:<<).with { |a| a.source_file == "#{@path}/b.js" }.never
358
+ pd["#{@path}/c.js"].expects(:<<).with { |a| a.source_file == "#{@path}/c.js" }.never
359
+ pd["#{@path}/d.js"].expects(:<<).with { |a| a.source_file == "#{@path}/d.js" }.once
360
+
361
+ assert_exported_file 'a.js', 'application/javascript', <<~JS
362
+ function b(){console.log("b")}function e(){console.log("e")}function c(){console.log("c"),e()}console.log("a"),b(),c();
363
+ JS
364
+ end
365
+
366
+ test 'same files in diffrent dirs sharing a cache doesnt poison the cache (ie capistrano deploys)' do
367
+ cachepath = Dir.mktmpdir
368
+
369
+ dir = File.realpath(Dir.mktmpdir)
370
+ base1 = File.join(dir, 'a')
371
+ base2 = File.join(dir, 'b')
372
+ base3 = File.join(dir, 'c')
373
+ Dir.mkdir(base1)
374
+ Dir.mkdir(base2)
375
+
376
+ [base1, base2, base3].each do |b|
377
+ file 'test.js', "export default function c () { console.log('t'); }\n", base: b
378
+ file 'test/b.js', <<~JS, base: b
379
+ import c from './c';
380
+ export default function b () { console.log('b'); c(); }
381
+ JS
382
+ file 'test/a.js', <<~JS, base: b
383
+ import t from 'test';
384
+ import b from './b';
385
+
386
+ console.log('a');
387
+ b();
388
+ JS
389
+ end
390
+
391
+ file 'test/c.js', "export default function c () { console.log('c'); }\n", base: base1
392
+ file 'test/c.js', "export default function c () { console.log('d'); }\n", base: base2
393
+ file 'test/c.js', "export default function c () { console.log('e'); }\n", base: base3
394
+
395
+ # Set the cache
396
+ env1 = Condenser.new(base1, logger: Logger.new(STDOUT, level: :debug), base: base1, npm_path: @npm_dir, cache: Condenser::Cache::FileStore.new(cachepath))
397
+ assert_equal 'function c(){console.log("c")}function b(){console.log("b"),c()}console.log("a"),b();', env1.find('test/a.js').export.source
398
+
399
+ # Poison the cache
400
+ env2 = Condenser.new(base2, logger: Logger.new(STDOUT, level: :debug), base: base2, npm_path: @npm_dir, cache: Condenser::Cache::FileStore.new(cachepath))
401
+ assert_equal 'function c(){console.log("d")}function b(){console.log("b"),c()}console.log("a"),b();', env2.find('test/a.js').export.source
402
+
403
+ # Fails to find dependency change because cache is missing the dependency
404
+ env3 = Condenser.new(base3, logger: Logger.new(STDOUT, level: :debug), base: base3, npm_path: @npm_dir, cache: Condenser::Cache::FileStore.new(cachepath))
405
+ assert_equal 'function c(){console.log("e")}function b(){console.log("b"),c()}console.log("a"),b();', env3.find('test/a.js').export.source
406
+ end
312
407
  end
@@ -17,7 +17,7 @@ class DependencyTest < ActiveSupport::TestCase
17
17
  JS
18
18
 
19
19
  asset = @env.find('name.js')
20
- assert_equal asset.instance_variable_get(:@process_dependencies).to_a, ["models/*.js","helpers/*.js"]
20
+ assert_equal asset.instance_variable_get(:@process_dependencies).to_a, [["models/*", ["application/javascript"]],["helpers/*", ["application/javascript"]]]
21
21
 
22
22
 
23
23
  assert_file 'name.js', 'application/javascript', <<~JS
@@ -54,7 +54,7 @@ class DependencyTest < ActiveSupport::TestCase
54
54
  JS
55
55
 
56
56
  asset = @env.find('name.js')
57
- assert_equal asset.instance_variable_get(:@process_dependencies).to_a, ["models/*.js","helpers/*.js"]
57
+ assert_equal asset.instance_variable_get(:@process_dependencies).to_a, [["models/*", ["application/javascript"]],["helpers/*", ["application/javascript"]]]
58
58
 
59
59
 
60
60
  assert_file 'name.js', 'application/javascript', <<~JS
@@ -74,4 +74,53 @@ class DependencyTest < ActiveSupport::TestCase
74
74
  JS
75
75
  end
76
76
 
77
+ test 'js depending on another file type with JSAnalzyer' do
78
+ @env.unregister_preprocessor 'application/javascript', Condenser::BabelProcessor
79
+ @env.register_preprocessor 'application/javascript', Condenser::JSAnalyzer
80
+ @env.unregister_minifier('application/javascript')
81
+
82
+ file 'a.js', ''
83
+ file 'b.rb', ''
84
+ file 'models/a.js', ''
85
+ file 'models/b.rb', ''
86
+
87
+ file 'name.js.erb', <<~JS
88
+ // depends_on **/*.rb
89
+
90
+ console.log([<%= Dir.children("#{@path}").sort.map(&:inspect).join(', ') %>]);
91
+ JS
92
+
93
+ asset = @env.find('name.js')
94
+ assert_equal asset.instance_variable_get(:@process_dependencies).to_a, [["**/*", ["application/ruby"]]]
95
+ assert_equal asset.process_dependencies.map(&:source_file), ["#{@path}/b.rb", "#{@path}/models/b.rb"]
96
+ end
97
+
98
+ test 'relative imports with JSAnalzyer' do
99
+ @env.unregister_preprocessor 'application/javascript', Condenser::BabelProcessor
100
+ @env.register_preprocessor 'application/javascript', Condenser::JSAnalyzer
101
+ @env.unregister_minifier('application/javascript')
102
+
103
+ file 'a/a.js', <<~JS
104
+ export decault function () { console.log("a/a"); }
105
+ JS
106
+ file 'b/a.js', <<~JS
107
+ export decault function () { console.log("a/a"); }
108
+ JS
109
+
110
+ file 'a/b.js', <<~JS
111
+ import fn from './a';
112
+ a();
113
+ console.log("a/b");
114
+ JS
115
+ file 'b/b.js', <<~JS
116
+ import fn from './a';
117
+ a();
118
+ console.log("b/b");
119
+ JS
120
+
121
+ asset = @env.find('a/b.js')
122
+ assert_equal asset.instance_variable_get(:@export_dependencies).to_a, [["#{@path}/a/a", ["application/javascript"]]]
123
+ assert_equal asset.export_dependencies.map(&:source_file), ["#{@path}/a/a.js"]
124
+ end
125
+
77
126
  end
@@ -62,8 +62,8 @@ class ManifestTest < ActiveSupport::TestCase
62
62
 
63
63
  data = JSON.parse(File.read(manifest.filename))
64
64
  assert data['application.js']
65
- assert data['application.js']['size'] > 16
66
- assert_equal asset.path, data['application.js']['path']
65
+ assert_equal asset.path, data['application.js']['path']
66
+ assert_equal 15, data['application.js']['size']
67
67
  end
68
68
 
69
69
  test "compile asset dependencies includes the dependencies" do
@@ -541,4 +541,19 @@ class ManifestTest < ActiveSupport::TestCase
541
541
  # assert_equal %w(0 1 0 1), processor.seq
542
542
  # end
543
543
 
544
+ test "javascript types are in the manifest" do
545
+ file 'application.js', <<-JS
546
+ console.log(1);
547
+ JS
548
+
549
+ manifest = Condenser::Manifest.new(@env, File.join(@dir, 'manifest.json'))
550
+ manifest.compile('application.js')
551
+ assert File.directory?(manifest.dir)
552
+ assert File.file?(manifest.filename)
553
+ assert File.exist?("#{@dir}/manifest.json")
554
+
555
+ data = JSON.parse(File.read(manifest.filename))
556
+ assert data['application.js']
557
+ assert_equal "module", data['application.js']['type']
558
+ end
544
559
  end