Skip to content

Commit ee6a165

Browse files
committedJun 3, 2018
feat(html-tags): Add a helper to create html-tags
1 parent d6b65dd commit ee6a165

File tree

2 files changed

+77
-22
lines changed

2 files changed

+77
-22
lines changed
 

‎index.js

+4-22
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ const path = require('path');
1010
const SyncWaterfallHook = require('tapable').SyncWaterfallHook;
1111
const AsyncSeriesWaterfallHook = require('tapable').AsyncSeriesWaterfallHook;
1212

13+
const htmlTagObjectToString = require('./lib/html-tags').htmlTagObjectToString;
14+
1315
const childCompiler = require('./lib/compiler.js');
1416
const prettyError = require('./lib/errors.js');
1517
const chunkSorter = require('./lib/chunksorter.js');
@@ -549,8 +551,8 @@ class HtmlWebpackPlugin {
549551
const htmlRegExp = /(<html[^>]*>)/i;
550552
const headRegExp = /(<\/head\s*>)/i;
551553
const bodyRegExp = /(<\/body\s*>)/i;
552-
const body = assetTags.body.map(this.createHtmlTag.bind(this));
553-
const head = assetTags.head.map(this.createHtmlTag.bind(this));
554+
const body = assetTags.body.map((assetTagObject) => htmlTagObjectToString(assetTagObject, this.options.xhtml));
555+
const head = assetTags.head.map((assetTagObject) => htmlTagObjectToString(assetTagObject, this.options.xhtml));
554556

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

602-
/**
603-
* Turn a tag definition into a html string
604-
*/
605-
createHtmlTag (tagDefinition) {
606-
const attributes = Object.keys(tagDefinition.attributes || {})
607-
.filter(attributeName => tagDefinition.attributes[attributeName] !== false)
608-
.map(attributeName => {
609-
if (tagDefinition.attributes[attributeName] === true) {
610-
return attributeName;
611-
}
612-
return attributeName + '="' + tagDefinition.attributes[attributeName] + '"';
613-
});
614-
// Backport of 3.x void tag definition
615-
const voidTag = tagDefinition.voidTag !== undefined ? tagDefinition.voidTag : !tagDefinition.closeTag;
616-
const selfClosingTag = tagDefinition.voidTag !== undefined ? tagDefinition.voidTag && this.options.xhtml : tagDefinition.selfClosingTag;
617-
return '<' + [tagDefinition.tagName].concat(attributes).join(' ') + (selfClosingTag ? '/' : '') + '>' +
618-
(tagDefinition.innerHTML || '') +
619-
(voidTag ? '' : '</' + tagDefinition.tagName + '>');
620-
}
621-
622604
/**
623605
* Helper to return the absolute template path with a fallback loader
624606
*/

‎lib/html-tags.js

+73
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
// @ts-check
2+
/* eslint-disable */
3+
/// <reference path="../typings.d.ts" />
4+
/* eslint-enable */
5+
/**
6+
* @file
7+
* This file provides to helper to create html as a object repesentation as
8+
* thoses objects are easier to modify than pure string representations
9+
*
10+
* Usage:
11+
* ```
12+
* const element = createHtmlTagObject('h1', {class: 'demo'}, 'Hello World');
13+
* const html = htmlTagObjectToString(element);
14+
* console.log(html) // -> <h1 class="demo">Hello World</h1>
15+
* ```
16+
*/
17+
18+
/**
19+
* All html tag elements which must not contain innerHTML
20+
* @see https://www.w3.org/TR/html5/syntax.html#void-elements
21+
*/
22+
const voidTags = ['area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'keygen', 'link', 'meta', 'param', 'source', 'track', 'wbr'];
23+
24+
/**
25+
* Turn a tag definition into a html string
26+
* @param {HtmlTagObject} tagDefinition
27+
* A tag element according to the htmlWebpackPlugin object notation
28+
*
29+
* @param xhtml {boolean}
30+
* Wether the generated html should add closing slashes to be xhtml compliant
31+
*/
32+
function htmlTagObjectToString (tagDefinition, xhtml) {
33+
const attributes = Object.keys(tagDefinition.attributes || {})
34+
.filter(function (attributeName) {
35+
return tagDefinition.attributes[attributeName] !== false;
36+
})
37+
.map(function (attributeName) {
38+
if (tagDefinition.attributes[attributeName] === true) {
39+
return xhtml ? attributeName + '="' + attributeName + '"' : attributeName;
40+
}
41+
return attributeName + '="' + tagDefinition.attributes[attributeName] + '"';
42+
});
43+
return '<' + [tagDefinition.tagName].concat(attributes).join(' ') + (tagDefinition.voidTag && xhtml ? '/' : '') + '>' +
44+
(tagDefinition.innerHTML || '') +
45+
(tagDefinition.voidTag ? '' : '</' + tagDefinition.tagName + '>');
46+
}
47+
48+
/**
49+
* Static helper to create a tag object to be get injected into the dom
50+
*
51+
* @param {string} tagName
52+
* the name of the tage e.g. 'div'
53+
*
54+
* @param {{[attributeName: string]: string|boolean}} [attributes]
55+
* tag attributes e.g. `{ 'class': 'example', disabled: true }`
56+
*
57+
* @param {string} [innerHTML]
58+
*
59+
* @returns {HtmlTagObject}
60+
*/
61+
function createHtmlTagObject (tagName, attributes, innerHTML) {
62+
return {
63+
tagName: tagName,
64+
voidTag: voidTags.indexOf(tagName) !== -1,
65+
attributes: attributes || {},
66+
innerHTML: innerHTML
67+
};
68+
}
69+
70+
module.exports = {
71+
createHtmlTagObject: createHtmlTagObject,
72+
htmlTagObjectToString: htmlTagObjectToString
73+
};

0 commit comments

Comments
 (0)
Please sign in to comment.