summaryrefslogtreecommitdiff
path: root/node_modules/handlebars/lib/precompiler.js
diff options
context:
space:
mode:
author8cy <[email protected]>2020-04-30 15:46:16 -0700
committer8cy <[email protected]>2020-04-30 15:46:16 -0700
commit3a4deac89054021b56ad5bd8005b2044cc085c98 (patch)
tree3dd6af8503e497e46180b6b5231674f36bdce9f2 /node_modules/handlebars/lib/precompiler.js
downloaduppity-3a4deac89054021b56ad5bd8005b2044cc085c98.tar.xz
uppity-3a4deac89054021b56ad5bd8005b2044cc085c98.zip
Up, up, uppity.
Diffstat (limited to 'node_modules/handlebars/lib/precompiler.js')
-rw-r--r--node_modules/handlebars/lib/precompiler.js340
1 files changed, 340 insertions, 0 deletions
diff --git a/node_modules/handlebars/lib/precompiler.js b/node_modules/handlebars/lib/precompiler.js
new file mode 100644
index 0000000..689c9f4
--- /dev/null
+++ b/node_modules/handlebars/lib/precompiler.js
@@ -0,0 +1,340 @@
+/* eslint-disable no-console */
+import Async from 'neo-async';
+import fs from 'fs';
+import * as Handlebars from './handlebars';
+import { basename } from 'path';
+import { SourceMapConsumer, SourceNode } from 'source-map';
+
+module.exports.loadTemplates = function(opts, callback) {
+ loadStrings(opts, function(err, strings) {
+ if (err) {
+ callback(err);
+ } else {
+ loadFiles(opts, function(err, files) {
+ if (err) {
+ callback(err);
+ } else {
+ opts.templates = strings.concat(files);
+ callback(undefined, opts);
+ }
+ });
+ }
+ });
+};
+
+function loadStrings(opts, callback) {
+ let strings = arrayCast(opts.string),
+ names = arrayCast(opts.name);
+
+ if (names.length !== strings.length && strings.length > 1) {
+ return callback(
+ new Handlebars.Exception(
+ 'Number of names did not match the number of string inputs'
+ )
+ );
+ }
+
+ Async.map(
+ strings,
+ function(string, callback) {
+ if (string !== '-') {
+ callback(undefined, string);
+ } else {
+ // Load from stdin
+ let buffer = '';
+ process.stdin.setEncoding('utf8');
+
+ process.stdin.on('data', function(chunk) {
+ buffer += chunk;
+ });
+ process.stdin.on('end', function() {
+ callback(undefined, buffer);
+ });
+ }
+ },
+ function(err, strings) {
+ strings = strings.map((string, index) => ({
+ name: names[index],
+ path: names[index],
+ source: string
+ }));
+ callback(err, strings);
+ }
+ );
+}
+
+function loadFiles(opts, callback) {
+ // Build file extension pattern
+ let extension = (opts.extension || 'handlebars').replace(
+ /[\\^$*+?.():=!|{}\-[\]]/g,
+ function(arg) {
+ return '\\' + arg;
+ }
+ );
+ extension = new RegExp('\\.' + extension + '$');
+
+ let ret = [],
+ queue = (opts.files || []).map(template => ({ template, root: opts.root }));
+ Async.whilst(
+ () => queue.length,
+ function(callback) {
+ let { template: path, root } = queue.shift();
+
+ fs.stat(path, function(err, stat) {
+ if (err) {
+ return callback(
+ new Handlebars.Exception(`Unable to open template file "${path}"`)
+ );
+ }
+
+ if (stat.isDirectory()) {
+ opts.hasDirectory = true;
+
+ fs.readdir(path, function(err, children) {
+ /* istanbul ignore next : Race condition that being too lazy to test */
+ if (err) {
+ return callback(err);
+ }
+ children.forEach(function(file) {
+ let childPath = path + '/' + file;
+
+ if (
+ extension.test(childPath) ||
+ fs.statSync(childPath).isDirectory()
+ ) {
+ queue.push({ template: childPath, root: root || path });
+ }
+ });
+
+ callback();
+ });
+ } else {
+ fs.readFile(path, 'utf8', function(err, data) {
+ /* istanbul ignore next : Race condition that being too lazy to test */
+ if (err) {
+ return callback(err);
+ }
+
+ if (opts.bom && data.indexOf('\uFEFF') === 0) {
+ data = data.substring(1);
+ }
+
+ // Clean the template name
+ let name = path;
+ if (!root) {
+ name = basename(name);
+ } else if (name.indexOf(root) === 0) {
+ name = name.substring(root.length + 1);
+ }
+ name = name.replace(extension, '');
+
+ ret.push({
+ path: path,
+ name: name,
+ source: data
+ });
+
+ callback();
+ });
+ }
+ });
+ },
+ function(err) {
+ if (err) {
+ callback(err);
+ } else {
+ callback(undefined, ret);
+ }
+ }
+ );
+}
+
+module.exports.cli = function(opts) {
+ if (opts.version) {
+ console.log(Handlebars.VERSION);
+ return;
+ }
+
+ if (!opts.templates.length && !opts.hasDirectory) {
+ throw new Handlebars.Exception(
+ 'Must define at least one template or directory.'
+ );
+ }
+
+ if (opts.simple && opts.min) {
+ throw new Handlebars.Exception('Unable to minimize simple output');
+ }
+
+ const multiple = opts.templates.length !== 1 || opts.hasDirectory;
+ if (opts.simple && multiple) {
+ throw new Handlebars.Exception(
+ 'Unable to output multiple templates in simple mode'
+ );
+ }
+
+ // Force simple mode if we have only one template and it's unnamed.
+ if (
+ !opts.amd &&
+ !opts.commonjs &&
+ opts.templates.length === 1 &&
+ !opts.templates[0].name
+ ) {
+ opts.simple = true;
+ }
+
+ // Convert the known list into a hash
+ let known = {};
+ if (opts.known && !Array.isArray(opts.known)) {
+ opts.known = [opts.known];
+ }
+ if (opts.known) {
+ for (let i = 0, len = opts.known.length; i < len; i++) {
+ known[opts.known[i]] = true;
+ }
+ }
+
+ const objectName = opts.partial ? 'Handlebars.partials' : 'templates';
+
+ let output = new SourceNode();
+ if (!opts.simple) {
+ if (opts.amd) {
+ output.add(
+ "define(['" +
+ opts.handlebarPath +
+ 'handlebars.runtime\'], function(Handlebars) {\n Handlebars = Handlebars["default"];'
+ );
+ } else if (opts.commonjs) {
+ output.add('var Handlebars = require("' + opts.commonjs + '");');
+ } else {
+ output.add('(function() {\n');
+ }
+ output.add(' var template = Handlebars.template, templates = ');
+ if (opts.namespace) {
+ output.add(opts.namespace);
+ output.add(' = ');
+ output.add(opts.namespace);
+ output.add(' || ');
+ }
+ output.add('{};\n');
+ }
+
+ opts.templates.forEach(function(template) {
+ let options = {
+ knownHelpers: known,
+ knownHelpersOnly: opts.o
+ };
+
+ if (opts.map) {
+ options.srcName = template.path;
+ }
+ if (opts.data) {
+ options.data = true;
+ }
+
+ let precompiled = Handlebars.precompile(template.source, options);
+
+ // If we are generating a source map, we have to reconstruct the SourceNode object
+ if (opts.map) {
+ let consumer = new SourceMapConsumer(precompiled.map);
+ precompiled = SourceNode.fromStringWithSourceMap(
+ precompiled.code,
+ consumer
+ );
+ }
+
+ if (opts.simple) {
+ output.add([precompiled, '\n']);
+ } else {
+ if (!template.name) {
+ throw new Handlebars.Exception('Name missing for template');
+ }
+
+ if (opts.amd && !multiple) {
+ output.add('return ');
+ }
+ output.add([
+ objectName,
+ "['",
+ template.name,
+ "'] = template(",
+ precompiled,
+ ');\n'
+ ]);
+ }
+ });
+
+ // Output the content
+ if (!opts.simple) {
+ if (opts.amd) {
+ if (multiple) {
+ output.add(['return ', objectName, ';\n']);
+ }
+ output.add('});');
+ } else if (!opts.commonjs) {
+ output.add('})();');
+ }
+ }
+
+ if (opts.map) {
+ output.add('\n//# sourceMappingURL=' + opts.map + '\n');
+ }
+
+ output = output.toStringWithSourceMap();
+ output.map = output.map + '';
+
+ if (opts.min) {
+ output = minify(output, opts.map);
+ }
+
+ if (opts.map) {
+ fs.writeFileSync(opts.map, output.map, 'utf8');
+ }
+ output = output.code;
+
+ if (opts.output) {
+ fs.writeFileSync(opts.output, output, 'utf8');
+ } else {
+ console.log(output);
+ }
+};
+
+function arrayCast(value) {
+ value = value != null ? value : [];
+ if (!Array.isArray(value)) {
+ value = [value];
+ }
+ return value;
+}
+
+/**
+ * Run uglify to minify the compiled template, if uglify exists in the dependencies.
+ *
+ * We are using `require` instead of `import` here, because es6-modules do not allow
+ * dynamic imports and uglify-js is an optional dependency. Since we are inside NodeJS here, this
+ * should not be a problem.
+ *
+ * @param {string} output the compiled template
+ * @param {string} sourceMapFile the file to write the source map to.
+ */
+function minify(output, sourceMapFile) {
+ try {
+ // Try to resolve uglify-js in order to see if it does exist
+ require.resolve('uglify-js');
+ } catch (e) {
+ if (e.code !== 'MODULE_NOT_FOUND') {
+ // Something else seems to be wrong
+ throw e;
+ }
+ // it does not exist!
+ console.error(
+ 'Code minimization is disabled due to missing uglify-js dependency'
+ );
+ return output;
+ }
+ return require('uglify-js').minify(output.code, {
+ sourceMap: {
+ content: output.map,
+ url: sourceMapFile
+ }
+ });
+}