html-webpack-plugin
Advanced tools
Comparing version 1.3.0 to 1.4.0
174
index.js
@@ -6,2 +6,4 @@ 'use strict'; | ||
var tmpl = require('blueimp-tmpl').tmpl; | ||
var Promise = require('bluebird'); | ||
Promise.promisifyAll(fs); | ||
@@ -14,48 +16,111 @@ function HtmlWebpackPlugin(options) { | ||
var self = this; | ||
compiler.plugin('emit', function(compilation, callback) { | ||
compiler.plugin('emit', function(compilation, compileCallback) { | ||
var webpackStatsJson = compilation.getStats().toJson(); | ||
var templateParams = {}; | ||
templateParams.webpack = webpackStatsJson; | ||
templateParams.htmlWebpackPlugin = {}; | ||
templateParams.htmlWebpackPlugin.assets = self.htmlWebpackPluginLegacyAssets(compilation, webpackStatsJson); | ||
templateParams.htmlWebpackPlugin.files = self.htmlWebpackPluginAssets(compilation, webpackStatsJson, self.options.chunks, self.options.excludeChunks); | ||
templateParams.htmlWebpackPlugin.options = self.options; | ||
templateParams.webpackConfig = compilation.options; | ||
var outputFilename = self.options.filename || 'index.html'; | ||
Promise.resolve() | ||
// Add the favicon | ||
.then(function(callback) { | ||
if (self.options.favicon) { | ||
return self.addFileToAssets(compilation, self.options.favicon, callback); | ||
} | ||
}) | ||
// Generate the html | ||
.then(function() { | ||
var templateParams = { | ||
webpack: webpackStatsJson, | ||
webpackConfig: compilation.options, | ||
htmlWebpackPlugin: { | ||
files: self.htmlWebpackPluginAssets(compilation, webpackStatsJson, self.options.chunks, self.options.excludeChunks), | ||
options: self.options, | ||
} | ||
}; | ||
// Deprecate templateParams.htmlWebpackPlugin.assets | ||
var assets = self.htmlWebpackPluginLegacyAssets(compilation, webpackStatsJson); | ||
Object.defineProperty(templateParams.htmlWebpackPlugin, 'assets', { | ||
get: function() { | ||
compilation.errors.push('htmlWebpackPlugin.assets is deprecated - please use htmlWebpackPlugin.files instead'); | ||
return assets; | ||
} | ||
}); | ||
if (self.options.templateContent && self.options.template) { | ||
compilation.errors.push(new Error('HtmlWebpackPlugin: cannot specify both template and templateContent options')); | ||
callback(); | ||
} else if (self.options.templateContent) { | ||
var templateContent = typeof self.options.templateContent === 'function' ? self.options.templateContent(templateParams, compiler) : self.options.templateContent; | ||
self.emitHtml(compilation, templateContent, templateParams, outputFilename); | ||
callback(); | ||
} else { | ||
var templateFile = self.options.template; | ||
if (!templateFile) { | ||
// Use a special index file to prevent double script / style injection if the `inject` option is truthy | ||
templateFile = path.join(__dirname, self.options.inject ? 'default_inject_index.html' : 'default_index.html'); | ||
} | ||
compilation.fileDependencies.push(templateFile); | ||
fs.readFile(templateFile, 'utf8', function(err, htmlTemplateContent) { | ||
if (err) { | ||
compilation.errors.push(new Error('HtmlWebpackPlugin: Unable to read HTML template "' + templateFile + '"')); | ||
} else { | ||
self.emitHtml(compilation, htmlTemplateContent, templateParams, outputFilename); | ||
} | ||
callback(); | ||
}); | ||
} | ||
// Get/generate html | ||
return self.getTemplateContent(compilation, templateParams) | ||
.then(function(htmlTemplateContent) { | ||
// Compile and add html to compilation | ||
return self.emitHtml(compilation, htmlTemplateContent, templateParams, outputFilename); | ||
}); | ||
}) | ||
// In case anything went wrong let the user know | ||
.catch(function(err) { | ||
compilation.errors.push(err); | ||
compilation.assets[outputFilename] = { | ||
source: function() { | ||
return err.toString(); | ||
}, | ||
size: function() { | ||
return err.toString().length; | ||
} | ||
}; | ||
}) | ||
// Tell the compiler to proceed | ||
.finally(compileCallback); | ||
}); | ||
}; | ||
/** | ||
* Retrieves the html source depending on `this.options`. | ||
* Supports: | ||
* + options.fileContent as string | ||
* + options.fileContent as sync function | ||
* + options.fileContent as async function | ||
* + options.template as template path | ||
* Returns a Promise | ||
*/ | ||
HtmlWebpackPlugin.prototype.getTemplateContent = function(compilation, templateParams) { | ||
var self = this; | ||
// If config is invalid | ||
if (self.options.templateContent && self.options.template) { | ||
return Promise.reject(new Error('HtmlWebpackPlugin: cannot specify both template and templateContent options')); | ||
} | ||
// If a function is passed | ||
if (typeof self.options.templateContent === 'function') { | ||
return Promise.fromNode(function(callback) { | ||
// allow to specify a sync or an async function to generate the template content | ||
var result = self.options.templateContent(templateParams, compilation, callback); | ||
// if it return a result expect it to be sync | ||
if (result !== undefined) { | ||
callback(null, result); | ||
} | ||
}); | ||
} | ||
// If a string is passed | ||
if (self.options.templateContent) { | ||
return Promise.resolve(self.options.templateContent); | ||
} | ||
// If templateContent is empty use the tempalte option | ||
var templateFile = self.options.template; | ||
if (!templateFile) { | ||
// Use a special index file to prevent double script / style injection if the `inject` option is truthy | ||
templateFile = path.join(__dirname, self.options.inject ? 'default_inject_index.html' : 'default_index.html'); | ||
} | ||
compilation.fileDependencies.push(templateFile); | ||
return fs.readFileAsync(templateFile, 'utf8') | ||
// If the file could not be read log a error | ||
.catch(function() { | ||
return Promise.reject(new Error('HtmlWebpackPlugin: Unable to read HTML template "' + templateFile + '"')); | ||
}); | ||
}; | ||
/* | ||
* Compile the html template and push the result to the compilation assets | ||
*/ | ||
HtmlWebpackPlugin.prototype.emitHtml = function(compilation, htmlTemplateContent, templateParams, outputFilename) { | ||
var html; | ||
// blueimp-tmpl processing | ||
try { | ||
html = tmpl(htmlTemplateContent, templateParams); | ||
html = tmpl(htmlTemplateContent, templateParams); | ||
} catch(e) { | ||
compilation.errors.push(new Error('HtmlWebpackPlugin: template error ' + e)); | ||
return Promise.reject(new Error('HtmlWebpackPlugin: template error ' + e)); | ||
} | ||
// Inject link and script elements into an existing html file | ||
@@ -65,2 +130,11 @@ if (this.options.inject) { | ||
} | ||
// Minify the html output | ||
if (this.options.minify) { | ||
var minify = require('html-minifier').minify; | ||
// If `options.minify` is set to true use the default minify options | ||
var minifyOptions = _.isObject(this.options.minify) ? this.options.minify : {}; | ||
html = minify(html, minifyOptions); | ||
} | ||
compilation.assets[outputFilename] = { | ||
@@ -76,2 +150,25 @@ source: function() { | ||
/* | ||
* Pushes the content of the given filename to the compilation assets | ||
*/ | ||
HtmlWebpackPlugin.prototype.addFileToAssets = function(compilation, filename) { | ||
return Promise.props({ | ||
size: fs.statAsync(filename), | ||
source: fs.readFileAsync(filename) | ||
}) | ||
.catch(function() { | ||
return Promise.reject(new Error('HtmlWebpackPlugin: could not load file ' + filename)); | ||
}) | ||
.then(function(results) { | ||
compilation.fileDependencies.push(filename); | ||
compilation.assets[path.basename(filename)] = { | ||
source: function() { | ||
return results.source; | ||
}, | ||
size: function() { | ||
return results.size; | ||
} | ||
}; | ||
}); | ||
}; | ||
@@ -89,2 +186,4 @@ HtmlWebpackPlugin.prototype.htmlWebpackPluginAssets = function(compilation, webpackStatsJson, includedChunks, excludedChunks) { | ||
css: [], | ||
// Will contain the path to the favicon if it exists | ||
favicon: self.options.favicon ? publicPath + path.basename(self.options.favicon): undefined, | ||
// Will contain the html5 appcache manifest files if it exists | ||
@@ -99,2 +198,3 @@ manifest: Object.keys(compilation.assets).filter(function(assetFile){ | ||
assets.manifest = self.appendHash(assets.manifest, webpackStatsJson.hash); | ||
assets.favicon = self.appendHash(assets.favicon, webpackStatsJson.hash); | ||
} | ||
@@ -182,2 +282,6 @@ | ||
}); | ||
// If there is a favicon present, add it above any link-tags | ||
if (assets.favicon) { | ||
styles.unshift('<link rel="shortcut icon" href="' + assets.favicon + '">'); | ||
} | ||
// Append scripts to body element | ||
@@ -184,0 +288,0 @@ html = html.replace(/(<\/body>)/i, function (match) { |
{ | ||
"name": "html-webpack-plugin", | ||
"version": "1.3.0", | ||
"version": "1.4.0", | ||
"description": "Simplifies creation of HTML files to serve your webpack bundles", | ||
"main": "index.js", | ||
"files": [ | ||
"index.js", | ||
"default_index.html", | ||
"default_inject_index.html" | ||
], | ||
"scripts": { | ||
@@ -26,11 +31,18 @@ "test": "jshint -c .jshintrc *.js spec && jasmine-node --captureExceptions spec" | ||
"devDependencies": { | ||
"css-loader": "^0.12.0", | ||
"extract-text-webpack-plugin": "^0.7.1", | ||
"file-loader": "^0.8.1", | ||
"jasmine-node": "^1.14.5", | ||
"jshint": "^2.5.2", | ||
"rimraf": "^2.2.8", | ||
"webpack": "^1.3.3-beta1" | ||
"jshint": "^2.7.0", | ||
"rimraf": "^2.3.3", | ||
"style-loader": "^0.12.2", | ||
"url-loader": "^0.5.5", | ||
"webpack": "^1.8.11" | ||
}, | ||
"dependencies": { | ||
"bluebird": "^2.9.25", | ||
"blueimp-tmpl": "~2.5.4", | ||
"lodash": "~3.6.0" | ||
"html-minifier": "^0.7.2", | ||
"lodash": "~3.8.0" | ||
} | ||
} |
@@ -57,3 +57,2 @@ HTML Webpack Plugin [![bitHound Score](https://www.bithound.io/github/ampedandwired/html-webpack-plugin/badges/score.svg)](https://www.bithound.io/github/ampedandwired/html-webpack-plugin) [![Dependency Status](https://david-dm.org/ampedandwired/html-webpack-plugin.svg)](https://david-dm.org/ampedandwired/html-webpack-plugin) | ||
Configuration | ||
@@ -67,2 +66,7 @@ ------------- | ||
You can specify a subdirectory here too (eg: `assets/admin.html`). | ||
- `template`: A html template (supports [blueimp templates](https://github.com/blueimp/JavaScript-Templates)). | ||
- `templateContent`: A html string or a function returning the html (supports [blueimp templates](https://github.com/blueimp/JavaScript-Templates)). | ||
- `inject`: Inject all assets into the given `template` or `templateContent`. | ||
- `favicon`: Adds the given favicon path to the output html. | ||
- `minify`: Set to true or pass a [html-minifier](https://github.com/kangax/html-minifier#options-quick-reference) options object to minify the output. | ||
- `hash`: if `true` then append a unique webpack compilation hash to all | ||
@@ -113,8 +117,15 @@ included scripts and css files. This is useful for cache busting. | ||
If the default generated HTML doesn't meet your needs you can supply | ||
your own [blueimp template](https://github.com/blueimp/JavaScript-Templates). | ||
The [default template](https://github.com/ampedandwired/html-webpack-plugin/blob/master/default_index.html) | ||
is a good starting point for writing your own. | ||
your own template. The easiest way is to use the `inject` option and pass a custom html file. | ||
The html-webpack-plugin will automatically inject all necessary css, js, manifest | ||
and favicon files into the markup. | ||
Let's say for example you wanted to put a webpack bundle into the head of your | ||
HTML as well as the body. Your template might look like this: | ||
```javascript | ||
plugins: [ | ||
new HtmlWebpackPlugin({ | ||
inject: true, | ||
template: 'my-index.html' | ||
}) | ||
] | ||
``` | ||
```html | ||
@@ -126,6 +137,4 @@ <!DOCTYPE html> | ||
<title>My App</title> | ||
<script src="{%=o.htmlWebpackPlugin.files.chunks.head.entry%}"></script> | ||
</head> | ||
<body> | ||
<script src="{%=o.htmlWebpackPlugin.files.chunks.main.entry%}"></script> | ||
</body> | ||
@@ -135,18 +144,2 @@ </html> | ||
To use this template, configure the plugin like this: | ||
```javascript | ||
{ | ||
entry: 'index.js', | ||
output: { | ||
path: 'dist', | ||
filename: 'index_bundle.js' | ||
}, | ||
plugins: [ | ||
new HtmlWebpackPlugin({ | ||
template: 'src/assets/my_template.html' | ||
}) | ||
] | ||
} | ||
``` | ||
Alternatively, if you already have your template's content in a String, you | ||
@@ -157,2 +150,3 @@ can pass it to the plugin using the `templateContent` option: | ||
new HtmlWebpackPlugin({ | ||
inject: true, | ||
templateContent: templateContentString | ||
@@ -163,2 +157,6 @@ }) | ||
You can use the [blueimp template](https://github.com/blueimp/JavaScript-Templates) syntax out of the box. | ||
If the `inject` feature doesn't fit your needs and you want full control over the asset placement use the [default template](https://github.com/ampedandwired/html-webpack-plugin/blob/master/default_index.html) | ||
as a starting point for writing your own. | ||
The `templateContent` option can also be a function to use another template language like jade: | ||
@@ -168,4 +166,5 @@ ```javascript | ||
new HtmlWebpackPlugin({ | ||
templateContent: function(templateParams, webpackCompiler) { | ||
templateContent: function(templateParams, compilation) { | ||
// Return your template content synchronously here | ||
return '..'; | ||
} | ||
@@ -175,2 +174,13 @@ }) | ||
``` | ||
Or the async version: | ||
```javascript | ||
plugins: [ | ||
new HtmlWebpackPlugin({ | ||
templateContent: function(templateParams, compilation, callback) { | ||
// Return your template content asynchronously here | ||
callback(null, '..'); | ||
} | ||
}) | ||
] | ||
``` | ||
@@ -177,0 +187,0 @@ Note the plugin will throw an error if you specify both `template` _and_ |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
244
1
20705
4
9
5
296
1
+ Addedbluebird@^2.9.25
+ Addedhtml-minifier@^0.7.2
+ Addedamdefine@1.0.1(transitive)
+ Addedasync@0.2.10(transitive)
+ Addedbluebird@2.11.0(transitive)
+ Addedcamel-case@1.2.2(transitive)
+ Addedcamelcase@1.2.1(transitive)
+ Addedchange-case@2.3.1(transitive)
+ Addedclean-css@3.1.9(transitive)
+ Addedcli@0.6.6(transitive)
+ Addedcommander@2.6.0(transitive)
+ Addedconcat-stream@1.4.11(transitive)
+ Addedconstant-case@1.1.2(transitive)
+ Addedcore-util-is@1.0.3(transitive)
+ Addeddecamelize@1.2.0(transitive)
+ Addeddot-case@1.1.2(transitive)
+ Addedexit@0.1.2(transitive)
+ Addedglob@3.2.11(transitive)
+ Addedhtml-minifier@0.7.2(transitive)
+ Addedinherits@2.0.4(transitive)
+ Addedis-lower-case@1.1.3(transitive)
+ Addedis-upper-case@1.1.2(transitive)
+ Addedisarray@0.0.1(transitive)
+ Addedlodash@3.8.0(transitive)
+ Addedlower-case@1.1.4(transitive)
+ Addedlower-case-first@1.0.2(transitive)
+ Addedlru-cache@2.7.3(transitive)
+ Addedminimatch@0.3.0(transitive)
+ Addedparam-case@1.1.2(transitive)
+ Addedpascal-case@1.1.2(transitive)
+ Addedpath-case@1.1.2(transitive)
+ Addedreadable-stream@1.1.14(transitive)
+ Addedrelateurl@0.2.7(transitive)
+ Addedsentence-case@1.1.3(transitive)
+ Addedsigmund@1.0.1(transitive)
+ Addedsnake-case@1.1.2(transitive)
+ Addedsource-map@0.1.340.1.43(transitive)
+ Addedstring_decoder@0.10.31(transitive)
+ Addedswap-case@1.1.2(transitive)
+ Addedtitle-case@1.1.2(transitive)
+ Addedtypedarray@0.0.7(transitive)
+ Addeduglify-js@2.4.24(transitive)
+ Addeduglify-to-browserify@1.0.2(transitive)
+ Addedupper-case@1.1.3(transitive)
+ Addedupper-case-first@1.1.2(transitive)
+ Addedwindow-size@0.1.0(transitive)
+ Addedwordwrap@0.0.2(transitive)
+ Addedyargs@3.5.4(transitive)
- Removedlodash@3.6.0(transitive)
Updatedlodash@~3.8.0