PluginProbe
Force Refresh / 2.0.0
Force Refresh v2.0.0
3.2.1 3.2.0 3.1.2 3.1.1 3.1.0 trunk 1.0.0 1.1.0 1.1.1 1.1.2 1.2.0 2.0.0 2.1.0 2.1.1 2.1.2 2.1.3 2.1.4 2.1.5 2.1.6 2.10.0 2.10.1 2.10.2 2.11.0 2.11.1 2.12.0 All 54 releases
force-refresh / node_modules / handlebars / lib / precompiler.js

precompiler.js in Force Refresh 2.0.0, at node_modules/handlebars/lib/precompiler.js

299 lines 7.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /* eslint-disable no-console */
2 import Async from 'async';
3 import fs from 'fs';
4 import * as Handlebars from './handlebars';
5 import {basename} from 'path';
6 import {SourceMapConsumer, SourceNode} from 'source-map';
7
8
9 module.exports.loadTemplates = function(opts, callback) {
10 loadStrings(opts, function(err, strings) {
11 if (err) {
12 callback(err);
13 } else {
14 loadFiles(opts, function(err, files) {
15 if (err) {
16 callback(err);
17 } else {
18 opts.templates = strings.concat(files);
19 callback(undefined, opts);
20 }
21 });
22 }
23 });
24 };
25
26 function loadStrings(opts, callback) {
27 let strings = arrayCast(opts.string),
28 names = arrayCast(opts.name);
29
30 if (names.length !== strings.length
31 && strings.length > 1) {
32 return callback(new Handlebars.Exception('Number of names did not match the number of string inputs'));
33 }
34
35 Async.map(strings, function(string, callback) {
36 if (string !== '-') {
37 callback(undefined, string);
38 } else {
39 // Load from stdin
40 let buffer = '';
41 process.stdin.setEncoding('utf8');
42
43 process.stdin.on('data', function(chunk) {
44 buffer += chunk;
45 });
46 process.stdin.on('end', function() {
47 callback(undefined, buffer);
48 });
49 }
50 },
51 function(err, strings) {
52 strings = strings.map((string, index) => ({
53 name: names[index],
54 path: names[index],
55 source: string
56 }));
57 callback(err, strings);
58 });
59 }
60
61 function loadFiles(opts, callback) {
62 // Build file extension pattern
63 let extension = (opts.extension || 'handlebars').replace(/[\\^$*+?.():=!|{}\-[\]]/g, function(arg) { return '\\' + arg; });
64 extension = new RegExp('\\.' + extension + '$');
65
66 let ret = [],
67 queue = (opts.files || []).map((template) => ({template, root: opts.root}));
68 Async.whilst(() => queue.length, function(callback) {
69 let {template: path, root} = queue.shift();
70
71 fs.stat(path, function(err, stat) {
72 if (err) {
73 return callback(new Handlebars.Exception(`Unable to open template file "${path}"`));
74 }
75
76 if (stat.isDirectory()) {
77 opts.hasDirectory = true;
78
79 fs.readdir(path, function(err, children) {
80 /* istanbul ignore next : Race condition that being too lazy to test */
81 if (err) {
82 return callback(err);
83 }
84 children.forEach(function(file) {
85 let childPath = path + '/' + file;
86
87 if (extension.test(childPath) || fs.statSync(childPath).isDirectory()) {
88 queue.push({template: childPath, root: root || path});
89 }
90 });
91
92 callback();
93 });
94 } else {
95 fs.readFile(path, 'utf8', function(err, data) {
96 /* istanbul ignore next : Race condition that being too lazy to test */
97 if (err) {
98 return callback(err);
99 }
100
101 if (opts.bom && data.indexOf('\uFEFF') === 0) {
102 data = data.substring(1);
103 }
104
105 // Clean the template name
106 let name = path;
107 if (!root) {
108 name = basename(name);
109 } else if (name.indexOf(root) === 0) {
110 name = name.substring(root.length + 1);
111 }
112 name = name.replace(extension, '');
113
114 ret.push({
115 path: path,
116 name: name,
117 source: data
118 });
119
120 callback();
121 });
122 }
123 });
124 },
125 function(err) {
126 if (err) {
127 callback(err);
128 } else {
129 callback(undefined, ret);
130 }
131 });
132 }
133
134 module.exports.cli = function(opts) {
135 if (opts.version) {
136 console.log(Handlebars.VERSION);
137 return;
138 }
139
140 if (!opts.templates.length && !opts.hasDirectory) {
141 throw new Handlebars.Exception('Must define at least one template or directory.');
142 }
143
144 if (opts.simple && opts.min) {
145 throw new Handlebars.Exception('Unable to minimize simple output');
146 }
147
148 const multiple = opts.templates.length !== 1 || opts.hasDirectory;
149 if (opts.simple && multiple) {
150 throw new Handlebars.Exception('Unable to output multiple templates in simple mode');
151 }
152
153 // Force simple mode if we have only one template and it's unnamed.
154 if (!opts.amd && !opts.commonjs && opts.templates.length === 1
155 && !opts.templates[0].name) {
156 opts.simple = true;
157 }
158
159 // Convert the known list into a hash
160 let known = {};
161 if (opts.known && !Array.isArray(opts.known)) {
162 opts.known = [opts.known];
163 }
164 if (opts.known) {
165 for (let i = 0, len = opts.known.length; i < len; i++) {
166 known[opts.known[i]] = true;
167 }
168 }
169
170 const objectName = opts.partial ? 'Handlebars.partials' : 'templates';
171
172 let output = new SourceNode();
173 if (!opts.simple) {
174 if (opts.amd) {
175 output.add('define([\'' + opts.handlebarPath + 'handlebars.runtime\'], function(Handlebars) {\n Handlebars = Handlebars["default"];');
176 } else if (opts.commonjs) {
177 output.add('var Handlebars = require("' + opts.commonjs + '");');
178 } else {
179 output.add('(function() {\n');
180 }
181 output.add(' var template = Handlebars.template, templates = ');
182 if (opts.namespace) {
183 output.add(opts.namespace);
184 output.add(' = ');
185 output.add(opts.namespace);
186 output.add(' || ');
187 }
188 output.add('{};\n');
189 }
190
191 opts.templates.forEach(function(template) {
192 let options = {
193 knownHelpers: known,
194 knownHelpersOnly: opts.o
195 };
196
197 if (opts.map) {
198 options.srcName = template.path;
199 }
200 if (opts.data) {
201 options.data = true;
202 }
203
204 let precompiled = Handlebars.precompile(template.source, options);
205
206 // If we are generating a source map, we have to reconstruct the SourceNode object
207 if (opts.map) {
208 let consumer = new SourceMapConsumer(precompiled.map);
209 precompiled = SourceNode.fromStringWithSourceMap(precompiled.code, consumer);
210 }
211
212 if (opts.simple) {
213 output.add([precompiled, '\n']);
214 } else {
215 if (!template.name) {
216 throw new Handlebars.Exception('Name missing for template');
217 }
218
219 if (opts.amd && !multiple) {
220 output.add('return ');
221 }
222 output.add([objectName, '[\'', template.name, '\'] = template(', precompiled, ');\n']);
223 }
224 });
225
226 // Output the content
227 if (!opts.simple) {
228 if (opts.amd) {
229 if (multiple) {
230 output.add(['return ', objectName, ';\n']);
231 }
232 output.add('});');
233 } else if (!opts.commonjs) {
234 output.add('})();');
235 }
236 }
237
238 if (opts.map) {
239 output.add('\n//# sourceMappingURL=' + opts.map + '\n');
240 }
241
242 output = output.toStringWithSourceMap();
243 output.map = output.map + '';
244
245 if (opts.min) {
246 output = minify(output, opts.map);
247 }
248
249 if (opts.map) {
250 fs.writeFileSync(opts.map, output.map, 'utf8');
251 }
252 output = output.code;
253
254 if (opts.output) {
255 fs.writeFileSync(opts.output, output, 'utf8');
256 } else {
257 console.log(output);
258 }
259 };
260
261 function arrayCast(value) {
262 value = value != null ? value : [];
263 if (!Array.isArray(value)) {
264 value = [value];
265 }
266 return value;
267 }
268
269 /**
270 * Run uglify to minify the compiled template, if uglify exists in the dependencies.
271 *
272 * We are using `require` instead of `import` here, because es6-modules do not allow
273 * dynamic imports and uglify-js is an optional dependency. Since we are inside NodeJS here, this
274 * should not be a problem.
275 *
276 * @param {string} output the compiled template
277 * @param {string} sourceMapFile the file to write the source map to.
278 */
279 function minify(output, sourceMapFile) {
280 try {
281 // Try to resolve uglify-js in order to see if it does exist
282 require.resolve('uglify-js');
283 } catch (e) {
284 if (e.code !== 'MODULE_NOT_FOUND') {
285 // Something else seems to be wrong
286 throw e;
287 }
288 // it does not exist!
289 console.error('Code minimization is disabled due to missing uglify-js dependency');
290 return output;
291 }
292 return require('uglify-js').minify(output.code, {
293 sourceMap: {
294 content: output.map,
295 url: sourceMapFile
296 }
297 });
298 }
299