mirror of
				https://scm.univ-tours.fr/22107988t/rappaurio-sae501_502.git
				synced 2025-11-04 05:15:23 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			342 lines
		
	
	
		
			8.3 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			342 lines
		
	
	
		
			8.3 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
/* eslint-env node */
 | 
						|
/* 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
 | 
						|
    }
 | 
						|
  });
 | 
						|
}
 |