code: function(bundler, files, cb) {
        var prevEngine = null;
        var templates = [];
        if (!(files && files.length > 0)) {
          cb('');
        }
        return files.forEach(function(desc) {
          // Work out which template engine to use, based upon the path (TODO split file.sep)
          var engine = selectEngine(desc.file) || defaultEngine;
  
          var formatter;
          if (engine.selectFormatter) {
            formatter = engine.selectFormatter(desc.file, ss.client.formatters, null);
          }
  
          var opts = {
            constants: bundler.constants(),
            locals: bundler.locals()
          };
  
          return bundler.format(desc,
            opts, formatter, function(output) {
  
            templates.push(wrapTemplate(output, desc.file, ss.bundler.clientFilePath(desc), opts, options, engine, prevEngine));
            prevEngine = engine;
  
            // Return if last template
            if (templates.length === files.length) {
              output = templates.join('');
              if (engine !== null && engine.suffix) {
                output += engine.suffix();
              }
              return cb(output);
            }
          }, function(err) {
            ss.log.clientIssue(client,options,err,desc);
            return cb('Couldn\'t format ' + desc.file + err.userInfoHTML);
          });
        });
      }
docs: TODO the default IDs for templates are best relative to client (or project root?) 
  @ngdoc function
  @name client.templateEngine:templateEngine#generate
  @methodOf client.templateEngine:templateEngine
  @param {Object} bundler - Bundler instance for client.
  @param {Array} files - Entries for the templates to render markup for.
  @param {Function} cb - Callback to receive the string output or Error object.
  @description
  Generate output (as a string) from Template Engines
  
  function(out) {
  if (typeof out === 'string') {
  } else {
  // error object
  }
  }