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
@@ -7,7 +7,7 @@ class Condenser::RollupProcessor < Condenser::NodeProcessor
|
|
7
7
|
|
8
8
|
def initialize(dir = nil, options = {})
|
9
9
|
super(dir)
|
10
|
-
npm_install('rollup', 'rollup
|
10
|
+
npm_install('rollup', '@rollup/plugin-commonjs', '@rollup/plugin-node-resolve')
|
11
11
|
|
12
12
|
@options = options.freeze
|
13
13
|
end
|
@@ -50,7 +50,12 @@ class Condenser::RollupProcessor < Condenser::NodeProcessor
|
|
50
50
|
return '';
|
51
51
|
} catch(e) {
|
52
52
|
if (e.name === "SyntaxError") {
|
53
|
-
if (e.message.startsWith('Unexpected
|
53
|
+
if (e.message.startsWith('Unexpected non-whitespace character after JSON at position ')) {
|
54
|
+
var pos = parseInt(e.message.slice(59));
|
55
|
+
emitMessages(buffer.slice(0,pos));
|
56
|
+
return emitMessages(buffer.slice(pos));
|
57
|
+
} else if (e.message.startsWith('Unexpected token { in JSON at position ')) {
|
58
|
+
// This can be removed, once dropping support for node <= v18
|
54
59
|
var pos = parseInt(e.message.slice(39));
|
55
60
|
emitMessages(buffer.slice(0,pos));
|
56
61
|
return emitMessages(buffer.slice(pos));
|
@@ -70,8 +75,8 @@ class Condenser::RollupProcessor < Condenser::NodeProcessor
|
|
70
75
|
});
|
71
76
|
|
72
77
|
const rollup = require("#{npm_module_path('rollup')}");
|
73
|
-
const commonjs = require("#{npm_module_path('rollup
|
74
|
-
const nodeResolve = require("#{npm_module_path('rollup
|
78
|
+
const commonjs = require("#{npm_module_path('@rollup/plugin-commonjs')}");
|
79
|
+
const nodeResolve = require("#{npm_module_path('@rollup/plugin-node-resolve')}").nodeResolve;
|
75
80
|
var rid = 0;
|
76
81
|
var renderStack = {};
|
77
82
|
var nodeResolver = null;
|
@@ -95,9 +100,8 @@ class Condenser::RollupProcessor < Condenser::NodeProcessor
|
|
95
100
|
mainFields: ['module', 'main'],
|
96
101
|
// modulesOnly: true,
|
97
102
|
// preferBuiltins: false,
|
98
|
-
|
99
|
-
|
100
|
-
}
|
103
|
+
moduleDirectories: [],
|
104
|
+
modulePaths: ['#{npm_module_path}']
|
101
105
|
});
|
102
106
|
}
|
103
107
|
|
@@ -105,9 +109,9 @@ class Condenser::RollupProcessor < Condenser::NodeProcessor
|
|
105
109
|
inputOptions.plugins = [];
|
106
110
|
inputOptions.plugins.push({
|
107
111
|
name: 'condenser',
|
108
|
-
resolveId: function (importee, importer) {
|
112
|
+
resolveId: function (importee, importer, options) {
|
109
113
|
if (importee.startsWith('\\0') || (importer && importer.startsWith('\\0'))) {
|
110
|
-
return;
|
114
|
+
return null;
|
111
115
|
}
|
112
116
|
|
113
117
|
if (!(importer in renderStack)) {
|
@@ -115,24 +119,15 @@ class Condenser::RollupProcessor < Condenser::NodeProcessor
|
|
115
119
|
}
|
116
120
|
|
117
121
|
return request('resolve', [importee, importer]).then((value) => {
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
}
|
123
|
-
return value;
|
124
|
-
});
|
125
|
-
}
|
126
|
-
|
127
|
-
if (!(value === null || value === undefined) && !renderStack[importer].includes(value)) {
|
128
|
-
renderStack[importer].push(value);
|
129
|
-
}
|
130
|
-
return value;
|
122
|
+
if (!(value === null || value === undefined) && !renderStack[importer].includes(value)) {
|
123
|
+
renderStack[importer].push(value);
|
124
|
+
}
|
125
|
+
return value;
|
131
126
|
});
|
132
127
|
},
|
133
128
|
load: function(id) {
|
134
129
|
if (id.startsWith('\\0')) {
|
135
|
-
return;
|
130
|
+
return null;
|
136
131
|
}
|
137
132
|
|
138
133
|
return request('load', [id]).then(function(value) {
|
@@ -140,17 +135,19 @@ class Condenser::RollupProcessor < Condenser::NodeProcessor
|
|
140
135
|
});
|
141
136
|
}
|
142
137
|
});
|
138
|
+
|
143
139
|
inputOptions.plugins.push(nodeResolver);
|
144
140
|
inputOptions.plugins.push(commonjs());
|
145
141
|
|
146
|
-
inputOptions.plugins.push({
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
}
|
142
|
+
// inputOptions.plugins.push({
|
143
|
+
// name: 'nullHanlder',
|
144
|
+
// resolveId: function (importee, importer, options) {
|
145
|
+
// request('log', [importee, importer, options])
|
146
|
+
// // request('error', ["AssetNotFound", importee, importer, renderStack]).then(function(value) {
|
147
|
+
// // process.exit(1);
|
148
|
+
// // });
|
149
|
+
// }
|
150
|
+
// });
|
154
151
|
|
155
152
|
const outputOptions = #{JSON.generate(output_options)};
|
156
153
|
|
@@ -204,14 +201,20 @@ class Condenser::RollupProcessor < Condenser::NodeProcessor
|
|
204
201
|
@entry
|
205
202
|
elsif importee.start_with?('@babel/runtime') || importee.start_with?('core-js-pure') || importee.start_with?('regenerator-runtime')
|
206
203
|
x = File.join(npm_module_path, importee.gsub(/^\.\//, File.dirname(importer) + '/')).sub('/node_modules/regenerator-runtime', '/node_modules/regenerator-runtime/runtime.js')
|
207
|
-
x = "#{x}.js" if !x.end_with?('.js')
|
204
|
+
x = "#{x}.js" if !x.end_with?('.js', '.mjs')
|
205
|
+
File.file?(x) ? x : (x.delete_suffix('.js') + "/index.js")
|
206
|
+
elsif npm_module_path && importee&.start_with?(npm_module_path)
|
207
|
+
x = importee.end_with?('.js', '.mjs') ? importee : "#{importee}.js"
|
208
|
+
x = (x.delete_suffix('.js') + "/index.js") if !File.file?(x)
|
209
|
+
x
|
210
|
+
elsif importee.start_with?('.') && importer.start_with?(npm_module_path)
|
211
|
+
x = File.expand_path(importee, File.dirname(importer))
|
212
|
+
x = "#{x}.js" if !x.end_with?('.js', '.mjs')
|
208
213
|
File.file?(x) ? x : (x.delete_suffix('.js') + "/index.js")
|
209
|
-
elsif npm_module_path && importer.start_with?(npm_module_path)
|
210
|
-
nil
|
211
214
|
elsif importee.end_with?('*')
|
212
215
|
File.join(File.dirname(importee), '*')
|
213
216
|
else
|
214
|
-
@environment.find(importee, importer ?
|
217
|
+
@environment.find(importee, importer ? (@entry == importer ? @input[:source_file] : importer) : nil, accept: @input[:content_types].last)&.source_file
|
215
218
|
end
|
216
219
|
when 'load'
|
217
220
|
importee = message['args'].first
|
@@ -261,7 +264,6 @@ class Condenser::RollupProcessor < Condenser::NodeProcessor
|
|
261
264
|
# when 'get_cache'
|
262
265
|
# io.write(JSON.generate({rid: message['rid'], return: [(@environment.cache.get('rollup') || '{}')] }))
|
263
266
|
end
|
264
|
-
|
265
267
|
io.write(JSON.generate({rid: message['rid'], return: ret}))
|
266
268
|
end
|
267
269
|
end
|
data/lib/condenser/resolve.rb
CHANGED
@@ -38,9 +38,7 @@ class Condenser
|
|
38
38
|
end
|
39
39
|
|
40
40
|
paths.each do |path|
|
41
|
-
glob = path
|
42
|
-
glob = File.join(glob, dirname) if dirname
|
43
|
-
glob = File.join(glob, basename)
|
41
|
+
glob = File.join(*[path, dirname, basename].compact)
|
44
42
|
glob << '.*' unless glob.end_with?('*')
|
45
43
|
|
46
44
|
Dir.glob(glob).sort.each do |f|
|
@@ -150,11 +148,34 @@ class Condenser
|
|
150
148
|
end
|
151
149
|
end
|
152
150
|
|
151
|
+
def has_dir?(path)
|
152
|
+
path.count('/') > (path.start_with?('/') ? 1 : 0)
|
153
|
+
end
|
154
|
+
|
155
|
+
def expand_path(path)
|
156
|
+
dir = if path.start_with?('/')
|
157
|
+
File.expand_path(path)
|
158
|
+
else
|
159
|
+
File.expand_path("/#{path}").delete_prefix('/')
|
160
|
+
end
|
161
|
+
dir.empty? ? nil : dir
|
162
|
+
end
|
163
|
+
|
153
164
|
def decompose_path(path, base=nil)
|
154
|
-
dirname = path.
|
155
|
-
|
156
|
-
|
165
|
+
dirname = if base && path.start_with?('.')
|
166
|
+
if has_dir?(base)
|
167
|
+
if has_dir?(path)
|
168
|
+
expand_path(File.join(File.dirname(base), File.dirname(path)))
|
169
|
+
else
|
170
|
+
expand_path(File.dirname(base))
|
171
|
+
end
|
172
|
+
else
|
173
|
+
expand_path(File.dirname(path))
|
174
|
+
end
|
175
|
+
else
|
176
|
+
path.index('/') ? File.dirname(path) : nil
|
157
177
|
end
|
178
|
+
|
158
179
|
|
159
180
|
_, star, basename, extensions = path.match(/(([^\.\/]+)(\.[^\/]+)|\*|[^\/]+)$/).to_a
|
160
181
|
if extensions == '.*'
|
@@ -0,0 +1,285 @@
|
|
1
|
+
class Condenser::DartSassTransformer < Condenser::NodeProcessor
|
2
|
+
|
3
|
+
@@helper_methods = Set.new
|
4
|
+
|
5
|
+
ACCEPT = ['text/css', 'text/scss', 'text/sass']
|
6
|
+
|
7
|
+
attr_accessor :options
|
8
|
+
|
9
|
+
# Use this function to append Modules that contain functions to expose
|
10
|
+
# to dart-sass
|
11
|
+
def self.add_helper_methods(module_to_add = nil, &block)
|
12
|
+
old_methods = self.instance_methods
|
13
|
+
|
14
|
+
self.include(module_to_add) if module_to_add
|
15
|
+
self.class_eval(&block) if block_given?
|
16
|
+
|
17
|
+
@@helper_methods.merge(self.instance_methods - old_methods)
|
18
|
+
end
|
19
|
+
|
20
|
+
add_helper_methods(Condenser::Sass::Functions)
|
21
|
+
|
22
|
+
def self.syntax
|
23
|
+
:sass
|
24
|
+
end
|
25
|
+
|
26
|
+
def initialize(dir, options = {})
|
27
|
+
super(dir)
|
28
|
+
npm_install('sass')
|
29
|
+
|
30
|
+
@options = options.merge({
|
31
|
+
indentedSyntax: self.class.syntax == :sass
|
32
|
+
}).freeze
|
33
|
+
end
|
34
|
+
|
35
|
+
def helper_method_signatures
|
36
|
+
x = @@helper_methods.map do |name|
|
37
|
+
arity = self.method(name).arity
|
38
|
+
signature = []
|
39
|
+
types = []
|
40
|
+
if respond_to?(:"#{name}_signature")
|
41
|
+
send(:"#{name}_signature").each do |arg, type|
|
42
|
+
signature << arg
|
43
|
+
types << type
|
44
|
+
end
|
45
|
+
elsif arity >= 0
|
46
|
+
arity.times.with_index do |a|
|
47
|
+
signature << "$arg#{a}"
|
48
|
+
types << 'String'
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
["#{name}(#{signature.join(', ')})", types]
|
53
|
+
end
|
54
|
+
x
|
55
|
+
end
|
56
|
+
|
57
|
+
def call(environment, input)
|
58
|
+
@context = environment.new_context_class#.new(environment)
|
59
|
+
|
60
|
+
options = {
|
61
|
+
verbose: true,
|
62
|
+
file: File.join('/', input[:filename])
|
63
|
+
}.merge(@options)
|
64
|
+
@environment = environment
|
65
|
+
@input = input
|
66
|
+
|
67
|
+
result = exec_runtime(<<-JS)
|
68
|
+
const fs = require('fs');
|
69
|
+
const sass = require("#{npm_module_path('sass')}");
|
70
|
+
const stdin = process.stdin;
|
71
|
+
stdin.resume();
|
72
|
+
stdin.setEncoding('utf8');
|
73
|
+
|
74
|
+
// SET STDOUT to sync so that we don't get in an infinte looping waiting
|
75
|
+
// for Ruby to response when we haven't even sent the entire request.
|
76
|
+
if (process.stdout._handle) process.stdout._handle.setBlocking(true)
|
77
|
+
|
78
|
+
const source = #{JSON.generate(input[:source])};
|
79
|
+
const options = #{JSON.generate(options)};
|
80
|
+
|
81
|
+
var rid = 0;
|
82
|
+
function request(method, ...args) {
|
83
|
+
var trid = rid;
|
84
|
+
rid += 1;
|
85
|
+
console.log(JSON.stringify({ rid: trid, method: method, args: args }) + "\\n");
|
86
|
+
|
87
|
+
|
88
|
+
var readBuffer = '';
|
89
|
+
var response = null;
|
90
|
+
let chunk = new Buffer(1024);
|
91
|
+
let bytesRead;
|
92
|
+
|
93
|
+
while (response === null) {
|
94
|
+
try {
|
95
|
+
bytesRead = fs.readSync(stdin.fd, chunk, 0, 1024);
|
96
|
+
if (bytesRead === null) { exit(1); }
|
97
|
+
readBuffer += chunk.toString('utf8', 0, bytesRead);
|
98
|
+
[readBuffer, response] = readResponse(readBuffer);
|
99
|
+
} catch (e) {
|
100
|
+
if (e.code !== 'EAGAIN') { throw e; }
|
101
|
+
}
|
102
|
+
}
|
103
|
+
return response['return'];
|
104
|
+
}
|
105
|
+
|
106
|
+
function readResponse(buffer) {
|
107
|
+
try {
|
108
|
+
var message = JSON.parse(buffer);
|
109
|
+
return ['', message];
|
110
|
+
} catch(e) {
|
111
|
+
if (e.name === "SyntaxError") {
|
112
|
+
if (e.message.startsWith('Unexpected non-whitespace character after JSON at position ')) {
|
113
|
+
let pos = parseInt(e.message.slice(59));
|
114
|
+
let [b, r] = readResponse(buffer.slice(0,pos));
|
115
|
+
return [b + buffer.slice(pos), r];
|
116
|
+
} else if (e.message.startsWith('Unexpected token { in JSON at position ')) {
|
117
|
+
// This can be removed, once dropping support for node <= v18
|
118
|
+
var pos = parseInt(e.message.slice(39));
|
119
|
+
let [b, r] = readResponse(buffer.slice(0,pos));
|
120
|
+
return [b + buffer.slice(pos), r];
|
121
|
+
} else {
|
122
|
+
return [buffer, null];
|
123
|
+
}
|
124
|
+
} else {
|
125
|
+
console.log(JSON.stringify({method: 'error', args: [e.name, e.message]}) + "\\n");
|
126
|
+
process.exit(1);
|
127
|
+
}
|
128
|
+
}
|
129
|
+
}
|
130
|
+
|
131
|
+
|
132
|
+
options.importer = function(url, prev) { return request('load', url, prev); };
|
133
|
+
|
134
|
+
const call_fn = function(name, types, args) {
|
135
|
+
const transformedArgs = [];
|
136
|
+
request('log', '==================')
|
137
|
+
args.forEach((a, i) => {
|
138
|
+
if (types[i] === 'Map') {
|
139
|
+
// Don't know how to go from SassMap to hash yet
|
140
|
+
transformedArgs.push({});
|
141
|
+
} else if (types[i] === 'List') {
|
142
|
+
// Don't know how to go from SassList to hash yet
|
143
|
+
transformedArgs.push([]);
|
144
|
+
} else if (!(a instanceof sass.types[types[i]])) {
|
145
|
+
throw "$url: Expected a string.";
|
146
|
+
} else {
|
147
|
+
transformedArgs.push(a.getValue());
|
148
|
+
}
|
149
|
+
|
150
|
+
|
151
|
+
// if (types[i] === 'List') { a = a.contents(); }
|
152
|
+
});
|
153
|
+
request('log', name, transformedArgs, types)
|
154
|
+
return new sass.types.String(request('call', name, transformedArgs));
|
155
|
+
}
|
156
|
+
options.functions = {};
|
157
|
+
#{JSON.generate(helper_method_signatures)}.forEach( (f) => {
|
158
|
+
let name = f[0].replace(/-/g, '_').replace(/(^[^\\(]+)\\(.*\\)$/, '$1');
|
159
|
+
options.functions[f[0]] = (...a) => call_fn(name, f[1], a);
|
160
|
+
})
|
161
|
+
|
162
|
+
try {
|
163
|
+
options.data = source;
|
164
|
+
const result = sass.renderSync(options);
|
165
|
+
request('result', result.css.toString());
|
166
|
+
process.exit(0);
|
167
|
+
} catch(e) {
|
168
|
+
request('error', e.name, e.message);
|
169
|
+
process.exit(1);
|
170
|
+
}
|
171
|
+
JS
|
172
|
+
|
173
|
+
input[:source] = result
|
174
|
+
# input[:map] = map.to_json({})
|
175
|
+
input[:linked_assets] += @context.links
|
176
|
+
input[:process_dependencies] += @context.dependencies
|
177
|
+
end
|
178
|
+
|
179
|
+
def find(importee, importer = nil)
|
180
|
+
# importer ||= @input[:source_file]
|
181
|
+
@environment.find(expand_path(importee, importer), nil, accept: ACCEPT)
|
182
|
+
end
|
183
|
+
|
184
|
+
def resolve(importee, importer = nil)
|
185
|
+
# importer ||= @input[:source_file]
|
186
|
+
@environment.resolve(expand_path(importee, importer), accept: ACCEPT)
|
187
|
+
end
|
188
|
+
|
189
|
+
def expand_path(path, base=nil)
|
190
|
+
if path.start_with?('.')
|
191
|
+
File.expand_path(path, File.dirname(base)).delete_prefix(File.expand_path('.') + '/')
|
192
|
+
else
|
193
|
+
File.expand_path(path).delete_prefix(File.expand_path('.') + '/')
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
def exec_runtime(script)
|
198
|
+
io = IO.popen([binary, '-e', script], 'r+')
|
199
|
+
buffer = ''
|
200
|
+
result = nil
|
201
|
+
|
202
|
+
begin
|
203
|
+
while IO.select([io]) && io_read = io.read_nonblock(1_024)
|
204
|
+
buffer << io_read
|
205
|
+
messages = buffer.split("\n\n")
|
206
|
+
buffer = buffer.end_with?("\n\n") ? '' : messages.pop
|
207
|
+
|
208
|
+
messages.each do |message|
|
209
|
+
message = JSON.parse(message)
|
210
|
+
|
211
|
+
ret = case message['method']
|
212
|
+
when 'result'
|
213
|
+
result = message['args'][0]
|
214
|
+
nil
|
215
|
+
when 'load'
|
216
|
+
importee = message['args'][0]
|
217
|
+
importer = message['args'][1]
|
218
|
+
|
219
|
+
if importee.end_with?('*')
|
220
|
+
@context.depend_on(importee)
|
221
|
+
code = ""
|
222
|
+
resolve(importee, importer).each do |f, i|
|
223
|
+
code << "@import '#{f.filename}';\n"
|
224
|
+
end
|
225
|
+
{ contents: code, map: nil }
|
226
|
+
else
|
227
|
+
if asset = find(importee)
|
228
|
+
@context.depend_on(asset.filename)
|
229
|
+
{ contents: asset.source, map: asset.sourcemap }
|
230
|
+
else
|
231
|
+
@context.depend_on(importee)
|
232
|
+
nil
|
233
|
+
end
|
234
|
+
end
|
235
|
+
when 'error'
|
236
|
+
io.write(JSON.generate({rid: message['rid'], return: nil}))
|
237
|
+
|
238
|
+
case message['args'][0]
|
239
|
+
when 'AssetNotFound'
|
240
|
+
error_message = "Could not find import \"#{message['args'][1]}\" for \"#{message['args'][2]}\".\n\n"
|
241
|
+
error_message << build_tree(message['args'][3], input, message['args'][2])
|
242
|
+
raise exec_runtime_error(error_message)
|
243
|
+
else
|
244
|
+
raise exec_runtime_error(message['args'][0] + ': ' + message['args'][1])
|
245
|
+
end
|
246
|
+
when 'call'
|
247
|
+
if respond_to?(message['args'][0])
|
248
|
+
send(message['args'][0], *message['args'][1])
|
249
|
+
else
|
250
|
+
puts '!!!'
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
254
|
+
io.write(JSON.generate({rid: message['rid'], return: ret}))
|
255
|
+
end
|
256
|
+
end
|
257
|
+
rescue Errno::EPIPE, EOFError
|
258
|
+
end
|
259
|
+
|
260
|
+
io.close
|
261
|
+
if $?.success?
|
262
|
+
result
|
263
|
+
else
|
264
|
+
raise exec_runtime_error(buffer)
|
265
|
+
end
|
266
|
+
end
|
267
|
+
|
268
|
+
protected
|
269
|
+
|
270
|
+
def condenser_context
|
271
|
+
@context
|
272
|
+
end
|
273
|
+
|
274
|
+
def condenser_environment
|
275
|
+
@environment
|
276
|
+
end
|
277
|
+
|
278
|
+
|
279
|
+
end
|
280
|
+
|
281
|
+
class Condenser::DartScssTransformer < Condenser::DartSassTransformer
|
282
|
+
def self.syntax
|
283
|
+
:scss
|
284
|
+
end
|
285
|
+
end
|
@@ -23,32 +23,32 @@ class Condenser::JstTransformer < Condenser::NodeProcessor
|
|
23
23
|
const source = #{JSON.generate(input[:source])};
|
24
24
|
const options = #{JSON.generate(opts).gsub(/"@?babel[\/-][^"]+"/) { |m| "require(#{m})"}};
|
25
25
|
|
26
|
-
|
27
|
-
|
28
|
-
return true;
|
29
|
-
} else if (scope.parent === null || scope.parent === undefined) {
|
30
|
-
return false;
|
31
|
-
} else {
|
32
|
-
return globalVar(scope.parent, name);
|
33
|
-
}
|
34
|
-
}
|
35
|
-
|
26
|
+
let scope = [['document', 'window']];
|
27
|
+
|
36
28
|
options['plugins'].unshift(function({ types: t }) {
|
37
29
|
return {
|
38
30
|
visitor: {
|
39
31
|
Identifier(path, state) {
|
40
|
-
if ( path.parent.type
|
32
|
+
if ( path.parent.type === 'MemberExpression' && path.parent.object !== path.node) {
|
41
33
|
return;
|
42
34
|
}
|
43
|
-
|
35
|
+
|
36
|
+
if ( path.parent.type === 'ImportSpecifier' ||
|
37
|
+
path.parent.type === 'ImportDefaultSpecifier' ||
|
38
|
+
path.parent.type === 'FunctionDeclaration' ||
|
39
|
+
path.parent.type === 'FunctionExpression' ||
|
40
|
+
path.parent.type === 'ArrowFunctionExpression' ||
|
41
|
+
path.parent.type === 'SpreadElement' ||
|
42
|
+
path.parent.type === 'CatchClause' ) {
|
43
|
+
return;
|
44
|
+
}
|
45
|
+
|
46
|
+
if ( path.parent.type === 'ObjectProperty' && path.parent.key === path.node ) {
|
44
47
|
return;
|
45
48
|
}
|
46
49
|
|
47
|
-
if (
|
48
|
-
|
49
|
-
path.node.name !== 'window' &&
|
50
|
-
!(path.node.name in global) &&
|
51
|
-
globalVar(path.scope, path.node.name)
|
50
|
+
if ( !(path.node.name in global) &&
|
51
|
+
!scope.find((s) => s.find(v => v === path.node.name))
|
52
52
|
) {
|
53
53
|
path.replaceWith(
|
54
54
|
t.memberExpression(t.identifier("locals"), path.node)
|
@@ -58,6 +58,56 @@ class Condenser::JstTransformer < Condenser::NodeProcessor
|
|
58
58
|
}
|
59
59
|
};
|
60
60
|
});
|
61
|
+
|
62
|
+
|
63
|
+
options['plugins'].unshift(function({ types: t }) {
|
64
|
+
return {
|
65
|
+
visitor: {
|
66
|
+
"FunctionDeclaration|FunctionExpression|ArrowFunctionExpression": {
|
67
|
+
enter(path, state) {
|
68
|
+
if (path.node.id) { scope[scope.length-1].push(path.node.id.name); }
|
69
|
+
scope.push(path.node.params.map((n) => n.type === 'RestElement' ? n.argument.name : n.name));
|
70
|
+
}
|
71
|
+
},
|
72
|
+
CatchClause: {
|
73
|
+
enter(path, state) {
|
74
|
+
scope.push([]);
|
75
|
+
if (path.node.param.name) { scope[scope.length-1].push(path.node.param.name); }
|
76
|
+
}
|
77
|
+
},
|
78
|
+
Scopable: {
|
79
|
+
enter(path, state) {
|
80
|
+
if (path.node.type !== 'Program' &&
|
81
|
+
path.node.type !== 'CatchClause' &&
|
82
|
+
path.parent.type !== 'FunctionDeclaration' &&
|
83
|
+
path.parent.type !== 'FunctionExpression' &&
|
84
|
+
path.parent.type !== 'ArrowFunctionExpression' &&
|
85
|
+
path.parent.type !== 'ExportDefaultDeclaration') {
|
86
|
+
scope.push([]);
|
87
|
+
}
|
88
|
+
},
|
89
|
+
exit(path, state) {
|
90
|
+
if (path.node.type !== 'Program' &&
|
91
|
+
path.parent.type !== 'ExportDefaultDeclaration') {
|
92
|
+
scope.pop();
|
93
|
+
}
|
94
|
+
}
|
95
|
+
},
|
96
|
+
ImportDeclaration(path, state) {
|
97
|
+
path.node.specifiers.forEach((s) => scope[scope.length-1].push(s.local.name));
|
98
|
+
},
|
99
|
+
ClassDeclaration(path, state) {
|
100
|
+
if (path.node.id) {
|
101
|
+
scope[scope.length-1].push(path.node.id.name)
|
102
|
+
}
|
103
|
+
},
|
104
|
+
VariableDeclaration(path, state) {
|
105
|
+
path.node.declarations.forEach((s) => scope[scope.length-1].push(s.id.name));
|
106
|
+
}
|
107
|
+
}
|
108
|
+
};
|
109
|
+
});
|
110
|
+
|
61
111
|
|
62
112
|
try {
|
63
113
|
const result = babel.transform(source, options);
|