From b4363a85757a07fe23264af2a445338bf45aa24b Mon Sep 17 00:00:00 2001 From: Jan Nicklas Date: Thu, 7 Jan 2016 11:14:23 +0100 Subject: [PATCH] Add events `html-webpack-plugin-before-html-processing`, `html-webpack-plugin-after-html-processing`, `html-webpack-plugin-after-emit` --- README.md | 17 ++++ index.js | 39 ++++++--- package.json | 2 +- spec/HtmlWebpackPluginSpec.js | 153 ++++++++++++++++++++++++++++++++++ 4 files changed, 198 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 7c832fe..01db6f0 100644 --- a/README.md +++ b/README.md @@ -263,3 +263,20 @@ plugins: [ ] ``` +Events +------ + +To allow other plugins to alter the html this plugin executes the following events: + + * `html-webpack-plugin-before-html-processing` + * `html-webpack-plugin-after-html-processing` + * `html-webpack-plugin-after-emit` + +Usage: + +``` + compilation.plugin('html-webpack-plugin-before-html-processing', function(htmlPluginData, callback) { + htmlPluginData.html += 'The magic footer'; + callback(); + }); +``` diff --git a/index.js b/index.js index 5859453..b45cb94 100644 --- a/index.js +++ b/index.js @@ -97,10 +97,30 @@ HtmlWebpackPlugin.prototype.apply = function(compiler) { return typeof compilationResult !== 'function' ? compilationResult : self.executeTemplate(compilationResult, chunks, assets, compilation); }) + // Allow plugins to change the html before assets are injected + .then(function(html) { + return new Promise(function(resolve){ + var pluginArgs = {html: html, assets: assets, plugin: self}; + compilation.applyPluginsAsyncWaterfall('html-webpack-plugin-before-html-processing', pluginArgs, + function() { + resolve(pluginArgs.html); + }); + }); + }) .then(function(html) { // Add the stylesheets, scripts and so on to the resulting html return self.postProcessHtml(html, assets); }) + // Allow plugins to change the html after assets are injected + .then(function(html) { + return new Promise(function(resolve){ + var pluginArgs = {html: html, assets: assets, plugin: self}; + compilation.applyPluginsAsyncWaterfall('html-webpack-plugin-after-html-processing', pluginArgs, + function() { + resolve(pluginArgs.html); + }); + }); + }) .catch(function(err) { // In case anything went wrong the promise is resolved // with the error message and an error is logged @@ -118,7 +138,11 @@ HtmlWebpackPlugin.prototype.apply = function(compiler) { return html.length; } }; - callback(); + // Let other plugins know that we are done: + compilation.applyPluginsAsyncWaterfall('html-webpack-plugin-after-emit', { + html: compilation.assets[self.options.filename], + plugin: self + }, callback); }); }); }; @@ -424,21 +448,12 @@ HtmlWebpackPlugin.prototype.htmlWebpackPluginAssets = function(compilation, chun * Injects the assets into the given html string */ HtmlWebpackPlugin.prototype.injectAssetsIntoHtml = function(html, assets) { - var chunks = Object.keys(assets.chunks); - - // Gather all css and script files - var styles = []; - var scripts = []; - chunks.forEach(function(chunkName) { - styles = styles.concat(assets.chunks[chunkName].css); - scripts.push(assets.chunks[chunkName].entry); - }); // Turn script files into script tags - scripts = scripts.map(function(scriptPath) { + var scripts = assets.js.map(function(scriptPath) { return ''; }); // Turn css files into link tags - styles = styles.map(function(stylePath) { + var styles = assets.css.map(function(stylePath) { return ''; }); // Injections diff --git a/package.json b/package.json index b55940e..4d39900 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "html-webpack-plugin", - "version": "2.2.0", + "version": "2.3.0", "description": "Simplifies creation of HTML files to serve your webpack bundles", "main": "index.js", "files": [ diff --git a/spec/HtmlWebpackPluginSpec.js b/spec/HtmlWebpackPluginSpec.js index 95e728f..326750f 100644 --- a/spec/HtmlWebpackPluginSpec.js +++ b/spec/HtmlWebpackPluginSpec.js @@ -551,6 +551,159 @@ describe('HtmlWebpackPlugin', function() { ['Public path is https://cdn.com'], null, done); }); + it('fires the html-webpack-plugin-before-html-processing event', function(done) { + var eventFired = false; + var examplePlugin = { + apply: function(compiler) { + compiler.plugin('compilation', function(compilation) { + compilation.plugin('html-webpack-plugin-before-html-processing', function(object, callback) { + eventFired = true; + callback(); + }); + }); + } + }; + testHtmlPlugin({ + entry: { + app: path.join(__dirname, 'fixtures/index.js') + }, + output: { + path: OUTPUT_DIR, + filename: '[name]_bundle.js' + }, + plugins: [ + new HtmlWebpackPlugin(), + examplePlugin + ] + },[], null, function() { + expect(eventFired).toBe(true); + done(); + }); + }); + + it('fires the html-webpack-plugin-after-html-processing event', function(done) { + var eventFired = false; + var examplePlugin = { + apply: function(compiler) { + compiler.plugin('compilation', function(compilation) { + compilation.plugin('html-webpack-plugin-after-html-processing', function(object, callback) { + eventFired = true; + callback(); + }); + }); + } + }; + testHtmlPlugin({ + entry: { + app: path.join(__dirname, 'fixtures/index.js') + }, + output: { + path: OUTPUT_DIR, + filename: '[name]_bundle.js' + }, + plugins: [ + new HtmlWebpackPlugin(), + examplePlugin + ] + },[], null, function() { + expect(eventFired).toBe(true); + done(); + }); + }); + + it('fires the html-webpack-plugin-after-emit event', function(done) { + var eventFired = false; + var examplePlugin = { + apply: function(compiler) { + compiler.plugin('compilation', function(compilation) { + compilation.plugin('html-webpack-plugin-after-emit', function(object, callback) { + eventFired = true; + callback(); + }); + }); + } + }; + testHtmlPlugin({ + entry: { + app: path.join(__dirname, 'fixtures/index.js') + }, + output: { + path: OUTPUT_DIR, + filename: '[name]_bundle.js' + }, + plugins: [ + new HtmlWebpackPlugin(), + examplePlugin + ] + },[], null, function() { + expect(eventFired).toBe(true); + done(); + }); + }); + + it('allows to modify the html during html-webpack-plugin-after-html-processing event', function(done) { + var eventFired = false; + var examplePlugin = { + apply: function(compiler) { + compiler.plugin('compilation', function(compilation) { + compilation.plugin('html-webpack-plugin-after-html-processing', function(object, callback) { + eventFired = true; + object.html += 'Injected by plugin'; + callback(); + }); + }); + } + }; + testHtmlPlugin({ + entry: { + app: path.join(__dirname, 'fixtures/index.js') + }, + output: { + path: OUTPUT_DIR, + filename: '[name]_bundle.js' + }, + plugins: [ + new HtmlWebpackPlugin(), + examplePlugin + ] + },['Injected by plugin'], null, function() { + expect(eventFired).toBe(true); + done(); + }); + }); + + it('allows to modify the html during html-webpack-plugin-before-html-processing event', function(done) { + var eventFired = false; + var examplePlugin = { + apply: function(compiler) { + compiler.plugin('compilation', function(compilation) { + compilation.plugin('html-webpack-plugin-before-html-processing', function(object, callback) { + eventFired = true; + object.assets.js.push('funky-script.js'); + object.html += 'Injected by plugin'; + callback(); + }); + }); + } + }; + testHtmlPlugin({ + entry: { + app: path.join(__dirname, 'fixtures/index.js') + }, + output: { + path: OUTPUT_DIR, + filename: '[name]_bundle.js' + }, + plugins: [ + new HtmlWebpackPlugin(), + examplePlugin + ] + },['Injected by plugin', '