Rename `closingTag` into `voidTag` like in the official w3c spec.

Provide a `createHtmlTagObject` helper for plugin authors to create new tags.
This commit is contained in:
Jan Nicklas 2017-01-29 13:42:52 +01:00
parent 2f4c88355c
commit 0a7d2244f4
5 changed files with 74 additions and 49 deletions

1
.node-version Normal file
View File

@ -0,0 +1 @@
4.3.2

View File

@ -1,6 +1,11 @@
Change History
==============
v3.x
---
* Rename `closingTag` into `voidTag` like in the official w3c spec.
* Provide a `createHtmlTagObject` helper for plugin authors to create new tags.
v2.26.0
---
* Allow plugins to add attributes without values to the `<script>` and `<link>` tags

View File

@ -30,7 +30,7 @@ There are already some really powerful plugins which can be integrated with zero
* [html-webpack-harddisk-plugin](https://github.com/jantimon/html-webpack-harddisk-plugin)
* [html-webpack-inline-source-plugin](https://github.com/DustinJackson/html-webpack-inline-source-plugin) to inline your assets in the resulting HTML file
* [html-webpack-exclude-assets-plugin](https://github.com/jamesjieye/html-webpack-exclude-assets-plugin) for excluding assets using regular expressions
Basic Usage
-----------
@ -79,7 +79,7 @@ Allowed values are as follows:
- `title`: The title to use for the generated HTML document.
- `filename`: The file to write the HTML to. Defaults to `index.html`.
You can specify a subdirectory here too (eg: `assets/admin.html`).
- `template`: Webpack require path to the template. Please see the [docs](https://github.com/ampedandwired/html-webpack-plugin/blob/master/docs/template-option.md) for details.
- `template`: Webpack require path to the template. Please see the [docs](https://github.com/ampedandwired/html-webpack-plugin/blob/master/docs/template-option.md) for details.
- `inject`: `true | 'head' | 'body' | false` Inject all assets into the given `template` or `templateContent` - When passing `true` or `'body'` all javascript resources will be placed at the bottom of the body element. `'head'` will place the scripts in the head element.
- `favicon`: Adds the given favicon path to the output html.
- `minify`: `{...} | false` Pass a [html-minifier](https://github.com/kangax/html-minifier#options-quick-reference) options object to minify the output.
@ -307,6 +307,7 @@ Note that the callback must be passed the htmlPluginData in order to pass this o
You're free to contribute to this project by submitting [issues](https://github.com/ampedandwired/html-webpack-plugin/issues) and/or [pull requests](https://github.com/ampedandwired/html-webpack-plugin/pulls). This project is test-driven, so keep in mind that every change and new feature should be covered by tests.
This project uses the [semistandard code style](https://github.com/Flet/semistandard).
This plugin follows the webpack teams decision to support [node 4+](http://node.green/).
# License

View File

@ -7,6 +7,7 @@ var path = require('path');
var childCompiler = require('./lib/compiler.js');
var prettyError = require('./lib/errors.js');
var chunkSorter = require('./lib/chunksorter.js');
var htmlTag = require('./lib/html-tags.js');
Promise.promisifyAll(fs);
function HtmlWebpackPlugin (options) {
@ -466,27 +467,17 @@ HtmlWebpackPlugin.prototype.htmlWebpackPluginAssets = function (compilation, chu
HtmlWebpackPlugin.prototype.generateAssetTags = function (assets) {
// Turn script files into script tags
var scripts = assets.js.map(function (scriptPath) {
return {
tagName: 'script',
closeTag: true,
attributes: {
type: 'text/javascript',
src: scriptPath
}
};
return htmlTag.createHtmlTagObject('script', {
type: 'text/javascript',
src: scriptPath
});
});
// Make tags self-closing in case of xhtml
var selfClosingTag = !!this.options.xhtml;
// Turn css files into link tags
var styles = assets.css.map(function (stylePath) {
return {
tagName: 'link',
selfClosingTag: selfClosingTag,
attributes: {
href: stylePath,
rel: 'stylesheet'
}
};
return htmlTag.createHtmlTagObject('link', {
href: stylePath,
rel: 'stylesheet'
});
});
// Injection targets
var head = [];
@ -494,14 +485,10 @@ HtmlWebpackPlugin.prototype.generateAssetTags = function (assets) {
// If there is a favicon present, add it to the head
if (assets.favicon) {
head.push({
tagName: 'link',
selfClosingTag: selfClosingTag,
attributes: {
rel: 'shortcut icon',
href: assets.favicon
}
});
head.push(htmlTag.createHtmlTagObject('link', {
rel: 'shortcut icon',
href: assets.favicon
}));
}
// Add styles to the head
head = head.concat(styles);
@ -521,8 +508,14 @@ HtmlWebpackPlugin.prototype.injectAssetsIntoHtml = function (html, assets, asset
var htmlRegExp = /(<html[^>]*>)/i;
var headRegExp = /(<\/head>)/i;
var bodyRegExp = /(<\/body>)/i;
var body = assetTags.body.map(this.createHtmlTag);
var head = assetTags.head.map(this.createHtmlTag);
// Create the html strings for head
var head = assetTags.head.map(
(htmlTagObject) => htmlTag.htmlTagObjectToString(htmlTagObject, this.options.xhtml)
);
// Create the html strings for body
var body = assetTags.body.map(
(htmlTagObject) => htmlTag.htmlTagObjectToString(htmlTagObject, this.options.xhtml)
);
if (body.length) {
if (bodyRegExp.test(html)) {
@ -577,25 +570,6 @@ HtmlWebpackPlugin.prototype.appendHash = function (url, hash) {
return url + (url.indexOf('?') === -1 ? '?' : '&') + hash;
};
/**
* Turn a tag definition into a html string
*/
HtmlWebpackPlugin.prototype.createHtmlTag = function (tagDefinition) {
var attributes = Object.keys(tagDefinition.attributes || {})
.filter(function (attributeName) {
return tagDefinition.attributes[attributeName] !== false;
})
.map(function (attributeName) {
if (tagDefinition.attributes[attributeName] === true) {
return attributeName;
}
return attributeName + '="' + tagDefinition.attributes[attributeName] + '"';
});
return '<' + [tagDefinition.tagName].concat(attributes).join(' ') + (tagDefinition.selfClosingTag ? '/' : '') + '>' +
(tagDefinition.innerHTML || '') +
(tagDefinition.closeTag ? '</' + tagDefinition.tagName + '>' : '');
};
/**
* Helper to return the absolute template path with a fallback loader
*/

44
lib/html-tags.js Normal file
View File

@ -0,0 +1,44 @@
/**
* This file helps to work with html tags as objects which are easy to modify
* and turn into a string
*/
/**
* Turn a tag definition into a html string
*/
function htmlTagObjectToString (tagDefinition, xhtml) {
var attributes = Object.keys(tagDefinition.attributes || {})
.filter(function (attributeName) {
return tagDefinition.attributes[attributeName] !== false;
})
.map(function (attributeName) {
if (tagDefinition.attributes[attributeName] === true) {
return xhtml ? attributeName + '="' + attributeName + '"' : attributeName;
}
return attributeName + '="' + tagDefinition.attributes[attributeName] + '"';
});
return '<' + [tagDefinition.tagName].concat(attributes).join(' ') + (tagDefinition.voidTag && xhtml ? '/' : '') + '>' +
(tagDefinition.innerHTML || '') +
(tagDefinition.voidTag ? '' : '</' + tagDefinition.tagName + '>');
}
/**
* Static helper to create a tag object to be get injected into the dom
*
* @param {String} tagName - the name of the tage e.g. 'div'
* @param {Object} attributes - tag attributes e.g. `{ 'class': 'example', disabled: true }`
*/
function createHtmlTagObject (tagName, attributes) {
// https://www.w3.org/TR/html5/syntax.html#void-elements
var voidTags = ['area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'keygen', 'link', 'meta', 'param', 'source', 'track', 'wbr'];
return {
tagName: tagName,
voidTag: voidTags.indexOf(tagName) !== -1,
attributes: attributes
};
}
module.exports = {
createHtmlTagObject: createHtmlTagObject,
htmlTagObjectToString: htmlTagObjectToString
};