condenser 1.0 → 1.2

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.
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