condenser 1.0 → 1.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/condenser.rb +1 -0
- data/lib/condenser/asset.rb +22 -1
- data/lib/condenser/minifiers/terser_minifier.rb +7 -9
- data/lib/condenser/processors/node_processor.rb +4 -0
- data/lib/condenser/processors/purgecss_processor.rb +70 -0
- data/lib/condenser/processors/rollup_processor.rb +0 -2
- data/lib/condenser/version.rb +1 -1
- data/test/cache_stores/file_store_test.rb +1 -1
- data/test/cache_test.rb +28 -0
- data/test/minifiers/terser_minifier_test.rb +2 -2
- data/test/postprocessors/purgecss_test.rb +83 -0
- data/test/preprocessor/babel_test.rb +41 -1
- data/test/test_helper.rb +1 -1
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e2b1dab33dd825d2bf0902e871c68c0334d49ee7af48ee0875132f39adce20d2
|
4
|
+
data.tar.gz: a3c40f6f19722d0cea00e28592cd2049db5185057b299bf697fc169c9a19c89a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c1ca10d2f7dff116d1b4d4daeba50302509c7faffed458e2312d40c391b84a407d596487102a4e306abd9a96bd435c39d0fb23add68a3608aa64014b3fffe0d7
|
7
|
+
data.tar.gz: 3f530d21b0ec272d51aabd96f0218dfc1a02dbb8845dbefd3d92cf1517447bc436785a102415ad9fda696df26d9769f67485f8530445eb66b48dc3318ffd8e72
|
data/lib/condenser.rb
CHANGED
@@ -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'
|
data/lib/condenser/asset.rb
CHANGED
@@ -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
|
-
|
9
|
-
|
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
|
-
|
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']
|
@@ -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 = ""
|
data/lib/condenser/version.rb
CHANGED
data/test/cache_test.rb
CHANGED
@@ -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
|
data/test/test_helper.rb
CHANGED
@@ -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.
|
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
|
+
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
|