docs: function processOutput(generator, startOutput) {
      return Promise(startOutput)
      .then(preparePlugins)
      .then(preparePages)
      .then(prepareAssets)
  
      .then(
          callHook.bind(null,
              'config',
              function(output) {
                  var book = output.getBook();
                  var config = book.getConfig();
                  var values = config.getValues();
  
                  return values.toJS();
              },
              function(output, result) {
                  var book = output.getBook();
                  var config = book.getConfig();
  
                  config = config.updateValues(result);
                  book = book.set('config', config);
                  return output.set('book', book);
              }
          )
      )
  
      .then(
          callHook.bind(null,
              'init',
              function(output) {
                  return {};
              },
              function(output) {
                  return output;
              }
          )
      )
  
      .then(function(output) {
          if (!generator.onInit) {
              return output;
          }
  
          return generator.onInit(output);
      })
  
      .then(generateAssets.bind(null, generator))
      .then(generatePages.bind(null, generator))
  
      .tap(function(output) {
          var book = output.getBook();
  
          if (!book.isMultilingual()) {
              return;
          }
  
          var logger = book.getLogger();
          var books = book.getBooks();
          var outputRoot = output.getRoot();
          var plugins = output.getPlugins();
          var state = output.getState();
          var options = output.getOptions();
  
          return Promise.forEach(books, function(langBook) {
              // Inherits plugins list, options and state
              var langOptions = options.set('root', path.join(outputRoot, langBook.getLanguage()));
              var langOutput = new Output({
                  book:       langBook,
                  options:    langOptions,
                  state:      state,
                  generator:  generator.name,
                  plugins:    plugins
              });
  
              logger.info.ln('');
              logger.info.ln('generating language "' + langBook.getLanguage() + '"');
              return processOutput(generator, langOutput);
          });
      })
  
      .then(callHook.bind(null,
          'finish:before',
              function(output) {
                  return {};
              },
              function(output) {
                  return output;
              }
          )
      )
  
      .then(function(output) {
          if (!generator.onFinish) {
              return output;
          }
  
          return generator.onFinish(output);
      })
  
      .then(callHook.bind(null,
          'finish',
              function(output) {
                  return {};
              },
              function(output) {
                  return output;
              }
          )
      );
  }