UNPKG

3.25 kBJavaScriptView Raw
1// @ts-check
2/** @typedef {import("../typings").HtmlTagObject} HtmlTagObject */
3/**
4 * @file
5 * This file provides to helper to create html as a object representation as
6 * those objects are easier to modify than pure string representations
7 *
8 * Usage:
9 * ```
10 * const element = createHtmlTagObject('h1', {class: 'demo'}, 'Hello World');
11 * const html = htmlTagObjectToString(element);
12 * console.log(html) // -> <h1 class="demo">Hello World</h1>
13 * ```
14 */
15
16/**
17 * All html tag elements which must not contain innerHTML
18 * @see https://www.w3.org/TR/html5/syntax.html#void-elements
19 */
20const voidTags = ['area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'keygen', 'link', 'meta', 'param', 'source', 'track', 'wbr'];
21
22/**
23 * Turn a tag definition into a html string
24 * @param {HtmlTagObject} tagDefinition
25 * A tag element according to the htmlWebpackPlugin object notation
26 *
27 * @param xhtml {boolean}
28 * Whether the generated html should add closing slashes to be xhtml compliant
29 */
30function htmlTagObjectToString (tagDefinition, xhtml) {
31 const attributes = Object.keys(tagDefinition.attributes || {})
32 .filter(function (attributeName) {
33 return tagDefinition.attributes[attributeName] === '' || tagDefinition.attributes[attributeName];
34 })
35 .map(function (attributeName) {
36 if (tagDefinition.attributes[attributeName] === true) {
37 return xhtml ? attributeName + '="' + attributeName + '"' : attributeName;
38 }
39 return attributeName + '="' + tagDefinition.attributes[attributeName] + '"';
40 });
41 return '<' + [tagDefinition.tagName].concat(attributes).join(' ') + (tagDefinition.voidTag && xhtml ? '/' : '') + '>' +
42 (tagDefinition.innerHTML || '') +
43 (tagDefinition.voidTag ? '' : '</' + tagDefinition.tagName + '>');
44}
45
46/**
47 * Static helper to create a tag object to be get injected into the dom
48 *
49 * @param {string} tagName
50 * the name of the tag e.g. 'div'
51 *
52 * @param {{[attributeName: string]: string|boolean|null|undefined}} [attributes]
53 * tag attributes e.g. `{ 'class': 'example', disabled: true }`
54 *
55 * @param {string} [innerHTML]
56 *
57 * @param {{[attributeName: string]: string|boolean|null|undefined}} [meta]
58 * meta information about the tag e.g. `{ 'plugin': 'html-webpack-plugin' }`
59 *
60 * @returns {HtmlTagObject}
61 */
62function createHtmlTagObject (tagName, attributes, innerHTML, meta) {
63 return {
64 tagName: tagName,
65 voidTag: voidTags.indexOf(tagName) !== -1,
66 attributes: attributes || {},
67 meta: meta || {},
68 innerHTML: innerHTML
69 };
70}
71
72/**
73 * The `HtmlTagArray Array with a custom `.toString()` method.
74 *
75 * This allows the following:
76 * ```
77 * const tags = HtmlTagArray.from([tag1, tag2]);
78 * const scriptTags = tags.filter((tag) => tag.tagName === 'script');
79 * const html = scriptTags.toString();
80 * ```
81 *
82 * Or inside a string literal:
83 * ```
84 * const tags = HtmlTagArray.from([tag1, tag2]);
85 * const html = `<html><body>${tags.filter((tag) => tag.tagName === 'script')}</body></html>`;
86 * ```
87 *
88 */
89class HtmlTagArray extends Array {
90 toString () {
91 return this.join('');
92 }
93}
94
95module.exports = {
96 HtmlTagArray: HtmlTagArray,
97 createHtmlTagObject: createHtmlTagObject,
98 htmlTagObjectToString: htmlTagObjectToString
99};