condenser 1.2 → 1.4
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/asset.rb +69 -35
- data/lib/condenser/build_cache.rb +22 -9
- data/lib/condenser/context.rb +9 -25
- data/lib/condenser/helpers/parse_helpers.rb +8 -1
- data/lib/condenser/manifest.rb +3 -1
- data/lib/condenser/pipeline.rb +8 -3
- data/lib/condenser/processors/babel_processor.rb +9 -15
- data/lib/condenser/processors/css_media_combiner_processor.rb +81 -0
- data/lib/condenser/processors/js_analyzer.rb +41 -8
- data/lib/condenser/processors/node_processor.rb +1 -0
- data/lib/condenser/processors/purgecss_processor.rb +6 -4
- data/lib/condenser/processors/rollup_processor.rb +38 -36
- data/lib/condenser/resolve.rb +27 -6
- data/lib/condenser/templating_engine/ejs.rb +1 -1
- data/lib/condenser/transformers/dart_sass_transformer.rb +285 -0
- data/lib/condenser/transformers/jst_transformer.rb +67 -17
- data/lib/condenser/transformers/sass/functions.rb +133 -0
- data/lib/condenser/transformers/sass/importer.rb +48 -0
- data/lib/condenser/transformers/sass.rb +4 -0
- data/lib/condenser/transformers/sass_transformer.rb +124 -281
- data/lib/condenser/transformers/svg_transformer/base.rb +26 -0
- data/lib/condenser/transformers/svg_transformer/tag.rb +54 -0
- data/lib/condenser/transformers/svg_transformer/template.rb +151 -0
- data/lib/condenser/transformers/svg_transformer/template_error.rb +2 -0
- data/lib/condenser/transformers/svg_transformer/value.rb +13 -0
- data/lib/condenser/transformers/svg_transformer/var_generator.rb +10 -0
- data/lib/condenser/transformers/svg_transformer.rb +19 -0
- data/lib/condenser/version.rb +1 -1
- data/lib/condenser.rb +17 -5
- data/test/cache_test.rb +157 -18
- data/test/dependency_test.rb +51 -2
- data/test/manifest_test.rb +34 -0
- data/test/minifiers/terser_minifier_test.rb +0 -1
- data/test/minifiers/uglify_minifier_test.rb +0 -1
- data/test/postprocessors/css_media_combiner_test.rb +107 -0
- data/test/postprocessors/purgecss_test.rb +62 -0
- data/test/preprocessor/babel_test.rb +703 -298
- data/test/preprocessor/js_analyzer_test.rb +35 -2
- data/test/processors/rollup_test.rb +50 -20
- data/test/resolve_test.rb +18 -9
- data/test/server_test.rb +15 -10
- data/test/templates/ejs_test.rb +2 -11
- data/test/templates/erb_test.rb +0 -5
- data/test/test_helper.rb +8 -3
- data/test/transformers/dart_scss_test.rb +139 -0
- data/test/transformers/jst_test.rb +165 -21
- data/test/transformers/scss_test.rb +14 -0
- data/test/transformers/svg_test.rb +40 -0
- metadata +23 -6
- data/lib/condenser/transformers/sass_transformer/importer.rb +0 -50
@@ -0,0 +1,151 @@
|
|
1
|
+
class Condenser::SVGTransformer::Template
|
2
|
+
|
3
|
+
include Condenser::ParseHelpers
|
4
|
+
|
5
|
+
attr_accessor :source
|
6
|
+
|
7
|
+
START_TAGS = ['<']
|
8
|
+
CLOSE_TAGS = ['/>', '>']
|
9
|
+
VOID_ELEMENTS = ['!DOCTYPE', '?xml']
|
10
|
+
|
11
|
+
def initialize(source)
|
12
|
+
@source = source.strip
|
13
|
+
process
|
14
|
+
end
|
15
|
+
|
16
|
+
def process
|
17
|
+
seek(0)
|
18
|
+
@tree = [Condenser::SVGTransformer::Base.new]
|
19
|
+
@stack = [:str]
|
20
|
+
|
21
|
+
while !eos?
|
22
|
+
case @stack.last
|
23
|
+
when :str
|
24
|
+
scan_until(Regexp.new("(#{START_TAGS.map{|s| Regexp.escape(s) }.join('|')}|\\z)"))
|
25
|
+
if !matched.nil? && START_TAGS.include?(matched)
|
26
|
+
@stack << :tag
|
27
|
+
end
|
28
|
+
when :tag
|
29
|
+
scan_until(Regexp.new("(\\/|[^\\s>]+)"))
|
30
|
+
if matched == '/'
|
31
|
+
@stack.pop
|
32
|
+
@stack << :close_tag
|
33
|
+
else
|
34
|
+
@tree << Condenser::SVGTransformer::Tag.new(matched)
|
35
|
+
@stack << :tag_attr_key
|
36
|
+
end
|
37
|
+
when :close_tag
|
38
|
+
scan_until(Regexp.new("([^\\s>]+)"))
|
39
|
+
|
40
|
+
el = @tree.pop
|
41
|
+
if el.tag_name != matched
|
42
|
+
raise Condenser::SVGTransformer::TemplateError.new("Expected to close #{el.tag_name.inspect} tag, instead closed #{matched.inspect}\n#{cursor}")
|
43
|
+
end
|
44
|
+
if !['!DOCTYPE', '?xml'].include?(el.tag_name)
|
45
|
+
@tree.last.children << el
|
46
|
+
scan_until(Regexp.new("(#{CLOSE_TAGS.map{|s| Regexp.escape(s) }.join('|')})"))
|
47
|
+
@stack.pop
|
48
|
+
end
|
49
|
+
when :tag_attr_key
|
50
|
+
scan_until(Regexp.new("(#{CLOSE_TAGS.map{|s| Regexp.escape(s) }.join('|')}|[^\\s=>]+)"))
|
51
|
+
if CLOSE_TAGS.include?(matched)
|
52
|
+
if matched == '/>' || VOID_ELEMENTS.include?(@tree.last.tag_name)
|
53
|
+
el = @tree.pop
|
54
|
+
@tree.last.children << el
|
55
|
+
@stack.pop
|
56
|
+
@stack.pop
|
57
|
+
else
|
58
|
+
@stack << :str
|
59
|
+
end
|
60
|
+
else
|
61
|
+
key = if matched.start_with?('"') && matched.end_with?('"')
|
62
|
+
matched[1..-2]
|
63
|
+
elsif matched.start_with?('"') && matched.end_with?('"')
|
64
|
+
matched[1..-2]
|
65
|
+
else
|
66
|
+
matched
|
67
|
+
end
|
68
|
+
@tree.last.attrs << key
|
69
|
+
@stack << :tag_attr_value_tx
|
70
|
+
end
|
71
|
+
when :tag_attr_value_tx
|
72
|
+
scan_until(Regexp.new("(#{(CLOSE_TAGS).map{|s| Regexp.escape(s) }.join('|')}|=|\\S)"))
|
73
|
+
tag_key = @tree.last.attrs.pop
|
74
|
+
if CLOSE_TAGS.include?(matched)
|
75
|
+
el = @tree.last
|
76
|
+
el.attrs << tag_key
|
77
|
+
if VOID_ELEMENTS.include?(el.tag_name)
|
78
|
+
@tree.pop
|
79
|
+
@tree.last.children << el
|
80
|
+
end
|
81
|
+
@stack.pop
|
82
|
+
@stack.pop
|
83
|
+
@stack.pop
|
84
|
+
elsif matched == '='
|
85
|
+
@stack.pop
|
86
|
+
@tree.last.attrs << tag_key
|
87
|
+
@stack << :tag_attr_value
|
88
|
+
else
|
89
|
+
@stack.pop
|
90
|
+
@tree.last.attrs << tag_key
|
91
|
+
rewind(1)
|
92
|
+
end
|
93
|
+
|
94
|
+
when :tag_attr_value
|
95
|
+
scan_until(Regexp.new("(#{CLOSE_TAGS.map{|s| Regexp.escape(s) }.join('|')}|'|\"|\\S+)"))
|
96
|
+
|
97
|
+
if matched == '"'
|
98
|
+
@stack.pop
|
99
|
+
@stack << :tag_attr_value_double_quoted
|
100
|
+
elsif matched == "'"
|
101
|
+
@stack.pop
|
102
|
+
@stack << :tag_attr_value_single_quoted
|
103
|
+
else
|
104
|
+
@stack.pop
|
105
|
+
key = @tree.last.attrs.pop
|
106
|
+
@tree.last.namespace = matched if key == 'xmlns'
|
107
|
+
@tree.last.attrs << { key => matched }
|
108
|
+
end
|
109
|
+
when :tag_attr_value_double_quoted
|
110
|
+
quoted_value = ''
|
111
|
+
scan_until(/"/)
|
112
|
+
quoted_value << pre_match if !pre_match.strip.empty?
|
113
|
+
rewind(1)
|
114
|
+
|
115
|
+
quoted_value = Condenser::SVGTransformer::Value.new(quoted_value)
|
116
|
+
|
117
|
+
key = @tree.last.attrs.pop
|
118
|
+
@tree.last.namespace = quoted_value if key == 'xmlns'
|
119
|
+
if @tree.last.attrs.last.is_a?(Hash) && !@tree.last.attrs.last.has_key?(key)
|
120
|
+
@tree.last.attrs.last[key] = quoted_value
|
121
|
+
else
|
122
|
+
@tree.last.attrs << { key => quoted_value }
|
123
|
+
end
|
124
|
+
scan_until(/\"/)
|
125
|
+
@stack.pop
|
126
|
+
when :tag_attr_value_single_quoted
|
127
|
+
quoted_value = ''
|
128
|
+
scan_until(/(')/)
|
129
|
+
quoted_value << pre_match if !pre_match.strip.empty?
|
130
|
+
rewind(1)
|
131
|
+
|
132
|
+
quoted_value = Condenser::SVGTransformer::Value.new(quoted_value)
|
133
|
+
|
134
|
+
key = @tree.last.attrs.pop
|
135
|
+
@tree.last.namespace = quoted_value if key == 'xmlns'
|
136
|
+
if @tree.last.attrs.last.is_a?(Hash) && !@tree.last.attrs.last.has_key?(key)
|
137
|
+
@tree.last.attrs.last[key] = quoted_value
|
138
|
+
else
|
139
|
+
@tree.last.attrs << { key => quoted_value }
|
140
|
+
end
|
141
|
+
scan_until(/\'/)
|
142
|
+
@stack.pop
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
def to_module
|
148
|
+
@tree.first.to_module
|
149
|
+
end
|
150
|
+
|
151
|
+
end
|
@@ -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
|
+
|
data/lib/condenser/version.rb
CHANGED
data/lib/condenser.rb
CHANGED
@@ -19,19 +19,25 @@ class Condenser
|
|
19
19
|
autoload :RollupProcessor, 'condenser/processors/rollup_processor'
|
20
20
|
autoload :JSAnalyzer, 'condenser/processors/js_analyzer'
|
21
21
|
autoload :PurgeCSSProcessor,'condenser/processors/purgecss_processor'
|
22
|
+
autoload :CSSMediaCombinerProcessor,'condenser/processors/css_media_combiner_processor'
|
22
23
|
autoload :NodeProcessor, 'condenser/processors/node_processor'
|
23
24
|
autoload :UglifyMinifier, 'condenser/minifiers/uglify_minifier'
|
24
25
|
autoload :TerserMinifier, 'condenser/minifiers/terser_minifier'
|
25
26
|
autoload :Erubi, 'condenser/templating_engine/erb'
|
27
|
+
autoload :Sass, 'condenser/transformers/sass'
|
26
28
|
autoload :SassMinifier, 'condenser/minifiers/sass_minifier'
|
27
|
-
autoload :
|
29
|
+
autoload :DartSassTransformer, 'condenser/transformers/dart_sass_transformer'
|
30
|
+
autoload :DartScssTransformer, 'condenser/transformers/dart_sass_transformer'
|
31
|
+
autoload :SassTransformer, 'condenser/transformers/sass_transformer'
|
28
32
|
autoload :ScssTransformer, 'condenser/transformers/sass_transformer'
|
29
|
-
autoload :
|
33
|
+
autoload :EjsTemplate, 'condenser/templating_engine/ejs'
|
30
34
|
autoload :JstTransformer, 'condenser/transformers/jst_transformer'
|
35
|
+
autoload :SVGTransformer, 'condenser/transformers/svg_transformer'
|
31
36
|
autoload :FileWriter, 'condenser/writers/file_writer'
|
32
37
|
autoload :ZlibWriter, 'condenser/writers/zlib_writer'
|
33
38
|
autoload :BrotliWriter, 'condenser/writers/brotli_writer'
|
34
39
|
autoload :BuildCache, 'condenser/build_cache'
|
40
|
+
autoload :ParseHelpers, 'condenser/helpers/parse_helpers'
|
35
41
|
|
36
42
|
def self.configure(&block)
|
37
43
|
instance_eval(&block)
|
@@ -56,8 +62,8 @@ class Condenser
|
|
56
62
|
configure(&block)
|
57
63
|
elsif pipeline != false
|
58
64
|
self.configure do
|
59
|
-
|
60
|
-
register_preprocessor 'application/javascript', Condenser::BabelProcessor
|
65
|
+
register_preprocessor 'application/javascript', Condenser::JSAnalyzer
|
66
|
+
# register_preprocessor 'application/javascript', Condenser::BabelProcessor
|
61
67
|
register_exporter 'application/javascript', Condenser::RollupProcessor
|
62
68
|
register_minifier 'application/javascript', Condenser::UglifyMinifier
|
63
69
|
|
@@ -132,6 +138,9 @@ Condenser.configure do
|
|
132
138
|
# CSS
|
133
139
|
register_mime_type 'text/css', extension: '.css', charset: :css
|
134
140
|
|
141
|
+
# PDF
|
142
|
+
register_mime_type 'application/pdf', extensions: %w(.pdf)
|
143
|
+
|
135
144
|
# SASS
|
136
145
|
register_mime_type 'text/sass', extensions: %w(.sass .css.sass)
|
137
146
|
# register_transformer 'text/sass', 'text/css', SassProcessor
|
@@ -145,12 +154,15 @@ Condenser.configure do
|
|
145
154
|
|
146
155
|
# EJS
|
147
156
|
register_mime_type 'application/ejs', extensions: '.ejs', charset: :unicode
|
148
|
-
register_template 'application/ejs', Condenser::
|
157
|
+
register_template 'application/ejs', Condenser::EjsTemplate
|
149
158
|
|
150
159
|
# JST
|
151
160
|
register_mime_type 'application/jst', extensions: '.jst', charset: :unicode
|
152
161
|
register_transformer 'application/jst', 'application/javascript', Condenser::JstTransformer
|
153
162
|
|
163
|
+
# SVG
|
164
|
+
register_transformer 'image/svg+xml', 'application/javascript', Condenser::SVGTransformer
|
165
|
+
|
154
166
|
# Writers
|
155
167
|
register_mime_type 'application/gzip', extensions: %w(.gz .gzip)
|
156
168
|
register_mime_type 'application/brotli', extension: %w(.br)
|
data/test/cache_test.rb
CHANGED
@@ -60,6 +60,19 @@ class CacheTest < ActiveSupport::TestCase
|
|
60
60
|
CSS
|
61
61
|
end
|
62
62
|
|
63
|
+
test 'changing a source file on calls needs_reprocessing! and needs_reexporting! once' do
|
64
|
+
file 'test.txt.erb', "1<%= 1 + 1 %>3\n"
|
65
|
+
assert_file 'test.txt', 'text/plain', <<~CSS
|
66
|
+
123
|
67
|
+
CSS
|
68
|
+
|
69
|
+
asset = @env.find('test.txt')
|
70
|
+
|
71
|
+
asset.expects(:needs_reprocessing!).once
|
72
|
+
asset.expects(:needs_reexporting!).once
|
73
|
+
file 'test.txt.erb', "1<%= 1 + 2 %>5\n"
|
74
|
+
end
|
75
|
+
|
63
76
|
test 'changing a js dependency reflects in the next call' do
|
64
77
|
file 'main.js', <<-JS
|
65
78
|
import { cube } from 'math';
|
@@ -74,11 +87,11 @@ class CacheTest < ActiveSupport::TestCase
|
|
74
87
|
JS
|
75
88
|
|
76
89
|
assert_exported_file 'main.js', 'application/javascript', <<~CSS
|
77
|
-
!function(){
|
90
|
+
!function(){var o;console.log((o=5)*o)}();
|
78
91
|
CSS
|
79
92
|
|
80
93
|
assert_exported_file 'main.js', 'application/javascript', <<~CSS
|
81
|
-
!function(){
|
94
|
+
!function(){var o;console.log((o=5)*o)}();
|
82
95
|
CSS
|
83
96
|
|
84
97
|
file 'math.js', <<-JS
|
@@ -88,7 +101,7 @@ class CacheTest < ActiveSupport::TestCase
|
|
88
101
|
JS
|
89
102
|
|
90
103
|
assert_exported_file 'main.js', 'application/javascript', <<~CSS
|
91
|
-
!function(){
|
104
|
+
!function(){var o;console.log((o=5)*o*o)}();
|
92
105
|
CSS
|
93
106
|
end
|
94
107
|
|
@@ -123,10 +136,10 @@ class CacheTest < ActiveSupport::TestCase
|
|
123
136
|
JS
|
124
137
|
|
125
138
|
assert_exported_file 'a.js', 'application/javascript', <<~JS
|
126
|
-
|
139
|
+
console.log(5);
|
127
140
|
JS
|
128
141
|
assert_exported_file 'b.js', 'application/javascript', <<~JS
|
129
|
-
|
142
|
+
console.log(5);
|
130
143
|
JS
|
131
144
|
|
132
145
|
file 'dep.js', <<-JS
|
@@ -134,15 +147,14 @@ class CacheTest < ActiveSupport::TestCase
|
|
134
147
|
JS
|
135
148
|
|
136
149
|
assert_exported_file 'a.js', 'application/javascript', <<~JS
|
137
|
-
|
150
|
+
console.log(10);
|
138
151
|
JS
|
139
152
|
assert_exported_file 'b.js', 'application/javascript', <<~JS
|
140
|
-
|
153
|
+
console.log(10);
|
141
154
|
JS
|
142
|
-
|
143
155
|
end
|
144
156
|
|
145
|
-
test 'a dependency is
|
157
|
+
test 'a dependency is superceeded by a new file' do
|
146
158
|
Dir.mkdir(File.join(@path, 'a'))
|
147
159
|
Dir.mkdir(File.join(@path, 'b'))
|
148
160
|
@env.clear_path
|
@@ -158,7 +170,7 @@ class CacheTest < ActiveSupport::TestCase
|
|
158
170
|
JS
|
159
171
|
|
160
172
|
assert_exported_file 'a.js', 'application/javascript', <<~JS
|
161
|
-
|
173
|
+
console.log(5);
|
162
174
|
JS
|
163
175
|
|
164
176
|
file 'a/dep.js', <<-JS
|
@@ -166,7 +178,7 @@ class CacheTest < ActiveSupport::TestCase
|
|
166
178
|
JS
|
167
179
|
|
168
180
|
assert_exported_file 'a.js', 'application/javascript', <<~JS
|
169
|
-
|
181
|
+
console.log(10);
|
170
182
|
JS
|
171
183
|
end
|
172
184
|
|
@@ -186,7 +198,7 @@ class CacheTest < ActiveSupport::TestCase
|
|
186
198
|
JS
|
187
199
|
|
188
200
|
assert_exported_file 'a.js', 'application/javascript', <<~JS
|
189
|
-
|
201
|
+
console.log(5);
|
190
202
|
JS
|
191
203
|
|
192
204
|
file 'a/deps/dep.js', <<-JS
|
@@ -194,7 +206,7 @@ class CacheTest < ActiveSupport::TestCase
|
|
194
206
|
JS
|
195
207
|
|
196
208
|
assert_exported_file 'a.js', 'application/javascript', <<~JS
|
197
|
-
|
209
|
+
console.log(10);
|
198
210
|
JS
|
199
211
|
|
200
212
|
file 'a/deps/dep.js', <<-JS
|
@@ -202,7 +214,7 @@ class CacheTest < ActiveSupport::TestCase
|
|
202
214
|
JS
|
203
215
|
|
204
216
|
assert_exported_file 'a.js', 'application/javascript', <<~JS
|
205
|
-
|
217
|
+
console.log(20);
|
206
218
|
JS
|
207
219
|
end
|
208
220
|
|
@@ -221,6 +233,21 @@ class CacheTest < ActiveSupport::TestCase
|
|
221
233
|
CSS
|
222
234
|
end
|
223
235
|
|
236
|
+
test '2a new dependency for a glob call is reflected in the next call' do
|
237
|
+
file "dir/a.svg", "<svg>test</svg>"
|
238
|
+
file 'test.scss', 'body { background: image-url("dir/a.svg") }'
|
239
|
+
|
240
|
+
assert_exported_file 'test.css', 'text/css', <<~CSS
|
241
|
+
body{background:url(/assets/dir/a-01a4bd3cb9faa518c5df2d2fcc8e6cd0ba24cfc3e9438dd01455ab1e59a39068.svg)}
|
242
|
+
CSS
|
243
|
+
|
244
|
+
file "dir/a.svg", "<svg>tests</svg>"
|
245
|
+
|
246
|
+
assert_exported_file 'test.css', 'text/css', <<~CSS
|
247
|
+
body{background:url(/assets/dir/a-1d7d038c7ace080963e116cbb962075a38d5e5dc68c6ff688e42d213dd432256.svg)}
|
248
|
+
CSS
|
249
|
+
end
|
250
|
+
|
224
251
|
test 'a dependency is removed for a glob call when one of it dependencies is delted' do
|
225
252
|
file "css/a.scss", "body { color: blue; }"
|
226
253
|
file "css/b.scss", "body { color: green; }"
|
@@ -237,14 +264,14 @@ class CacheTest < ActiveSupport::TestCase
|
|
237
264
|
CSS
|
238
265
|
end
|
239
266
|
|
240
|
-
test 'a dependency is added then changed should flush the parent' do
|
267
|
+
test 'a dependency is added then changed should flush the parent (JS)' do
|
241
268
|
file 'a.js', "console.log('a');\n"
|
242
269
|
file 'b.js', <<~JS
|
243
270
|
export default function b () { console.log('b'); }
|
244
271
|
JS
|
245
272
|
|
246
273
|
assert_exported_file 'a.js', 'application/javascript', <<~JS
|
247
|
-
|
274
|
+
console.log("a");
|
248
275
|
JS
|
249
276
|
|
250
277
|
file 'a.js', <<~JS
|
@@ -254,7 +281,7 @@ class CacheTest < ActiveSupport::TestCase
|
|
254
281
|
JS
|
255
282
|
|
256
283
|
assert_exported_file 'a.js', 'application/javascript', <<~JS
|
257
|
-
|
284
|
+
console.log("a"),console.log("b");
|
258
285
|
JS
|
259
286
|
|
260
287
|
file 'b.js', <<~JS
|
@@ -262,7 +289,119 @@ class CacheTest < ActiveSupport::TestCase
|
|
262
289
|
JS
|
263
290
|
|
264
291
|
assert_exported_file 'a.js', 'application/javascript', <<~JS
|
265
|
-
|
292
|
+
console.log("a"),console.log("c");
|
266
293
|
JS
|
267
294
|
end
|
295
|
+
|
296
|
+
test 'a dependency is added then changed should flush the parent (CSS)' do
|
297
|
+
file 'a.scss', "body { background: aqua; }"
|
298
|
+
file 'b.scss', <<~JS
|
299
|
+
body { background: blue; }
|
300
|
+
JS
|
301
|
+
|
302
|
+
assert_exported_file 'a.css', 'text/css', <<~JS
|
303
|
+
body{background:aqua}
|
304
|
+
JS
|
305
|
+
|
306
|
+
file 'a.scss', <<~JS
|
307
|
+
@import "b";
|
308
|
+
body { background: aqua; }
|
309
|
+
JS
|
310
|
+
|
311
|
+
assert_exported_file 'a.css', 'text/css', <<~JS
|
312
|
+
body{background:blue}body{background:aqua}
|
313
|
+
JS
|
314
|
+
|
315
|
+
file 'b.scss', <<~JS
|
316
|
+
body { background: green; }
|
317
|
+
JS
|
318
|
+
|
319
|
+
assert_exported_file 'a.css', 'text/css', <<~JS
|
320
|
+
body{background:green}body{background:aqua}
|
321
|
+
JS
|
322
|
+
end
|
323
|
+
|
324
|
+
test 'ensure the build cache only walks the dependency tree once' do
|
325
|
+
# a
|
326
|
+
# | |
|
327
|
+
# b c
|
328
|
+
# |
|
329
|
+
# d
|
330
|
+
|
331
|
+
file 'd.js', "export default function d () { console.log('d'); }\n"
|
332
|
+
file 'b.js', "export default function b () { console.log('b'); }\n"
|
333
|
+
file 'c.js', <<~JS
|
334
|
+
import d from 'd';
|
335
|
+
|
336
|
+
export default function c () { console.log('c'); d(); }
|
337
|
+
JS
|
338
|
+
file 'a.js', <<~JS
|
339
|
+
import b from 'b';
|
340
|
+
import c from 'c';
|
341
|
+
|
342
|
+
console.log('a'); b(); c();
|
343
|
+
JS
|
344
|
+
|
345
|
+
assert_exported_file 'a.js', 'application/javascript', <<~JS
|
346
|
+
console.log("a"),console.log("b"),console.log("c"),console.log("d");
|
347
|
+
JS
|
348
|
+
|
349
|
+
file 'd.js', "export default function e () { console.log('e'); }\n"
|
350
|
+
|
351
|
+
pd = @env.build_cache.instance_variable_get(:@process_dependencies)
|
352
|
+
pd["#{@path}/a.js"] ||= Set.new
|
353
|
+
pd["#{@path}/b.js"] ||= Set.new
|
354
|
+
pd["#{@path}/c.js"] ||= Set.new
|
355
|
+
pd["#{@path}/d.js"] ||= Set.new
|
356
|
+
pd["#{@path}/a.js"].expects(:<<).with { |a| a.source_file == "#{@path}/a.js" }.once
|
357
|
+
pd["#{@path}/b.js"].expects(:<<).with { |a| a.source_file == "#{@path}/b.js" }.never
|
358
|
+
pd["#{@path}/c.js"].expects(:<<).with { |a| a.source_file == "#{@path}/c.js" }.never
|
359
|
+
pd["#{@path}/d.js"].expects(:<<).with { |a| a.source_file == "#{@path}/d.js" }.once
|
360
|
+
|
361
|
+
assert_exported_file 'a.js', 'application/javascript', <<~JS
|
362
|
+
console.log("a"),console.log("b"),console.log("c"),console.log("e");
|
363
|
+
JS
|
364
|
+
end
|
365
|
+
|
366
|
+
test 'same files in diffrent dirs sharing a cache doesnt poison the cache (ie capistrano deploys)' do
|
367
|
+
cachepath = Dir.mktmpdir
|
368
|
+
|
369
|
+
dir = File.realpath(Dir.mktmpdir)
|
370
|
+
base1 = File.join(dir, 'a')
|
371
|
+
base2 = File.join(dir, 'b')
|
372
|
+
base3 = File.join(dir, 'c')
|
373
|
+
Dir.mkdir(base1)
|
374
|
+
Dir.mkdir(base2)
|
375
|
+
|
376
|
+
[base1, base2, base3].each do |b|
|
377
|
+
file 'test.js', "export default function c () { console.log('t'); }\n", base: b
|
378
|
+
file 'test/b.js', <<~JS, base: b
|
379
|
+
import c from './c';
|
380
|
+
export default function b () { console.log('b'); c(); }
|
381
|
+
JS
|
382
|
+
file 'test/a.js', <<~JS, base: b
|
383
|
+
import t from 'test';
|
384
|
+
import b from './b';
|
385
|
+
|
386
|
+
console.log('a');
|
387
|
+
b();
|
388
|
+
JS
|
389
|
+
end
|
390
|
+
|
391
|
+
file 'test/c.js', "export default function c () { console.log('c'); }\n", base: base1
|
392
|
+
file 'test/c.js', "export default function c () { console.log('d'); }\n", base: base2
|
393
|
+
file 'test/c.js', "export default function c () { console.log('e'); }\n", base: base3
|
394
|
+
|
395
|
+
# Set the cache
|
396
|
+
env1 = Condenser.new(base1, logger: Logger.new(STDOUT, level: :debug), base: base1, npm_path: @npm_dir, cache: Condenser::Cache::FileStore.new(cachepath))
|
397
|
+
assert_equal 'console.log("a"),console.log("b"),console.log("c");', env1.find('test/a.js').export.source
|
398
|
+
|
399
|
+
# Poison the cache
|
400
|
+
env2 = Condenser.new(base2, logger: Logger.new(STDOUT, level: :debug), base: base2, npm_path: @npm_dir, cache: Condenser::Cache::FileStore.new(cachepath))
|
401
|
+
assert_equal 'console.log("a"),console.log("b"),console.log("d");', env2.find('test/a.js').export.source
|
402
|
+
|
403
|
+
# Fails to find dependency change because cache is missing the dependency
|
404
|
+
env3 = Condenser.new(base3, logger: Logger.new(STDOUT, level: :debug), base: base3, npm_path: @npm_dir, cache: Condenser::Cache::FileStore.new(cachepath))
|
405
|
+
assert_equal 'console.log("a"),console.log("b"),console.log("e");', env3.find('test/a.js').export.source
|
406
|
+
end
|
268
407
|
end
|
data/test/dependency_test.rb
CHANGED
@@ -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
|
20
|
+
assert_equal asset.instance_variable_get(:@process_dependencies).to_a, [["models/*", ["application/javascript"]],["helpers/*", ["application/javascript"]]]
|
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
|
57
|
+
assert_equal asset.instance_variable_get(:@process_dependencies).to_a, [["models/*", ["application/javascript"]],["helpers/*", ["application/javascript"]]]
|
58
58
|
|
59
59
|
|
60
60
|
assert_file 'name.js', 'application/javascript', <<~JS
|
@@ -74,4 +74,53 @@ class DependencyTest < ActiveSupport::TestCase
|
|
74
74
|
JS
|
75
75
|
end
|
76
76
|
|
77
|
+
test 'js depending on another file type with JSAnalzyer' do
|
78
|
+
@env.unregister_preprocessor 'application/javascript', Condenser::BabelProcessor
|
79
|
+
@env.register_preprocessor 'application/javascript', Condenser::JSAnalyzer
|
80
|
+
@env.unregister_minifier('application/javascript')
|
81
|
+
|
82
|
+
file 'a.js', ''
|
83
|
+
file 'b.rb', ''
|
84
|
+
file 'models/a.js', ''
|
85
|
+
file 'models/b.rb', ''
|
86
|
+
|
87
|
+
file 'name.js.erb', <<~JS
|
88
|
+
// depends_on **/*.rb
|
89
|
+
|
90
|
+
console.log([<%= Dir.children("#{@path}").sort.map(&:inspect).join(', ') %>]);
|
91
|
+
JS
|
92
|
+
|
93
|
+
asset = @env.find('name.js')
|
94
|
+
assert_equal asset.instance_variable_get(:@process_dependencies).to_a, [["**/*", ["application/ruby"]]]
|
95
|
+
assert_equal asset.process_dependencies.map(&:source_file), ["#{@path}/b.rb", "#{@path}/models/b.rb"]
|
96
|
+
end
|
97
|
+
|
98
|
+
test 'relative imports with JSAnalzyer' do
|
99
|
+
@env.unregister_preprocessor 'application/javascript', Condenser::BabelProcessor
|
100
|
+
@env.register_preprocessor 'application/javascript', Condenser::JSAnalyzer
|
101
|
+
@env.unregister_minifier('application/javascript')
|
102
|
+
|
103
|
+
file 'a/a.js', <<~JS
|
104
|
+
export decault function () { console.log("a/a"); }
|
105
|
+
JS
|
106
|
+
file 'b/a.js', <<~JS
|
107
|
+
export decault function () { console.log("a/a"); }
|
108
|
+
JS
|
109
|
+
|
110
|
+
file 'a/b.js', <<~JS
|
111
|
+
import fn from './a';
|
112
|
+
a();
|
113
|
+
console.log("a/b");
|
114
|
+
JS
|
115
|
+
file 'b/b.js', <<~JS
|
116
|
+
import fn from './a';
|
117
|
+
a();
|
118
|
+
console.log("b/b");
|
119
|
+
JS
|
120
|
+
|
121
|
+
asset = @env.find('a/b.js')
|
122
|
+
assert_equal asset.instance_variable_get(:@export_dependencies).to_a, [["#{@path}/a/a", ["application/javascript"]]]
|
123
|
+
assert_equal asset.export_dependencies.map(&:source_file), ["#{@path}/a/a.js"]
|
124
|
+
end
|
125
|
+
|
77
126
|
end
|
data/test/manifest_test.rb
CHANGED
@@ -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
|