Skip to content

Commit

Permalink
feat(html-tags): Add a helper to create html-tags
Browse files Browse the repository at this point in the history
  • Loading branch information
jantimon committed Jun 3, 2018
1 parent d6b65dd commit ee6a165
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 22 deletions.
26 changes: 4 additions & 22 deletions index.js
Expand Up @@ -10,6 +10,8 @@ const path = require('path');
const SyncWaterfallHook = require('tapable').SyncWaterfallHook;
const AsyncSeriesWaterfallHook = require('tapable').AsyncSeriesWaterfallHook;

const htmlTagObjectToString = require('./lib/html-tags').htmlTagObjectToString;

const childCompiler = require('./lib/compiler.js');
const prettyError = require('./lib/errors.js');
const chunkSorter = require('./lib/chunksorter.js');
Expand Down Expand Up @@ -549,8 +551,8 @@ class HtmlWebpackPlugin {
const htmlRegExp = /(<html[^>]*>)/i;
const headRegExp = /(<\/head\s*>)/i;
const bodyRegExp = /(<\/body\s*>)/i;
const body = assetTags.body.map(this.createHtmlTag.bind(this));
const head = assetTags.head.map(this.createHtmlTag.bind(this));
const body = assetTags.body.map((assetTagObject) => htmlTagObjectToString(assetTagObject, this.options.xhtml));
const head = assetTags.head.map((assetTagObject) => htmlTagObjectToString(assetTagObject, this.options.xhtml));

if (body.length) {
if (bodyRegExp.test(html)) {
Expand Down Expand Up @@ -599,26 +601,6 @@ class HtmlWebpackPlugin {
return url + (url.indexOf('?') === -1 ? '?' : '&') + hash;
}

/**
* Turn a tag definition into a html string
*/
createHtmlTag (tagDefinition) {
const attributes = Object.keys(tagDefinition.attributes || {})
.filter(attributeName => tagDefinition.attributes[attributeName] !== false)
.map(attributeName => {
if (tagDefinition.attributes[attributeName] === true) {
return attributeName;
}
return attributeName + '="' + tagDefinition.attributes[attributeName] + '"';
});
// Backport of 3.x void tag definition
const voidTag = tagDefinition.voidTag !== undefined ? tagDefinition.voidTag : !tagDefinition.closeTag;
const selfClosingTag = tagDefinition.voidTag !== undefined ? tagDefinition.voidTag && this.options.xhtml : tagDefinition.selfClosingTag;
return '<' + [tagDefinition.tagName].concat(attributes).join(' ') + (selfClosingTag ? '/' : '') + '>' +
(tagDefinition.innerHTML || '') +
(voidTag ? '' : '</' + tagDefinition.tagName + '>');
}

/**
* Helper to return the absolute template path with a fallback loader
*/
Expand Down
73 changes: 73 additions & 0 deletions lib/html-tags.js
@@ -0,0 +1,73 @@
// @ts-check
/* eslint-disable */
/// <reference path="../typings.d.ts" />
/* eslint-enable */
/**
* @file
* This file provides to helper to create html as a object repesentation as
* thoses objects are easier to modify than pure string representations
*
* Usage:
* ```
* const element = createHtmlTagObject('h1', {class: 'demo'}, 'Hello World');
* const html = htmlTagObjectToString(element);
* console.log(html) // -> <h1 class="demo">Hello World</h1>
* ```
*/

/**
* All html tag elements which must not contain innerHTML
* @see https://www.w3.org/TR/html5/syntax.html#void-elements
*/
const voidTags = ['area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'keygen', 'link', 'meta', 'param', 'source', 'track', 'wbr'];

/**
* Turn a tag definition into a html string
* @param {HtmlTagObject} tagDefinition
* A tag element according to the htmlWebpackPlugin object notation
*
* @param xhtml {boolean}
* Wether the generated html should add closing slashes to be xhtml compliant
*/
function htmlTagObjectToString (tagDefinition, xhtml) {
const 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 {{[attributeName: string]: string|boolean}} [attributes]
* tag attributes e.g. `{ 'class': 'example', disabled: true }`
*
* @param {string} [innerHTML]
*
* @returns {HtmlTagObject}
*/
function createHtmlTagObject (tagName, attributes, innerHTML) {
return {
tagName: tagName,
voidTag: voidTags.indexOf(tagName) !== -1,
attributes: attributes || {},
innerHTML: innerHTML
};
}

module.exports = {
createHtmlTagObject: createHtmlTagObject,
htmlTagObjectToString: htmlTagObjectToString
};

0 comments on commit ee6a165

Please sign in to comment.