all files / static-site-generator-webpack-plugin/ index.js

100% Statements 71/71
100% Branches 32/32
100% Functions 10/10
100% Lines 71/71
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147   17×     17×   17× 17× 17× 17×     17×   17× 17× 17×   17× 17×   17× 17×   17×     16×   16× 16×   16×     16×     15× 35×   35× 32×     35×           35× 34× 33×       35×       35×   34×           15×             17× 11×   11×     17×   17×     16×   16×     15×     15×       16× 16× 16×     16×       16×   16×     16×                    
var RawSource = require('webpack-sources/lib/RawSource');
var evaluate = require('eval');
var path = require('path');
var Promise = require('bluebird');
 
function StaticSiteGeneratorWebpackPlugin(options) {
  if (arguments.length > 1) {
    options = legacyArgsToOptions.apply(null, arguments);
  }
 
  options = options || {};
 
  this.entry = options.entry;
  this.paths = Array.isArray(options.paths) ? options.paths : [options.paths || '/'];
  this.locals = options.locals;
  this.globals = options.globals;
}
 
StaticSiteGeneratorWebpackPlugin.prototype.apply = function(compiler) {
  var self = this;
 
  compiler.plugin('this-compilation', function(compilation) {
    compilation.plugin('optimize-assets', function(_, done) {
      var renderPromises;
 
      var webpackStats = compilation.getStats();
      var webpackStatsJson = webpackStats.toJson();
 
      try {
        var asset = findAsset(self.entry, compilation, webpackStatsJson);
 
        if (asset == null) {
          throw new Error('Source file not found: "' + self.entry + '"');
        }
 
        var assets = getAssetsFromCompilation(compilation, webpackStatsJson);
 
        var source = asset.source();
        var render = evaluate(source, /* filename: */ self.entry, /* scope: */ self.globals, /* includeGlobals: */ true);
 
        if (render.hasOwnProperty('default')) {
          render = render['default'];
        }
 
        if (typeof render !== 'function') {
          throw new Error('Export from "' + self.entry + '" must be a function that returns an HTML string. Is output.libraryTarget in the configuration set to "umd"?');
        }
 
        renderPromises = self.paths.map(function(outputPath) {
          var outputFileName = outputPath.replace(/^(\/|\\)/, ''); // Remove leading slashes for webpack-dev-server
 
          if (!/\.(html?)$/i.test(outputFileName)) {
            outputFileName = path.join(outputFileName, 'index.html');
          }
 
          var locals = {
            path: outputPath,
            assets: assets,
            webpackStats: webpackStats
          };
 
          for (var prop in self.locals) {
            if (self.locals.hasOwnProperty(prop)) {
              locals[prop] = self.locals[prop];
            }
          }
 
          var renderPromise = render.length < 2 ?
            Promise.resolve(render(locals)) :
            Promise.fromNode(render.bind(null, locals));
 
          return renderPromise
            .then(function(output) {
              compilation.assets[outputFileName] = new RawSource(output);
            })
            .catch(function(err) {
              compilation.errors.push(err.stack);
            });
        });
 
        Promise.all(renderPromises).nodeify(done);
      } catch (err) {
        compilation.errors.push(err.stack);
        done();
      }
    });
  });
};
 
var findAsset = function(src, compilation, webpackStatsJson) {
  if (!src) {
    var chunkNames = Object.keys(webpackStatsJson.assetsByChunkName);
 
    src = chunkNames[0];
  }
 
  var asset = compilation.assets[src];
 
  if (asset) {
    return asset;
  }
 
  var chunkValue = webpackStatsJson.assetsByChunkName[src];
 
  if (!chunkValue) {
    return null;
  }
  // Webpack outputs an array for each chunk when using sourcemaps
  if (chunkValue instanceof Array) {
    // Is the main bundle always the first element?
    chunkValue = chunkValue[0];
  }
  return compilation.assets[chunkValue];
};
 
// Shamelessly stolen from html-webpack-plugin - Thanks @ampedandwired :)
var getAssetsFromCompilation = function(compilation, webpackStatsJson) {
  var assets = {};
  for (var chunk in webpackStatsJson.assetsByChunkName) {
    var chunkValue = webpackStatsJson.assetsByChunkName[chunk];
 
    // Webpack outputs an array for each chunk when using sourcemaps
    if (chunkValue instanceof Array) {
      // Is the main bundle always the first element?
      chunkValue = chunkValue[0];
    }
 
    if (compilation.options.output.publicPath) {
      chunkValue = compilation.options.output.publicPath + chunkValue;
    }
    assets[chunk] = chunkValue;
  }
 
  return assets;
};
 
function legacyArgsToOptions(entry, paths, locals, globals) {
  return {
    entry: entry,
    paths: paths,
    locals: locals,
    globals: globals
  };
}
 
module.exports = StaticSiteGeneratorWebpackPlugin;