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