condenser 1.0 → 1.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 24f2e6a83798d231764a5940648a38a65f72c34e55e70e833292397bb98347a8
4
- data.tar.gz: 384ceedcef19c3137ad969a255fe8519eb37ac20116c54879ccaa19a05a331c3
3
+ metadata.gz: e2b1dab33dd825d2bf0902e871c68c0334d49ee7af48ee0875132f39adce20d2
4
+ data.tar.gz: a3c40f6f19722d0cea00e28592cd2049db5185057b299bf697fc169c9a19c89a
5
5
  SHA512:
6
- metadata.gz: 906d4e278f46053c31bd55943fab2100468f604aa43472a98993ea71350384abde3b0181f08d8357c814f020c897a359fe496397012a402602f0cdc8777695ae
7
- data.tar.gz: f96cfdc8570e74939b71a4257a3b8647495aac682f49cc5a60e39f653367fbf6e73fe77cd5965e1f92b4cab899cf3262be7533158cf4760d2e7e166a244fe0e7
6
+ metadata.gz: c1ca10d2f7dff116d1b4d4daeba50302509c7faffed458e2312d40c391b84a407d596487102a4e306abd9a96bd435c39d0fb23add68a3608aa64014b3fffe0d7
7
+ data.tar.gz: 3f530d21b0ec272d51aabd96f0218dfc1a02dbb8845dbefd3d92cf1517447bc436785a102415ad9fda696df26d9769f67485f8530445eb66b48dc3318ffd8e72
@@ -18,6 +18,7 @@ class Condenser
18
18
  autoload :BabelProcessor, 'condenser/processors/babel_processor'
19
19
  autoload :RollupProcessor, 'condenser/processors/rollup_processor'
20
20
  autoload :JSAnalyzer, 'condenser/processors/js_analyzer'
21
+ autoload :PurgeCSSProcessor,'condenser/processors/purgecss_processor'
21
22
  autoload :NodeProcessor, 'condenser/processors/node_processor'
22
23
  autoload :UglifyMinifier, 'condenser/minifiers/uglify_minifier'
23
24
  autoload :TerserMinifier, 'condenser/minifiers/terser_minifier'
@@ -159,7 +159,7 @@ class Condenser
159
159
  Digest::SHA256.file(dep.source_file).hexdigest
160
160
  ]
161
161
  end
162
-
162
+
163
163
  @pcv = Digest::SHA1.base64digest(JSON.generate(f))
164
164
  end
165
165
 
@@ -241,6 +241,7 @@ class Condenser
241
241
  data[:processors] << processor_klass.name
242
242
  @environment.load_processors(processor_klass)
243
243
 
244
+ @environment.logger.info { "Pre Processing #{self.filename} with #{processor.name}" }
244
245
  processor.call(@environment, data)
245
246
  end
246
247
  end
@@ -257,6 +258,17 @@ class Condenser
257
258
  data[:content_type] << to_mime_type
258
259
  end
259
260
  end
261
+
262
+ if @environment.postprocessors.has_key?(data[:content_type].last)
263
+ @environment.postprocessors[data[:content_type].last].each do |processor|
264
+ processor_klass = (processor.is_a?(Class) ? processor : processor.class)
265
+ data[:processors] << processor_klass.name
266
+ @environment.load_processors(processor_klass)
267
+
268
+ @environment.logger.info { "Post Processing #{self.filename} with #{processor.name}" }
269
+ processor.call(@environment, data)
270
+ end
271
+ end
260
272
 
261
273
  if mime_types != @content_types
262
274
  raise ContentTypeMismatch, "mime type(s) \"#{@content_types.join(', ')}\" does not match requested mime type(s) \"#{data[:mime_types].join(', ')}\""
@@ -335,6 +347,15 @@ class Condenser
335
347
  data[:digest_name] = @environment.digestor.name.sub(/^.*::/, '').downcase
336
348
  data
337
349
  end
350
+
351
+ if @environment.build_cache.listening
352
+ # TODO we could skip file and all their depencies here if they are
353
+ # already in build_cache.@export_dependencies
354
+ all_export_dependencies.each do |sf|
355
+ @environment.build_cache.instance_variable_get(:@export_dependencies)[sf]&.add(self)
356
+ end
357
+ end
358
+
338
359
  Export.new(@environment, data)
339
360
  end
340
361
  end
@@ -5,9 +5,8 @@ class Condenser::TerserMinifier < Condenser::NodeProcessor
5
5
  npm_install('terser')
6
6
 
7
7
  @options = options.merge({
8
- warnings: true,
9
- sourceMap: false,
10
- keep_classnames: true
8
+ keep_classnames: true,
9
+ keep_fnames: true
11
10
  }).freeze
12
11
  end
13
12
 
@@ -28,13 +27,12 @@ class Condenser::TerserMinifier < Condenser::NodeProcessor
28
27
  const options = #{JSON.generate(opts)};
29
28
 
30
29
 
31
- var result = Terser.minify(source, options);
32
- if (result.error !== undefined) {
33
- console.log(JSON.stringify({'error': result.error.name + ": " + result.error.message}));
34
- process.exit(1);
35
- } else {
30
+ Terser.minify(source, options).then((result) => {
36
31
  console.log(JSON.stringify(result));
37
- }
32
+ }, (error) => {
33
+ console.log(JSON.stringify({'error': error.name + ": " + error.message}));
34
+ process.exit(1);
35
+ });
38
36
  JS
39
37
 
40
38
  exec_runtime_error(result['error']) if result['error']
@@ -8,6 +8,10 @@ class Condenser
8
8
 
9
9
  def self.setup(environment)
10
10
  end
11
+
12
+ def name
13
+ self.class.name
14
+ end
11
15
 
12
16
  def self.call(environment, input)
13
17
  @instances ||= {}
@@ -0,0 +1,70 @@
1
+ require 'json'
2
+
3
+ class Condenser::PurgeCSSProcessor < Condenser::NodeProcessor
4
+
5
+ attr_accessor :options
6
+
7
+ # Public: initialize with custom options.
8
+ #
9
+ # dir - String (path to node_modules directory)
10
+ # options - Hash
11
+ # content - Array - html files to process
12
+ # ex. [File.expand_path('./docs-src/**/*.erb'), File.expand_path('./docs-src/assets/javascripts/**/*.js')]
13
+ #
14
+ # Options are passed to PurgeCSS checkout [PurgeCSS Configurations](https://purgecss.com/configuration.html)
15
+ #
16
+
17
+ def self.call(environment, input)
18
+ @instances ||= {}
19
+ @instances[environment] ||= new(environment.npm_path, {
20
+ content: [File.join(environment.base, '**/*.html'), File.join(environment.base, '**/*.js')]
21
+ })
22
+ @instances[environment].call(environment, input)
23
+ end
24
+
25
+
26
+ def initialize(dir = nil, options = {})
27
+ super(dir)
28
+ @options = options
29
+ npm_install('purgecss')
30
+ end
31
+
32
+ def call(environment, input)
33
+ result = exec_runtime(<<-JS)
34
+ const { PurgeCSS } = require("#{File.join(npm_module_path('purgecss'))}")
35
+ const options = #{@options.to_json}
36
+ options.css = [{
37
+ raw: #{input[:source].inspect}
38
+ }]
39
+ if(options.safelist) {
40
+ options.safelist = options.safelist.map(s => {
41
+ if(s[0] == "/" && s[s.length - 1] == "/") {
42
+ return new RegExp(s.slice(1, -1))
43
+ }
44
+ return s
45
+ })
46
+ }
47
+ const result = new PurgeCSS().purge(options)
48
+ try {
49
+ result.then(
50
+ r => console.log(JSON.stringify({
51
+ success: r[0]
52
+ })),
53
+ function() {console.log(JSON.stringify({'error': arguments}))}
54
+ )
55
+ } catch(e) {
56
+ console.log(JSON.stringify({'error': [e.name, e.message, e.stack]}));
57
+ }
58
+ JS
59
+ if result['error']
60
+ if result['error'][0] == 'SyntaxError'
61
+ raise exec_syntax_error(result['error'][1], "/assets/#{input[:filename]}")
62
+ else
63
+ raise exec_runtime_error(result['error'][0] + ': ' + result['error'][1])
64
+ end
65
+ else
66
+ input[:source] = result["success"]["css"]
67
+ end
68
+ end
69
+
70
+ end
@@ -217,8 +217,6 @@ class Condenser::RollupProcessor < Condenser::NodeProcessor
217
217
  importee = message['args'].first
218
218
  if importee == @entry
219
219
  { code: @input[:source], map: @input[:map] }
220
- elsif importee.start_with?(npm_module_path)
221
- { code: File.read(importee), map: nil }
222
220
  elsif importee.end_with?('*')
223
221
  importees = @environment.resolve(importee, importer ? File.dirname(@entry == importer ? @input[:source_file] : importer) : nil, accept: @input[:content_types].last)
224
222
  code = ""
@@ -1,3 +1,3 @@
1
1
  class Condenser
2
- VERSION = '1.0'
2
+ VERSION = '1.2'
3
3
  end
@@ -22,7 +22,7 @@ class CacheFileStoreTest < ActiveSupport::TestCase
22
22
 
23
23
  oldenv = @env
24
24
  begin
25
- @env = Condenser.new(@path)
25
+ @env = Condenser.new(@path, base: @path)
26
26
  @env.cache = Condenser::Cache::FileStore.new(@cachepath)
27
27
  Condenser::Erubi.stubs(:call).never
28
28
 
@@ -237,4 +237,32 @@ class CacheTest < ActiveSupport::TestCase
237
237
  CSS
238
238
  end
239
239
 
240
+ test 'a dependency is added then changed should flush the parent' do
241
+ file 'a.js', "console.log('a');\n"
242
+ file 'b.js', <<~JS
243
+ export default function b () { console.log('b'); }
244
+ JS
245
+
246
+ assert_exported_file 'a.js', 'application/javascript', <<~JS
247
+ !function(){"use strict";console.log("a")}();
248
+ JS
249
+
250
+ file 'a.js', <<~JS
251
+ import b from 'b';
252
+ console.log('a');
253
+ b();
254
+ JS
255
+
256
+ assert_exported_file 'a.js', 'application/javascript', <<~JS
257
+ !function(){"use strict";console.log("a"),console.log("b")}();
258
+ JS
259
+
260
+ file 'b.js', <<~JS
261
+ export default function b () { console.log('c'); }
262
+ JS
263
+
264
+ assert_exported_file 'a.js', 'application/javascript', <<~JS
265
+ !function(){"use strict";console.log("a"),console.log("c")}();
266
+ JS
267
+ end
240
268
  end
@@ -27,8 +27,8 @@ class TerserMinifierTest < ActiveSupport::TestCase
27
27
  }
28
28
  JS
29
29
 
30
- @env.logger.expects(:warn).with('Dropping unused variable u [test.js:8,6]')
31
- @env.logger.expects(:warn).with('Dropping unused variable bl [test.js:10,6]')
30
+ # @env.logger.expects(:warn).with('Dropping unused variable u [test.js:8,6]')
31
+ # @env.logger.expects(:warn).with('Dropping unused variable bl [test.js:10,6]')
32
32
 
33
33
  assert_exported_file 'test.js', 'application/javascript', <<~CSS
34
34
  class MyClass{fn(){console.log("Hello")}}function fa(){return console.log(1),5}
@@ -0,0 +1,83 @@
1
+ require 'test_helper'
2
+
3
+ class PurgeCSSTest < ActiveSupport::TestCase
4
+
5
+ def setup
6
+ super
7
+ @env.register_postprocessor('text/css', Condenser::PurgeCSSProcessor)
8
+ @env.unregister_minifier('text/css')
9
+ end
10
+
11
+ test 'purge from html' do
12
+ file 'main.css', <<~CSS
13
+ .test{
14
+ display: block;
15
+ }
16
+ .test2{
17
+ display: inline;
18
+ }
19
+ CSS
20
+ file 'index.html', <<~HTML
21
+ <div class="test2"></div>
22
+ HTML
23
+
24
+ assert_exported_file 'main.css', 'text/css', <<~FILE
25
+ .test2{
26
+ display: inline;
27
+ }
28
+ FILE
29
+ end
30
+
31
+ test 'purge from js' do
32
+ file 'main.css', <<~CSS
33
+ .test{
34
+ display: block;
35
+ }
36
+ .test2{
37
+ display: inline;
38
+ }
39
+ .test3{
40
+ display: inline-block;
41
+ }
42
+ CSS
43
+ file 'main.js', <<~HTML
44
+ document.getElementById('foo').classList.add('test3', 'test2');
45
+ HTML
46
+
47
+ assert_exported_file 'main.css', 'text/css', <<~FILE
48
+ .test2{
49
+ display: inline;
50
+ }
51
+ .test3{
52
+ display: inline-block;
53
+ }
54
+ FILE
55
+ end
56
+
57
+ test 'purge from js with space separated classes' do
58
+ file 'main.css', <<~CSS
59
+ .test{
60
+ display: block;
61
+ }
62
+ .test2{
63
+ display: inline;
64
+ }
65
+ .test3{
66
+ display: inline-block;
67
+ }
68
+ CSS
69
+ file 'main.js', <<~HTML
70
+ document.getElementById('foo').setAttribute('class', 'test3 test2');
71
+ HTML
72
+
73
+ assert_exported_file 'main.css', 'text/css', <<~FILE
74
+ .test2{
75
+ display: inline;
76
+ }
77
+ .test3{
78
+ display: inline-block;
79
+ }
80
+ FILE
81
+ end
82
+
83
+ end
@@ -134,7 +134,7 @@ class CondenserBabelTest < ActiveSupport::TestCase
134
134
  check(typeof self == 'object' && self) ||
135
135
  check(typeof commonjsGlobal == 'object' && commonjsGlobal) ||
136
136
  // eslint-disable-next-line no-new-func
137
- Function('return this')();
137
+ (function () { return this; })() || Function('return this')();
138
138
 
139
139
  var fails = function (exec) {
140
140
  try {
@@ -622,4 +622,44 @@ class CondenserBabelTest < ActiveSupport::TestCase
622
622
  JS
623
623
  end
624
624
 
625
+ test 'npm modules also get babelized' do
626
+ file "#{@npm_path}/module/name.js", <<~JS
627
+ export default class { };
628
+ JS
629
+
630
+ file 'name.js', <<~JS
631
+ import C from 'module/name';
632
+
633
+ class D extends C { }
634
+ JS
635
+
636
+ assert_file 'name.js', 'application/javascript', <<~JS
637
+ import _Reflect$construct from "@babel/runtime-corejs3/core-js-stable/reflect/construct";
638
+ import _classCallCheck from "@babel/runtime-corejs3/helpers/esm/classCallCheck";
639
+ import _inherits from "@babel/runtime-corejs3/helpers/esm/inherits";
640
+ import _possibleConstructorReturn from "@babel/runtime-corejs3/helpers/esm/possibleConstructorReturn";
641
+ import _getPrototypeOf from "@babel/runtime-corejs3/helpers/esm/getPrototypeOf";
642
+
643
+ function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = _Reflect$construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }
644
+
645
+ function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !_Reflect$construct) return false; if (_Reflect$construct.sham) return false; if (typeof Proxy === "function") return true; try { Date.prototype.toString.call(_Reflect$construct(Date, [], function () {})); return true; } catch (e) { return false; } }
646
+
647
+ import C from 'module/name';
648
+
649
+ var D = /*#__PURE__*/function (_C) {
650
+ _inherits(D, _C);
651
+
652
+ var _super = _createSuper(D);
653
+
654
+ function D() {
655
+ _classCallCheck(this, D);
656
+
657
+ return _super.apply(this, arguments);
658
+ }
659
+
660
+ return D;
661
+ }(C);
662
+ JS
663
+
664
+ end
625
665
  end
@@ -34,7 +34,7 @@ class ActiveSupport::TestCase
34
34
  @path = File.realpath(Dir.mktmpdir)
35
35
  @npm_dir = File.expand_path('../../tmp', __FILE__)
36
36
  Dir.mkdir(@npm_dir) if !Dir.exist?(@npm_dir)
37
- @env = Condenser.new(@path, logger: Logger.new('/dev/null', level: :debug), npm_path: @npm_dir)
37
+ @env = Condenser.new(@path, logger: Logger.new('/dev/null', level: :debug), npm_path: @npm_dir, base: @path)
38
38
  @env.unregister_writer(Condenser::ZlibWriter)
39
39
  @env.unregister_writer(Condenser::BrotliWriter)
40
40
  @env.context_class.class_eval do
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: condenser
3
3
  version: !ruby/object:Gem::Version
4
- version: '1.0'
4
+ version: '1.2'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jon Bracy
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-11-04 00:00:00.000000000 Z
11
+ date: 2020-12-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: erubi
@@ -326,6 +326,7 @@ files:
326
326
  - lib/condenser/processors/babel_processor.rb
327
327
  - lib/condenser/processors/js_analyzer.rb
328
328
  - lib/condenser/processors/node_processor.rb
329
+ - lib/condenser/processors/purgecss_processor.rb
329
330
  - lib/condenser/processors/rollup_processor.rb
330
331
  - lib/condenser/resolve.rb
331
332
  - lib/condenser/server.rb
@@ -349,6 +350,7 @@ files:
349
350
  - test/minifiers/terser_minifier_test.rb
350
351
  - test/minifiers/uglify_minifier_test.rb
351
352
  - test/pipeline_test.rb
353
+ - test/postprocessors/purgecss_test.rb
352
354
  - test/preprocessor/babel_test.rb
353
355
  - test/preprocessor/js_analyzer_test.rb
354
356
  - test/processors/rollup_test.rb
@@ -396,6 +398,7 @@ test_files:
396
398
  - test/minifiers/terser_minifier_test.rb
397
399
  - test/minifiers/uglify_minifier_test.rb
398
400
  - test/pipeline_test.rb
401
+ - test/postprocessors/purgecss_test.rb
399
402
  - test/preprocessor/babel_test.rb
400
403
  - test/preprocessor/js_analyzer_test.rb
401
404
  - test/processors/rollup_test.rb