condenser 1.0 → 1.3

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 (53) hide show
  1. checksums.yaml +4 -4
  2. data/lib/condenser/asset.rb +41 -17
  3. data/lib/condenser/build_cache.rb +1 -1
  4. data/lib/condenser/context.rb +9 -25
  5. data/lib/condenser/helpers/parse_helpers.rb +1 -1
  6. data/lib/condenser/manifest.rb +3 -1
  7. data/lib/condenser/minifiers/terser_minifier.rb +7 -9
  8. data/lib/condenser/pipeline.rb +8 -3
  9. data/lib/condenser/processors/babel_processor.rb +1 -1
  10. data/lib/condenser/processors/css_media_combiner_processor.rb +81 -0
  11. data/lib/condenser/processors/js_analyzer.rb +0 -2
  12. data/lib/condenser/processors/node_processor.rb +4 -0
  13. data/lib/condenser/processors/purgecss_processor.rb +72 -0
  14. data/lib/condenser/processors/rollup_processor.rb +37 -37
  15. data/lib/condenser/resolve.rb +1 -3
  16. data/lib/condenser/templating_engine/ejs.rb +1 -1
  17. data/lib/condenser/transformers/dart_sass_transformer.rb +285 -0
  18. data/lib/condenser/transformers/jst_transformer.rb +67 -17
  19. data/lib/condenser/transformers/sass/functions.rb +133 -0
  20. data/lib/condenser/transformers/sass/importer.rb +48 -0
  21. data/lib/condenser/transformers/sass.rb +4 -0
  22. data/lib/condenser/transformers/sass_transformer.rb +124 -281
  23. data/lib/condenser/transformers/svg_transformer/base.rb +26 -0
  24. data/lib/condenser/transformers/svg_transformer/tag.rb +54 -0
  25. data/lib/condenser/transformers/svg_transformer/template.rb +151 -0
  26. data/lib/condenser/transformers/svg_transformer/template_error.rb +2 -0
  27. data/lib/condenser/transformers/svg_transformer/value.rb +13 -0
  28. data/lib/condenser/transformers/svg_transformer/var_generator.rb +10 -0
  29. data/lib/condenser/transformers/svg_transformer.rb +19 -0
  30. data/lib/condenser/version.rb +1 -1
  31. data/lib/condenser.rb +18 -5
  32. data/test/cache_stores/file_store_test.rb +1 -1
  33. data/test/cache_test.rb +73 -1
  34. data/test/dependency_test.rb +2 -2
  35. data/test/manifest_test.rb +34 -0
  36. data/test/minifiers/terser_minifier_test.rb +2 -3
  37. data/test/minifiers/uglify_minifier_test.rb +0 -1
  38. data/test/postprocessors/css_media_combiner_test.rb +107 -0
  39. data/test/postprocessors/purgecss_test.rb +145 -0
  40. data/test/preprocessor/babel_test.rb +702 -268
  41. data/test/preprocessor/js_analyzer_test.rb +0 -2
  42. data/test/processors/rollup_test.rb +50 -20
  43. data/test/resolve_test.rb +8 -9
  44. data/test/server_test.rb +6 -1
  45. data/test/templates/ejs_test.rb +2 -11
  46. data/test/templates/erb_test.rb +0 -5
  47. data/test/test_helper.rb +4 -2
  48. data/test/transformers/dart_scss_test.rb +139 -0
  49. data/test/transformers/jst_test.rb +165 -21
  50. data/test/transformers/scss_test.rb +14 -0
  51. data/test/transformers/svg_test.rb +40 -0
  52. metadata +26 -6
  53. data/lib/condenser/transformers/sass_transformer/importer.rb +0 -50
@@ -0,0 +1,19 @@
1
+ class Condenser::SVGTransformer
2
+
3
+ autoload :Base, File.expand_path('../svg_transformer/base', __FILE__)
4
+ autoload :Tag, File.expand_path('../svg_transformer/tag', __FILE__)
5
+ autoload :Template, File.expand_path('../svg_transformer/template', __FILE__)
6
+ autoload :TemplateError, File.expand_path('../svg_transformer/template_error', __FILE__)
7
+ autoload :Value, File.expand_path('../svg_transformer/value', __FILE__)
8
+ autoload :VarGenerator, File.expand_path('../svg_transformer/var_generator', __FILE__)
9
+
10
+ def self.setup(env)
11
+ end
12
+
13
+ def self.call(environment, input)
14
+ input[:source] = Condenser::SVGTransformer::Template.new(input[:source]).to_module
15
+ end
16
+
17
+ end
18
+
19
+
@@ -1,3 +1,3 @@
1
1
  class Condenser
2
- VERSION = '1.0'
2
+ VERSION = '1.3'
3
3
  end
data/lib/condenser.rb CHANGED
@@ -18,19 +18,26 @@ 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'
22
+ autoload :CSSMediaCombinerProcessor,'condenser/processors/css_media_combiner_processor'
21
23
  autoload :NodeProcessor, 'condenser/processors/node_processor'
22
24
  autoload :UglifyMinifier, 'condenser/minifiers/uglify_minifier'
23
25
  autoload :TerserMinifier, 'condenser/minifiers/terser_minifier'
24
26
  autoload :Erubi, 'condenser/templating_engine/erb'
27
+ autoload :Sass, 'condenser/transformers/sass'
25
28
  autoload :SassMinifier, 'condenser/minifiers/sass_minifier'
26
- autoload :SassTransformer, 'condenser/transformers/sass_transformer'
29
+ autoload :DartSassTransformer, 'condenser/transformers/dart_sass_transformer'
30
+ autoload :DartScssTransformer, 'condenser/transformers/dart_sass_transformer'
31
+ autoload :SassTransformer, 'condenser/transformers/sass_transformer'
27
32
  autoload :ScssTransformer, 'condenser/transformers/sass_transformer'
28
- autoload :EjsTemplare, 'condenser/templating_engine/ejs'
33
+ autoload :EjsTemplate, 'condenser/templating_engine/ejs'
29
34
  autoload :JstTransformer, 'condenser/transformers/jst_transformer'
35
+ autoload :SVGTransformer, 'condenser/transformers/svg_transformer'
30
36
  autoload :FileWriter, 'condenser/writers/file_writer'
31
37
  autoload :ZlibWriter, 'condenser/writers/zlib_writer'
32
38
  autoload :BrotliWriter, 'condenser/writers/brotli_writer'
33
39
  autoload :BuildCache, 'condenser/build_cache'
40
+ autoload :ParseHelpers, 'condenser/helpers/parse_helpers'
34
41
 
35
42
  def self.configure(&block)
36
43
  instance_eval(&block)
@@ -55,8 +62,8 @@ class Condenser
55
62
  configure(&block)
56
63
  elsif pipeline != false
57
64
  self.configure do
58
- # register_preprocessor 'application/javascript', Condenser::JSAnalyzer
59
- register_preprocessor 'application/javascript', Condenser::BabelProcessor
65
+ register_preprocessor 'application/javascript', Condenser::JSAnalyzer
66
+ # register_preprocessor 'application/javascript', Condenser::BabelProcessor
60
67
  register_exporter 'application/javascript', Condenser::RollupProcessor
61
68
  register_minifier 'application/javascript', Condenser::UglifyMinifier
62
69
 
@@ -131,6 +138,9 @@ Condenser.configure do
131
138
  # CSS
132
139
  register_mime_type 'text/css', extension: '.css', charset: :css
133
140
 
141
+ # PDF
142
+ register_mime_type 'application/pdf', extensions: %w(.pdf)
143
+
134
144
  # SASS
135
145
  register_mime_type 'text/sass', extensions: %w(.sass .css.sass)
136
146
  # register_transformer 'text/sass', 'text/css', SassProcessor
@@ -144,12 +154,15 @@ Condenser.configure do
144
154
 
145
155
  # EJS
146
156
  register_mime_type 'application/ejs', extensions: '.ejs', charset: :unicode
147
- register_template 'application/ejs', Condenser::EjsTemplare
157
+ register_template 'application/ejs', Condenser::EjsTemplate
148
158
 
149
159
  # JST
150
160
  register_mime_type 'application/jst', extensions: '.jst', charset: :unicode
151
161
  register_transformer 'application/jst', 'application/javascript', Condenser::JstTransformer
152
162
 
163
+ # SVG
164
+ register_transformer 'image/svg+xml', 'application/javascript', Condenser::SVGTransformer
165
+
153
166
  # Writers
154
167
  register_mime_type 'application/gzip', extensions: %w(.gz .gzip)
155
168
  register_mime_type 'application/brotli', extension: %w(.br)
@@ -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
 
data/test/cache_test.rb CHANGED
@@ -142,7 +142,7 @@ class CacheTest < ActiveSupport::TestCase
142
142
 
143
143
  end
144
144
 
145
- test 'a dependency is supurceeded by a new file' do
145
+ test 'a dependency is superceeded by a new file' do
146
146
  Dir.mkdir(File.join(@path, 'a'))
147
147
  Dir.mkdir(File.join(@path, 'b'))
148
148
  @env.clear_path
@@ -221,6 +221,21 @@ class CacheTest < ActiveSupport::TestCase
221
221
  CSS
222
222
  end
223
223
 
224
+ test '2a new dependency for a glob call is reflected in the next call' do
225
+ file "dir/a.svg", "<svg>test</svg>"
226
+ file 'test.scss', 'body { background: image-url("dir/a.svg") }'
227
+
228
+ assert_exported_file 'test.css', 'text/css', <<~CSS
229
+ body{background:url(/assets/dir/a-01a4bd3cb9faa518c5df2d2fcc8e6cd0ba24cfc3e9438dd01455ab1e59a39068.svg)}
230
+ CSS
231
+
232
+ file "dir/a.svg", "<svg>tests</svg>"
233
+
234
+ assert_exported_file 'test.css', 'text/css', <<~CSS
235
+ body{background:url(/assets/dir/a-1d7d038c7ace080963e116cbb962075a38d5e5dc68c6ff688e42d213dd432256.svg)}
236
+ CSS
237
+ end
238
+
224
239
  test 'a dependency is removed for a glob call when one of it dependencies is delted' do
225
240
  file "css/a.scss", "body { color: blue; }"
226
241
  file "css/b.scss", "body { color: green; }"
@@ -237,4 +252,61 @@ class CacheTest < ActiveSupport::TestCase
237
252
  CSS
238
253
  end
239
254
 
255
+ test 'a dependency is added then changed should flush the parent (JS)' do
256
+ file 'a.js', "console.log('a');\n"
257
+ file 'b.js', <<~JS
258
+ export default function b () { console.log('b'); }
259
+ JS
260
+
261
+ assert_exported_file 'a.js', 'application/javascript', <<~JS
262
+ !function(){"use strict";console.log("a")}();
263
+ JS
264
+
265
+ file 'a.js', <<~JS
266
+ import b from 'b';
267
+ console.log('a');
268
+ b();
269
+ JS
270
+
271
+ assert_exported_file 'a.js', 'application/javascript', <<~JS
272
+ !function(){"use strict";console.log("a"),console.log("b")}();
273
+ JS
274
+
275
+ file 'b.js', <<~JS
276
+ export default function b () { console.log('c'); }
277
+ JS
278
+
279
+ assert_exported_file 'a.js', 'application/javascript', <<~JS
280
+ !function(){"use strict";console.log("a"),console.log("c")}();
281
+ JS
282
+ end
283
+
284
+ test 'a dependency is added then changed should flush the parent (CSS)' do
285
+ file 'a.scss', "body { background: aqua; }"
286
+ file 'b.scss', <<~JS
287
+ body { background: blue; }
288
+ JS
289
+
290
+ assert_exported_file 'a.css', 'text/css', <<~JS
291
+ body{background:aqua}
292
+ JS
293
+
294
+ file 'a.scss', <<~JS
295
+ @import "b";
296
+ body { background: aqua; }
297
+ JS
298
+
299
+ assert_exported_file 'a.css', 'text/css', <<~JS
300
+ body{background:blue}body{background:aqua}
301
+ JS
302
+
303
+ file 'b.scss', <<~JS
304
+ body { background: green; }
305
+ JS
306
+
307
+ assert_exported_file 'a.css', 'text/css', <<~JS
308
+ body{background:green}body{background:aqua}
309
+ JS
310
+ end
311
+
240
312
  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), ["models/*.js","helpers/*.js"]
20
+ assert_equal asset.instance_variable_get(:@process_dependencies).to_a, ["models/*.js","helpers/*.js"]
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), ["models/*.js","helpers/*.js"]
57
+ assert_equal asset.instance_variable_get(:@process_dependencies).to_a, ["models/*.js","helpers/*.js"]
58
58
 
59
59
 
60
60
  assert_file 'name.js', 'application/javascript', <<~JS
@@ -66,6 +66,40 @@ class ManifestTest < ActiveSupport::TestCase
66
66
  assert_equal asset.path, data['application.js']['path']
67
67
  end
68
68
 
69
+ test "compile asset dependencies includes the dependencies" do
70
+ file 'foo.svg', <<-SVG
71
+ <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
72
+ <path d="M6 18L18 6M6 6l12 12" />
73
+ </svg>
74
+ SVG
75
+
76
+ file 'test.scss', <<-SCSS
77
+ body {
78
+ background: asset-url("foo.svg");
79
+ }
80
+ SCSS
81
+
82
+ manifest = Condenser::Manifest.new(@env, File.join(@dir, 'manifest.json'))
83
+
84
+ main_digest_path = @env['test.css'].path
85
+ dep_digest_path = @env['foo.svg'].path
86
+
87
+ assert !File.exist?("#{@dir}/#{main_digest_path}")
88
+ assert !File.exist?("#{@dir}/#{dep_digest_path}")
89
+
90
+ manifest.compile('test.css')
91
+ assert File.directory?(manifest.dir)
92
+ assert File.file?(manifest.filename)
93
+
94
+ assert File.exist?("#{@dir}/manifest.json")
95
+ assert File.exist?("#{@dir}/#{main_digest_path}")
96
+ assert File.exist?("#{@dir}/#{dep_digest_path}")
97
+
98
+ data = JSON.parse(File.read(manifest.filename))
99
+ assert_equal main_digest_path, data['test.css']['path']
100
+ assert_equal dep_digest_path, data['foo.svg']['path']
101
+ end
102
+
69
103
  # TODO:
70
104
  # test "compile asset with aliased index links" do
71
105
  # manifest = Sprockets::Manifest.new(@env, File.join(@dir, 'manifest.json'))
@@ -4,7 +4,6 @@ class TerserMinifierTest < ActiveSupport::TestCase
4
4
 
5
5
  def setup
6
6
  super
7
- @env.unregister_preprocessor('application/javascript', Condenser::BabelProcessor)
8
7
  @env.unregister_exporter('application/javascript', Condenser::RollupProcessor)
9
8
  @env.register_minifier('application/javascript', Condenser::TerserMinifier)
10
9
  end
@@ -27,8 +26,8 @@ class TerserMinifierTest < ActiveSupport::TestCase
27
26
  }
28
27
  JS
29
28
 
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]')
29
+ # @env.logger.expects(:warn).with('Dropping unused variable u [test.js:8,6]')
30
+ # @env.logger.expects(:warn).with('Dropping unused variable bl [test.js:10,6]')
32
31
 
33
32
  assert_exported_file 'test.js', 'application/javascript', <<~CSS
34
33
  class MyClass{fn(){console.log("Hello")}}function fa(){return console.log(1),5}
@@ -4,7 +4,6 @@ class UglifyMinifierTest < ActiveSupport::TestCase
4
4
 
5
5
  def setup
6
6
  super
7
- @env.unregister_preprocessor('application/javascript', Condenser::BabelProcessor)
8
7
  @env.unregister_exporter('application/javascript', Condenser::RollupProcessor)
9
8
  end
10
9
 
@@ -0,0 +1,107 @@
1
+ require 'test_helper'
2
+
3
+ class MediaCombinerTest < ActiveSupport::TestCase
4
+
5
+ def setup
6
+ super
7
+ @env.register_postprocessor('text/css', Condenser::CSSMediaCombinerProcessor)
8
+ @env.unregister_minifier('text/css')
9
+ end
10
+
11
+ test 'combine media queries' do
12
+ file 'main.css', <<~CSS
13
+ .test{
14
+ display: block;
15
+ }
16
+ @media only screen and (max-width: 100px) {
17
+ .test {
18
+ display: inline-block;
19
+ color: blue;
20
+ }
21
+ }
22
+ @media only screen and (max-width: 500px) {
23
+ .test {
24
+ display: inline;
25
+ }
26
+ }
27
+
28
+ .test2{
29
+ display: block;
30
+ }
31
+ @media only screen and (max-width: 100px) {
32
+ .test2 {
33
+ display: inline-block;
34
+ }
35
+ }
36
+ CSS
37
+
38
+ assert_exported_file 'main.css', 'text/css', <<~FILE
39
+ .test{
40
+ display: block;
41
+ }
42
+
43
+
44
+
45
+ .test2{
46
+ display: block;
47
+ }
48
+ @media only screen and (max-width: 100px) {
49
+ .test {
50
+ display: inline-block;
51
+ color: blue;
52
+ }
53
+
54
+ .test2 {
55
+ display: inline-block;
56
+ }
57
+ }@media only screen and (max-width: 500px) {
58
+ .test {
59
+ display: inline;
60
+ }
61
+ }
62
+ FILE
63
+ end
64
+
65
+ test 'single line css' do
66
+ file 'main.css', <<~CSS
67
+ .test{display: block;} @media only screen and (max-width: 100px) {.test {display: inline-block;}}@media only screen and (max-width: 500px) {.test {display: inline;}}.test2{display: block;}@media only screen and (max-width: 100px) {.test2 {display: inline-block;}}
68
+ CSS
69
+
70
+ assert_exported_file 'main.css', 'text/css', <<~FILE
71
+ .test{display: block;} .test2{display: block;}@media only screen and (max-width: 100px) {.test {display: inline-block;}.test2 {display: inline-block;}}@media only screen and (max-width: 500px) {.test {display: inline;}}
72
+ FILE
73
+ end
74
+
75
+
76
+ test 'keyframes' do
77
+ file 'main.css', <<~CSS
78
+ .trobber {
79
+ animation: throb 1s infinite;
80
+ }
81
+ @keyframes throb {
82
+ 0% {
83
+ opacity: 1;
84
+ }
85
+ 100%{
86
+ opacity: 0;
87
+ }
88
+ }
89
+ CSS
90
+
91
+ assert_exported_file 'main.css', 'text/css', <<~FILE
92
+ .trobber {
93
+ animation: throb 1s infinite;
94
+ }
95
+ @keyframes throb {
96
+ 0% {
97
+ opacity: 1;
98
+ }
99
+ 100%{
100
+ opacity: 0;
101
+ }
102
+ }
103
+ FILE
104
+ end
105
+
106
+
107
+ end
@@ -0,0 +1,145 @@
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
+ test 'purge from html with class with /' do
84
+ file 'main.css', <<~CSS
85
+ .test{
86
+ display: block;
87
+ }
88
+ .test2-1\\/2{
89
+ display: inline;
90
+ }
91
+ CSS
92
+ file 'index.html', <<~HTML
93
+ <div class="test2-1/2"></div>
94
+ HTML
95
+
96
+ assert_exported_file 'main.css', 'text/css', <<~FILE
97
+ .test2-1\\/2{
98
+ display: inline;
99
+ }
100
+ FILE
101
+ end
102
+
103
+ test 'purge from html with nested tag' do
104
+ file 'main.css', <<~CSS
105
+ .test pre{
106
+ display: block;
107
+ }
108
+ CSS
109
+ file 'index.html', <<~HTML
110
+ <div class="test">
111
+ <pre>Test</pre>
112
+ </div>
113
+ HTML
114
+
115
+ assert_exported_file 'main.css', 'text/css', <<~FILE
116
+ .test pre{
117
+ display: block;
118
+ }
119
+ FILE
120
+ end
121
+
122
+ test 'purge from html with nested tags' do
123
+ file 'main.css', <<~CSS
124
+ code {
125
+ background: gray;
126
+ }
127
+ pre code{
128
+ background: none;
129
+ }
130
+ CSS
131
+ file 'index.html', <<~HTML
132
+ <pre><code>Test</code></pre>
133
+ HTML
134
+
135
+ assert_exported_file 'main.css', 'text/css', <<~FILE
136
+ code {
137
+ background: gray;
138
+ }
139
+ pre code{
140
+ background: none;
141
+ }
142
+ FILE
143
+ end
144
+
145
+ end