html-webpack-plugin 3.2.0 → 4.0.0-alpha

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,139 +1,47 @@
1
+ // @ts-check
2
+ /** @typedef {import("webpack/lib/Compilation.js")} WebpackCompilation */
1
3
  'use strict';
2
4
 
3
- const toposort = require('toposort');
4
- const _ = require('lodash');
5
+ // Import webpack types using commonjs
6
+ // As we use only the type we have to prevent warnings about unused varaibles
7
+ /* eslint-disable */
8
+ const WebpackCompilation = require('webpack/lib/Compilation');
9
+ /* eslint-enable */
5
10
 
6
11
  /**
7
- Sorts dependencies between chunks by their "parents" attribute.
8
-
9
- This function sorts chunks based on their dependencies with each other.
10
- The parent relation between chunks as generated by Webpack for each chunk
11
- is used to define a directed (and hopefully acyclic) graph, which is then
12
- topologically sorted in order to retrieve the correct order in which
13
- chunks need to be embedded into HTML. A directed edge in this graph is
14
- describing a "is parent of" relationship from a chunk to another (distinct)
15
- chunk. Thus topological sorting orders chunks from bottom-layer chunks to
16
- highest level chunks that use the lower-level chunks.
17
-
18
- @param {Array} chunks an array of chunks as generated by the html-webpack-plugin.
19
- - For webpack < 4, It is assumed that each entry contains at least the properties
20
- "id" (containing the chunk id) and "parents" (array containing the ids of the
21
- parent chunks).
22
- - For webpack 4+ the see the chunkGroups param for parent-child relationships
23
-
24
- @param {Array} chunks an array of ChunkGroups that has a getParents method.
25
- Each ChunkGroup contains a list of chunks in order.
26
-
27
- @return {Array} A topologically sorted version of the input chunks
28
- */
29
- module.exports.dependency = (chunks, options, compilation) => {
30
- const chunkGroups = compilation.chunkGroups;
31
- if (!chunks) {
32
- return chunks;
33
- }
34
-
35
- // We build a map (chunk-id -> chunk) for faster access during graph building.
36
- const nodeMap = {};
37
-
38
- chunks.forEach(chunk => {
39
- nodeMap[chunk.id] = chunk;
40
- });
41
-
42
- // Next, we add an edge for each parent relationship into the graph
43
- let edges = [];
44
-
45
- if (chunkGroups) {
46
- // Add an edge for each parent (parent -> child)
47
- edges = chunkGroups.reduce((result, chunkGroup) => result.concat(
48
- Array.from(chunkGroup.parentsIterable, parentGroup => [parentGroup, chunkGroup])
49
- ), []);
50
- const sortedGroups = toposort.array(chunkGroups, edges);
51
- // flatten chunkGroup into chunks
52
- const sortedChunks = sortedGroups
53
- .reduce((result, chunkGroup) => result.concat(chunkGroup.chunks), [])
54
- .map(chunk => // use the chunk from the list passed in, since it may be a filtered list
55
- nodeMap[chunk.id])
56
- .filter((chunk, index, self) => {
57
- // make sure exists (ie excluded chunks not in nodeMap)
58
- const exists = !!chunk;
59
- // make sure we have a unique list
60
- const unique = self.indexOf(chunk) === index;
61
- return exists && unique;
62
- });
63
- return sortedChunks;
64
- } else {
65
- // before webpack 4 there was no chunkGroups
66
- chunks.forEach(chunk => {
67
- if (chunk.parents) {
68
- // Add an edge for each parent (parent -> child)
69
- chunk.parents.forEach(parentId => {
70
- // webpack2 chunk.parents are chunks instead of string id(s)
71
- const parentChunk = _.isObject(parentId) ? parentId : nodeMap[parentId];
72
- // If the parent chunk does not exist (e.g. because of an excluded chunk)
73
- // we ignore that parent
74
- if (parentChunk) {
75
- edges.push([parentChunk, chunk]);
76
- }
77
- });
78
- }
79
- });
80
- // We now perform a topological sorting on the input chunks and built edges
81
- return toposort.array(chunks, edges);
82
- }
83
- };
84
-
85
- /**
86
- * Sorts the chunks based on the chunk id.
87
- *
88
- * @param {Array} chunks the list of chunks to sort
89
- * @return {Array} The sorted list of chunks
12
+ * @type {{[sortmode: string] : (entryPointNames: Array<string>, compilation, htmlWebpackPluginOptions) => Array<string> }}
13
+ * This file contains different sort methods for the entry chunks names
90
14
  */
91
- module.exports.id = chunks => chunks.sort(function orderEntryLast (a, b) {
92
- if (a.entry !== b.entry) {
93
- return b.entry ? 1 : -1;
94
- } else {
95
- return b.id - a.id;
96
- }
97
- });
15
+ const sortFunctions = {};
16
+ module.exports = sortFunctions;
98
17
 
99
18
  /**
100
19
  * Performs identity mapping (no-sort).
101
20
  * @param {Array} chunks the chunks to sort
102
21
  * @return {Array} The sorted chunks
103
22
  */
104
- module.exports.none = chunks => chunks;
23
+ sortFunctions.none = chunks => chunks;
105
24
 
106
25
  /**
107
26
  * Sort manually by the chunks
108
- * @param {Array} chunks the chunks to sort
109
- * @return {Array} The sorted chunks
27
+ * @param {string[]} entryPointNames the chunks to sort
28
+ * @param {WebpackCompilation} compilation the webpack compilation
29
+ * @param htmlWebpackPluginOptions the plugin options
30
+ * @return {string[]} The sorted chunks
110
31
  */
111
- module.exports.manual = (chunks, options) => {
112
- const specifyChunks = options.chunks;
113
- const chunksResult = [];
114
- let filterResult = [];
115
- if (Array.isArray(specifyChunks)) {
116
- for (var i = 0; i < specifyChunks.length; i++) {
117
- filterResult = chunks.filter(chunk => {
118
- if (chunk.names[0] && chunk.names[0] === specifyChunks[i]) {
119
- return true;
120
- }
121
- return false;
122
- });
123
- filterResult.length > 0 && chunksResult.push(filterResult[0]);
124
- }
32
+ sortFunctions.manual = (entryPointNames, compilation, htmlWebpackPluginOptions) => {
33
+ const chunks = htmlWebpackPluginOptions.chunks;
34
+ if (!Array.isArray(chunks)) {
35
+ return entryPointNames;
125
36
  }
126
- return chunksResult;
37
+ // Remove none existing entries from
38
+ // htmlWebpackPluginOptions.chunks
39
+ return chunks.filter((entryPointName) => {
40
+ return compilation.entrypoints.has(entryPointName);
41
+ });
127
42
  };
128
43
 
129
44
  /**
130
45
  * Defines the default sorter.
131
46
  */
132
- module.exports.auto = module.exports.id;
133
-
134
- // In webpack 2 the ids have been flipped.
135
- // Therefore the id sort doesn't work the same way as it did for webpack 1
136
- // Luckily the dependency sort is working as expected
137
- if (Number(require('webpack/package.json').version.split('.')[0]) > 1) {
138
- module.exports.auto = module.exports.dependency;
139
- }
47
+ sortFunctions.auto = module.exports.none;
package/lib/compiler.js CHANGED
@@ -59,9 +59,7 @@ module.exports.compileTemplate = function compileTemplate (template, context, ou
59
59
  // Fix for "Uncaught TypeError: __webpack_require__(...) is not a function"
60
60
  // Hot module replacement requires that every child compiler has its own
61
61
  // cache. @see https://github.com/ampedandwired/html-webpack-plugin/pull/179
62
-
63
- // Backwards compatible version of: childCompiler.hooks.compilation
64
- (childCompiler.hooks ? childCompiler.hooks.compilation.tap.bind(childCompiler.hooks.compilation, 'HtmlWebpackPlugin') : childCompiler.plugin.bind(childCompiler, 'compilation'))(compilation => {
62
+ childCompiler.hooks.compilation.tap('HtmlWebpackPlugin', compilation => {
65
63
  if (compilation.cache) {
66
64
  if (!compilation.cache[compilerName]) {
67
65
  compilation.cache[compilerName] = {};
@@ -81,19 +79,10 @@ module.exports.compileTemplate = function compileTemplate (template, context, ou
81
79
  reject(err);
82
80
  } else {
83
81
  // Replace [hash] placeholders in filename
84
- // In webpack 4 the plugin interface changed, so check for available fns
85
- const outputName = compilation.mainTemplate.getAssetPath
86
- ? compilation.mainTemplate.hooks.assetPath.call(outputOptions.filename, {
87
- hash: childCompilation.hash,
88
- chunk: entries[0]
89
- })
90
- : compilation.mainTemplate.applyPluginsWaterfall(
91
- 'asset-path',
92
- outputOptions.filename,
93
- {
94
- hash: childCompilation.hash,
95
- chunk: entries[0]
96
- });
82
+ const outputName = compilation.mainTemplate.hooks.assetPath.call(outputOptions.filename, {
83
+ hash: childCompilation.hash,
84
+ chunk: entries[0]
85
+ });
97
86
 
98
87
  // Restore the parent compilation to the state like it
99
88
  // was before the child compilation
package/lib/errors.js CHANGED
@@ -1,8 +1,9 @@
1
+ // @ts-nocheck
1
2
  'use strict';
2
3
  const PrettyError = require('pretty-error');
3
4
  const prettyError = new PrettyError();
4
5
  prettyError.withoutColors();
5
- prettyError.skipPackage(['html-plugin-evaluation']);
6
+ prettyError.skipPackage('html-plugin-evaluation');
6
7
  prettyError.skipNodeFiles();
7
8
  prettyError.skip(function (traceLine) {
8
9
  return traceLine.path === 'html-plugin-evaluation';
package/lib/hooks.js ADDED
@@ -0,0 +1,132 @@
1
+ // @ts-check
2
+ /* eslint-disable */
3
+ /// <reference path="../typings.d.ts" />
4
+ /* eslint-enable */
5
+ 'use strict';
6
+ /**
7
+ * This file provides access to all public htmlWebpackPlugin hooks
8
+ *
9
+ * Usage:
10
+ * ```js
11
+ * const getHtmlWebpackPluginHooks = require('html-webpack-plugin/lib/hooks').getHtmlWebpackPluginHooks;
12
+ *
13
+ * compiler.hooks.compilation.tap('YOUR_PLUGIN_NAME', (compilation) => {
14
+ * const htmlWebpackPluginHooks = getHtmlWebpackPluginHooks(compilation);
15
+ * htmlWebpackPluginHooks.htmlWebpackPluginAfterEmit.tap('YOUR_PLUGIN_NAME', (pluginArgs) => {
16
+ * // your code
17
+ * });
18
+ * });
19
+ * ```
20
+ */
21
+
22
+ /** @typedef {import("webpack/lib/Compilation.js")} WebpackCompilation */
23
+ /** @typedef {import("../index.js")} HtmlWebpackPlugin */
24
+
25
+ const AsyncSeriesWaterfallHook = require('tapable').AsyncSeriesWaterfallHook;
26
+
27
+ // The following typedef holds the API definition for all available hooks
28
+ // to allow easier access when using ts-check or typescript inside plugins
29
+ /** @typedef {{
30
+ htmlWebpackPluginBeforeHtmlGeneration:
31
+ AsyncSeriesWaterfallHook<{
32
+ assets: {
33
+ publicPath: string,
34
+ js: Array<{entryName: string, path: string}>,
35
+ css: Array<{entryName: string, path: string}>,
36
+ },
37
+ outputName: string,
38
+ plugin: HtmlWebpackPlugin
39
+ }>,
40
+ htmlWebpackPluginBeforeHtmlProcessing:
41
+ AsyncSeriesWaterfallHook<{
42
+ html: string,
43
+ assets: {
44
+ publicPath: string,
45
+ js: Array<{entryName: string, path: string}>,
46
+ css: Array<{entryName: string, path: string}>,
47
+ },
48
+ outputName: string,
49
+ plugin: HtmlWebpackPlugin,
50
+ }>,
51
+ htmlWebpackPluginAfterHtmlProcessing:
52
+ AsyncSeriesWaterfallHook<{
53
+ html: string,
54
+ assets: {
55
+ publicPath: string,
56
+ js: Array<{entryName: string, path: string}>,
57
+ css: Array<{entryName: string, path: string}>,
58
+ },
59
+ outputName: string,
60
+ plugin: HtmlWebpackPlugin,
61
+ }>,
62
+ htmlWebpackPluginAlterAssetTags:
63
+ AsyncSeriesWaterfallHook<{
64
+ head: Array<HtmlTagObject>,
65
+ body: Array<HtmlTagObject>,
66
+ outputName: string,
67
+ plugin: HtmlWebpackPlugin
68
+ }>,
69
+ htmlWebpackPluginAfterEmit:
70
+ AsyncSeriesWaterfallHook<{
71
+ html: string,
72
+ outputName: string,
73
+ plugin: HtmlWebpackPlugin
74
+ }>,
75
+ }} HtmlWebpackPluginHooks
76
+ */
77
+
78
+ /**
79
+ * Returns all public hooks of the html webpack plugin for the given compilation
80
+ *
81
+ * @param {WebpackCompilation} compilation
82
+ * @returns {HtmlWebpackPluginHooks}
83
+ */
84
+ function getHtmlWebpackPluginHooks (compilation) {
85
+ /** @type {HtmlWebpackPluginHooks} */
86
+ const hooks = compilation.hooks;
87
+ // Setup the hooks only once
88
+ if (!hooks.htmlWebpackPluginAfterEmit) {
89
+ attachHooksToCompilation(compilation);
90
+ }
91
+ return {
92
+ htmlWebpackPluginBeforeHtmlGeneration: hooks.htmlWebpackPluginBeforeHtmlGeneration,
93
+ htmlWebpackPluginBeforeHtmlProcessing: hooks.htmlWebpackPluginBeforeHtmlProcessing,
94
+ htmlWebpackPluginAlterAssetTags: hooks.htmlWebpackPluginAlterAssetTags,
95
+ htmlWebpackPluginAfterHtmlProcessing: hooks.htmlWebpackPluginAfterHtmlProcessing,
96
+ htmlWebpackPluginAfterEmit: hooks.htmlWebpackPluginAfterEmit
97
+ };
98
+ }
99
+
100
+ /**
101
+ * Add hooks to the webpack compilation object to allow foreign plugins to
102
+ * extend the HtmlWebpackPlugin
103
+ *
104
+ * @param {WebpackCompilation} compilation
105
+ */
106
+ function attachHooksToCompilation (compilation) {
107
+ /** @type {HtmlWebpackPluginHooks} */
108
+ const hooks = compilation.hooks;
109
+ hooks.htmlWebpackPluginBeforeHtmlGeneration = new AsyncSeriesWaterfallHook(['pluginArgs']);
110
+ hooks.htmlWebpackPluginBeforeHtmlProcessing = new AsyncSeriesWaterfallHook(['pluginArgs']);
111
+ hooks.htmlWebpackPluginAlterAssetTags = new AsyncSeriesWaterfallHook(['pluginArgs']);
112
+ hooks.htmlWebpackPluginAfterHtmlProcessing = new AsyncSeriesWaterfallHook(['pluginArgs']);
113
+ hooks.htmlWebpackPluginAfterEmit = new AsyncSeriesWaterfallHook(['pluginArgs']);
114
+ }
115
+
116
+ /**
117
+ * Small workaround helper to work around https://github.com/Microsoft/TypeScript/issues/1178
118
+ * Returns the hook of the given name
119
+ *
120
+ * @type {
121
+ <T extends keyof HtmlWebpackPluginHooks>(compilation: WebpackCompilation, hookName: T) => HtmlWebpackPluginHooks[T]
122
+ }
123
+ */
124
+ const getHtmlWebpackPluginHook = (compilation, hookName) => {
125
+ const hooks = getHtmlWebpackPluginHooks(compilation);
126
+ return /** @type {any} */hooks[hookName];
127
+ };
128
+
129
+ module.exports = {
130
+ getHtmlWebpackPluginHooks,
131
+ getHtmlWebpackPluginHook
132
+ };
@@ -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
+ };
package/lib/loader.js CHANGED
@@ -1,6 +1,6 @@
1
1
  /* This loader renders the template with underscore if no other loader was found */
2
+ // @ts-nocheck
2
3
  'use strict';
3
-
4
4
  const _ = require('lodash');
5
5
  const loaderUtils = require('loader-utils');
6
6
 
@@ -21,11 +21,11 @@ module.exports = function (source) {
21
21
  return source;
22
22
  }
23
23
 
24
- // The following part renders the tempalte with lodash as aminimalistic loader
24
+ // The following part renders the template with lodash as aminimalistic loader
25
25
  //
26
26
  // Get templating options
27
- const options = this.query !== '' ? loaderUtils.parseQuery(this.query) : {};
28
- const template = _.template(source, _.defaults(options, { variable: 'data' }));
27
+ const options = this.query !== '' ? loaderUtils.getOptions(this) : {};
28
+ const template = _.template(source, _.defaults(options, { interpolate: /<%=([\s\S]+?)%>/g, variable: 'data' }));
29
29
  // Require !!lodash - using !! will disable all loaders (e.g. babel)
30
30
  return 'var _ = require(' + loaderUtils.stringifyRequest(this, '!!' + require.resolve('lodash')) + ');' +
31
31
  'module.exports = function (templateParams) { with(templateParams) {' +
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "html-webpack-plugin",
3
- "version": "3.2.0",
3
+ "version": "4.0.0-alpha",
4
4
  "license": "MIT",
5
5
  "description": "Simplifies creation of HTML files to serve your webpack bundles",
6
6
  "author": "Charles Blaxland <charles.blaxland@gmail.com> (https://github.com/ampedandwired)",
@@ -12,6 +12,7 @@
12
12
  ],
13
13
  "scripts": {
14
14
  "pretest": "semistandard",
15
+ "posttest": "tsc --pretty",
15
16
  "commit": "git-cz",
16
17
  "build-examples": "node examples/build-examples.js",
17
18
  "test": "jasmine",
@@ -23,13 +24,13 @@
23
24
  ]
24
25
  },
25
26
  "devDependencies": {
27
+ "@types/node": "10.1.1",
26
28
  "appcache-webpack-plugin": "^1.3.0",
27
29
  "commitizen": "2.9.6",
28
30
  "css-loader": "^0.26.1",
29
31
  "cz-conventional-changelog": "2.1.0",
30
32
  "dir-compare": "1.3.0",
31
- "es6-promise": "^4.0.5",
32
- "extract-text-webpack-plugin": "^1.0.1",
33
+ "extract-text-webpack-plugin": "^4.0.0-beta.0",
33
34
  "file-loader": "^0.9.0",
34
35
  "html-loader": "^0.4.4",
35
36
  "jade": "^1.11.0",
@@ -40,22 +41,24 @@
40
41
  "semistandard": "8.0.0",
41
42
  "standard-version": "^4.3.0",
42
43
  "style-loader": "^0.13.1",
44
+ "typescript": "2.9.0-dev.20180518",
43
45
  "underscore-template-loader": "^0.7.3",
44
46
  "url-loader": "^0.5.7",
45
- "webpack": "^1.14.0",
47
+ "webpack": "4.8.3",
48
+ "webpack-cli": "2.0.12",
46
49
  "webpack-recompilation-simulator": "^1.3.0"
47
50
  },
48
51
  "dependencies": {
52
+ "@types/tapable": "1.0.2",
49
53
  "html-minifier": "^3.2.3",
50
- "loader-utils": "^0.2.16",
51
- "lodash": "^4.17.3",
54
+ "loader-utils": "^1.1.0",
55
+ "lodash": "^4.17.10",
52
56
  "pretty-error": "^2.0.2",
53
57
  "tapable": "^1.0.0",
54
- "toposort": "^1.0.0",
55
58
  "util.promisify": "1.0.0"
56
59
  },
57
60
  "peerDependencies": {
58
- "webpack": "^1.0.0 || ^2.0.0 || ^3.0.0 || ^4.0.0"
61
+ "webpack": "^4.0.0"
59
62
  },
60
63
  "keywords": [
61
64
  "webpack",