Skip to content

Commit 34d8aa5

Browse files
committedJul 23, 2019
feat: add .toString implementation to htmlTags to allow easier rendering
1 parent 075473d commit 34d8aa5

File tree

12 files changed

+206
-11
lines changed

12 files changed

+206
-11
lines changed
 

‎README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -144,8 +144,8 @@ Allowed values are as follows
144144
|**`title`**|`{String}`|`Webpack App`|The title to use for the generated HTML document|
145145
|**`filename`**|`{String}`|`'index.html'`|The file to write the HTML to. Defaults to `index.html`. You can specify a subdirectory here too (eg: `assets/admin.html`)|
146146
|**`template`**|`{String}`|``|`webpack` relative or absolute path to the template. By default it will use `src/index.ejs` if it exists. Please see the [docs](https://github.com/jantimon/html-webpack-plugin/blob/master/docs/template-option.md) for details|
147-
|**`templateParameters`**|`{Boolean\|Object\|Function}`|``| Allows to overwrite the parameters used in the template |
148-
|**`inject`**|`{Boolean\|String}`|`true`|`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|
147+
|**`templateParameters`**|`{Boolean\|Object\|Function}`|``| Allows to overwrite the parameters used in the template - see [example](https://github.com/jantimon/html-webpack-plugin/tree/master/examples/template-parameters) |
148+
|**`inject`**|`{Boolean\|String}`|`true`|`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 - see the [inject:false example](https://github.com/jantimon/html-webpack-plugin/tree/master/examples/custom-insertion-position)|
149149
|**`favicon`**|`{String}`|``|Adds the given favicon path to the output HTML|
150150
|**`meta`**|`{Object}`|`{}`|Allows to inject `meta`-tags. E.g. `meta: {viewport: 'width=device-width, initial-scale=1, shrink-to-fit=no'}`|
151151
|**`base`**|`{Object\|String\|false}`|`false`|Inject a [`base`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base) tag. E.g. `base: "https://example.com/path/page.html`|

‎examples/README.md

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ Example | Link | Description
77
Appcache | [appcache](./appcache)
88
Chunk Optimization | [chunk-optimization](./chunk-optimization)
99
Custom Template | [custom-template](./custom-template)
10+
Custom Script / Link tag position | [custom-insertion-point](./custom-insertion-point)
1011
Default | [default](./default)
1112
Favicon | [favicon](.\/favicon.)
1213
Html Loader | [html-loader](./.html-loader)

‎examples/chunk-optimization/dist/webpack-4/entryA.js

+1
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
/******/ result = __webpack_require__(__webpack_require__.s = deferredModule[0]);
4747
/******/ }
4848
/******/ }
49+
/******/
4950
/******/ return result;
5051
/******/ }
5152
/******/

‎examples/chunk-optimization/dist/webpack-4/entryB.js

+1
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
/******/ result = __webpack_require__(__webpack_require__.s = deferredModule[0]);
4747
/******/ }
4848
/******/ }
49+
/******/
4950
/******/ return result;
5051
/******/ }
5152
/******/
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
/******/ (function(modules) { // webpackBootstrap
2+
/******/ // The module cache
3+
/******/ var installedModules = {};
4+
/******/
5+
/******/ // The require function
6+
/******/ function __webpack_require__(moduleId) {
7+
/******/
8+
/******/ // Check if module is in cache
9+
/******/ if(installedModules[moduleId]) {
10+
/******/ return installedModules[moduleId].exports;
11+
/******/ }
12+
/******/ // Create a new module (and put it into the cache)
13+
/******/ var module = installedModules[moduleId] = {
14+
/******/ i: moduleId,
15+
/******/ l: false,
16+
/******/ exports: {}
17+
/******/ };
18+
/******/
19+
/******/ // Execute the module function
20+
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
21+
/******/
22+
/******/ // Flag the module as loaded
23+
/******/ module.l = true;
24+
/******/
25+
/******/ // Return the exports of the module
26+
/******/ return module.exports;
27+
/******/ }
28+
/******/
29+
/******/
30+
/******/ // expose the modules object (__webpack_modules__)
31+
/******/ __webpack_require__.m = modules;
32+
/******/
33+
/******/ // expose the module cache
34+
/******/ __webpack_require__.c = installedModules;
35+
/******/
36+
/******/ // define getter function for harmony exports
37+
/******/ __webpack_require__.d = function(exports, name, getter) {
38+
/******/ if(!__webpack_require__.o(exports, name)) {
39+
/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
40+
/******/ }
41+
/******/ };
42+
/******/
43+
/******/ // define __esModule on exports
44+
/******/ __webpack_require__.r = function(exports) {
45+
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
46+
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
47+
/******/ }
48+
/******/ Object.defineProperty(exports, '__esModule', { value: true });
49+
/******/ };
50+
/******/
51+
/******/ // create a fake namespace object
52+
/******/ // mode & 1: value is a module id, require it
53+
/******/ // mode & 2: merge all properties of value into the ns
54+
/******/ // mode & 4: return value when already ns object
55+
/******/ // mode & 8|1: behave like require
56+
/******/ __webpack_require__.t = function(value, mode) {
57+
/******/ if(mode & 1) value = __webpack_require__(value);
58+
/******/ if(mode & 8) return value;
59+
/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
60+
/******/ var ns = Object.create(null);
61+
/******/ __webpack_require__.r(ns);
62+
/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
63+
/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
64+
/******/ return ns;
65+
/******/ };
66+
/******/
67+
/******/ // getDefaultExport function for compatibility with non-harmony modules
68+
/******/ __webpack_require__.n = function(module) {
69+
/******/ var getter = module && module.__esModule ?
70+
/******/ function getDefault() { return module['default']; } :
71+
/******/ function getModuleExports() { return module; };
72+
/******/ __webpack_require__.d(getter, 'a', getter);
73+
/******/ return getter;
74+
/******/ };
75+
/******/
76+
/******/ // Object.prototype.hasOwnProperty.call
77+
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
78+
/******/
79+
/******/ // __webpack_public_path__
80+
/******/ __webpack_require__.p = "";
81+
/******/
82+
/******/
83+
/******/ // Load entry module and return exports
84+
/******/ return __webpack_require__(__webpack_require__.s = 0);
85+
/******/ })
86+
/************************************************************************/
87+
/******/ ([
88+
/* 0 */
89+
/***/ (function(module, exports) {
90+
91+
var h1 = document.createElement('h1');
92+
h1.innerHTML = 'Hello world!';
93+
document.body.appendChild(h1);
94+
95+
96+
/***/ })
97+
/******/ ]);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1">
5+
<title>Custom insertion example</title>
6+
</head>
7+
<body>
8+
All scripts are placed here:
9+
<script src="bundle.js"></script>
10+
<script>console.log("Executed after all other scripts")</script>
11+
</body>
12+
</html>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
var h1 = document.createElement('h1');
2+
h1.innerHTML = 'Hello world!';
3+
document.body.appendChild(h1);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<%= htmlWebpackPlugin.tags.headTags %>
5+
<title>Custom insertion example</title>
6+
</head>
7+
<body>
8+
All scripts are placed here:
9+
<%= htmlWebpackPlugin.tags.bodyTags %>
10+
<script>console.log("Executed after all other scripts")</script>
11+
</body>
12+
</html>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# custom insertion example
2+
3+
This example shows how you can define the position where the scripts are injected
4+
by setting `inject:false` and using the template parameters inside the `inside.ejs`
5+
6+
The example is using the template parameters `headTags` and `bodyTags`
7+
8+
```
9+
<%= htmlWebpackPlugin.tags.headTags %>
10+
<%= htmlWebpackPlugin.tags.bodyTags %>
11+
```
12+
13+
`headTags` and `bodyTags` are arrays so you can use any Array.prototype function like `filter`:
14+
15+
```
16+
<%= htmlWebpackPlugin
17+
.tags
18+
.headTags
19+
.filter((tag) => tag.tagName === 'meta')
20+
.join('')
21+
%>
22+
```
23+
24+
For further information about the tag object take a look at the `createHtmlTagObject` inside `lib/html-tags.js` or at the `prepareAssetTagGroupForRendering` inside `index.js`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
var path = require('path');
2+
var HtmlWebpackPlugin = require('../..');
3+
var webpackMajorVersion = require('webpack/package.json').version.split('.')[0];
4+
module.exports = {
5+
context: __dirname,
6+
entry: './example.js',
7+
output: {
8+
path: path.join(__dirname, 'dist/webpack-' + webpackMajorVersion),
9+
publicPath: '',
10+
filename: 'bundle.js'
11+
},
12+
plugins: [
13+
new HtmlWebpackPlugin({
14+
template: 'index.ejs',
15+
inject: false,
16+
// The following settings are optional and only used for
17+
// demo purposes:
18+
meta: {
19+
charset: { charset: 'utf-8' },
20+
viewport: 'width=device-width, initial-scale=1'
21+
},
22+
minify: false
23+
})
24+
]
25+
};
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
<head><link href="styles.css" rel="stylesheet"></head>Hello World from backend2019-04-25T12:53:42.170Z<h2>Partial</h2><img src="0714810ae3fb211173e2964249507195.png"><script src="bundle.js"></script>
1+
<head><link href="styles.css" rel="stylesheet"></head>Hello World from backend2019-07-22T06:55:15.576Z<h2>Partial</h2><img src="0714810ae3fb211173e2964249507195.png"><script src="bundle.js"></script>

‎index.js

+27-8
Original file line numberDiff line numberDiff line change
@@ -372,9 +372,13 @@ class HtmlWebpackPlugin {
372372
return Promise.resolve({});
373373
}
374374
if (typeof templateParameters === 'function') {
375+
const preparedAssetTags = {
376+
headTags: this.prepareAssetTagGroupForRendering(assetTags.headTags),
377+
bodyTags: this.prepareAssetTagGroupForRendering(assetTags.bodyTags)
378+
};
375379
return Promise
376380
.resolve()
377-
.then(() => templateParameters(compilation, assets, assetTags, this.options));
381+
.then(() => templateParameters(compilation, assets, preparedAssetTags, this.options));
378382
}
379383
if (typeof templateParameters === 'object') {
380384
return Promise.resolve(templateParameters);
@@ -829,6 +833,28 @@ class HtmlWebpackPlugin {
829833
return result;
830834
}
831835

836+
/**
837+
* Add toString methods for easier rendering
838+
* inside the template
839+
*
840+
* @param {Array<HtmlTagObject>} assetTagGroup
841+
* @returns {Array<HtmlTagObject>}
842+
*/
843+
prepareAssetTagGroupForRendering (assetTagGroup) {
844+
const xhtml = this.options.xhtml;
845+
const preparedTags = assetTagGroup.map((assetTag) => {
846+
const copiedAssetTag = Object.assign({}, assetTag);
847+
copiedAssetTag.toString = function () {
848+
return htmlTagObjectToString(this, xhtml);
849+
};
850+
return copiedAssetTag;
851+
});
852+
preparedTags.toString = function () {
853+
return this.join('');
854+
};
855+
return preparedTags;
856+
}
857+
832858
/**
833859
* Injects the assets into the given html string
834860
*
@@ -956,13 +982,6 @@ class HtmlWebpackPlugin {
956982
* @returns {TemplateParameter}
957983
*/
958984
function templateParametersGenerator (compilation, assets, assetTags, options) {
959-
const xhtml = options.xhtml;
960-
assetTags.headTags.toString = function () {
961-
return this.map((assetTagObject) => htmlTagObjectToString(assetTagObject, xhtml)).join('');
962-
};
963-
assetTags.bodyTags.toString = function () {
964-
return this.map((assetTagObject) => htmlTagObjectToString(assetTagObject, xhtml)).join('');
965-
};
966985
return {
967986
compilation: compilation,
968987
webpackConfig: compilation.options,

1 commit comments

Comments
 (1)

aKzenT commented on Sep 4, 2019

@aKzenT

@jantimon the ability to call toString on the individual tag-objects would be very useful for me in my current object, but it seems that this is not yet released as part of the latest beta. Any chance to get a new beta with this feature included? Thanks!

Please sign in to comment.