diff --git a/index.js b/index.js
index e197e8ba..9e91832a 100644
--- a/index.js
+++ b/index.js
@@ -1,8 +1,9 @@
// @ts-check
// Import types
-/* eslint-disable */
-///
-/* eslint-enable */
+/** @typedef {import("./typings").HtmlTagObject} HtmlTagObject */
+/** @typedef {import("./typings").Options} HtmlWebpackOptions */
+/** @typedef {import("./typings").ProcessedOptions} ProcessedHtmlWebpackOptions */
+/** @typedef {import("./typings").TemplateParameter} TemplateParameter */
/** @typedef {import("webpack/lib/Compiler.js")} WebpackCompiler */
/** @typedef {import("webpack/lib/Compilation.js")} WebpackCompilation */
'use strict';
@@ -28,14 +29,14 @@ const fsReadFileAsync = promisify(fs.readFile);
class HtmlWebpackPlugin {
/**
- * @param {Partial} [options]
+ * @param {HtmlWebpackOptions} [options]
*/
constructor (options) {
- /** @type {Partial} */
+ /** @type {HtmlWebpackOptions} */
const userOptions = options || {};
// Default options
- /** @type {HtmlWebpackPluginOptions} */
+ /** @type {ProcessedHtmlWebpackOptions} */
const defaultOptions = {
template: path.join(__dirname, 'default_index.ejs'),
templateContent: false,
@@ -56,7 +57,7 @@ class HtmlWebpackPlugin {
xhtml: false
};
- /** @type {HtmlWebpackPluginOptions} */
+ /** @type {ProcessedHtmlWebpackOptions} */
this.options = Object.assign(defaultOptions, userOptions);
// Default metaOptions if no template is provided
@@ -112,6 +113,7 @@ class HtmlWebpackPlugin {
const minify = this.options.minify;
if (minify === true || (minify === undefined && isProductionLikeMode)) {
+ /** @type { import('html-minifier').Options } */
this.options.minify = {
// https://github.com/kangax/html-minifier#options-quick-reference
collapseWhitespace: true,
@@ -381,7 +383,7 @@ class HtmlWebpackPlugin {
/**
* This function renders the actual html by executing the template function
*
- * @param {(templatePArameters) => string | Promise} templateFunction
+ * @param {(templateParameters) => string | Promise} templateFunction
* @param {{
publicPath: string,
js: Array,
@@ -628,7 +630,7 @@ class HtmlWebpackPlugin {
*
* @param {string|false} faviconFilePath
* @param {WebpackCompilation} compilation
- * @parma {string} publicPath
+ * @param {string} publicPath
* @returns {Promise}
*/
getFaviconPublicPath (faviconFilePath, compilation, publicPath) {
@@ -877,7 +879,7 @@ class HtmlWebpackPlugin {
/**
* Helper to return the absolute template path with a fallback loader
* @param {string} template
- * The path to the tempalate e.g. './index.html'
+ * The path to the template e.g. './index.html'
* @param {string} context
* The webpack base resolution path for relative paths e.g. process.cwd()
*/
@@ -920,8 +922,8 @@ class HtmlWebpackPlugin {
headTags: HtmlTagObject[],
bodyTags: HtmlTagObject[]
}} assetTags
- * @param {HtmlWebpackPluginOptions} options
- * @returns {HtmlWebpackPluginTemplateParameter}
+ * @param {ProcessedHtmlWebpackOptions} options
+ * @returns {TemplateParameter}
*/
function templateParametersGenerator (compilation, assets, assetTags, options) {
const xhtml = options.xhtml;
diff --git a/lib/hooks.js b/lib/hooks.js
index a3c5c837..cf6ce139 100644
--- a/lib/hooks.js
+++ b/lib/hooks.js
@@ -1,7 +1,5 @@
// @ts-check
-/* eslint-disable */
-///
-/* eslint-enable */
+/** @typedef {import("../typings").Hooks} HtmlWebpackPluginHooks */
'use strict';
/**
* This file provides access to all public htmlWebpackPlugin hooks
@@ -12,10 +10,9 @@
const AsyncSeriesWaterfallHook = require('tapable').AsyncSeriesWaterfallHook;
-// The following typedef holds the API definition for all available hooks
-// to allow easier access when using ts-check or typescript inside plugins
-/** @typedef {{
-
+// The following is the API definition for all available hooks
+// For the TypeScript definition, see the Hooks type in typings.d.ts
+/**
beforeAssetTagGeneration:
AsyncSeriesWaterfallHook<{
assets: {
@@ -28,7 +25,6 @@ const AsyncSeriesWaterfallHook = require('tapable').AsyncSeriesWaterfallHook;
outputName: string,
plugin: HtmlWebpackPlugin
}>,
-
alterAssetTags:
AsyncSeriesWaterfallHook<{
assetTags: {
@@ -39,7 +35,6 @@ const AsyncSeriesWaterfallHook = require('tapable').AsyncSeriesWaterfallHook;
outputName: string,
plugin: HtmlWebpackPlugin
}>,
-
alterAssetTagGroups:
AsyncSeriesWaterfallHook<{
headTags: Array,
@@ -47,7 +42,6 @@ const AsyncSeriesWaterfallHook = require('tapable').AsyncSeriesWaterfallHook;
outputName: string,
plugin: HtmlWebpackPlugin
}>,
-
afterTemplateExecution:
AsyncSeriesWaterfallHook<{
html: string,
@@ -56,22 +50,18 @@ const AsyncSeriesWaterfallHook = require('tapable').AsyncSeriesWaterfallHook;
outputName: string,
plugin: HtmlWebpackPlugin,
}>,
-
beforeEmit:
AsyncSeriesWaterfallHook<{
html: string,
outputName: string,
plugin: HtmlWebpackPlugin,
}>,
-
afterEmit:
AsyncSeriesWaterfallHook<{
outputName: string,
plugin: HtmlWebpackPlugin
- }>,
-
- }} HtmlWebpackPluginHooks
- */
+ }>
+*/
/**
* @type {WeakMap}}
diff --git a/lib/html-tags.js b/lib/html-tags.js
index cdad0d4a..4f331245 100644
--- a/lib/html-tags.js
+++ b/lib/html-tags.js
@@ -1,7 +1,5 @@
// @ts-check
-/* eslint-disable */
-///
-/* eslint-enable */
+/** @typedef {import("../typings").HtmlTagObject} HtmlTagObject */
/**
* @file
* This file provides to helper to create html as a object repesentation as
diff --git a/package.json b/package.json
index 967f0721..df5fa638 100644
--- a/package.json
+++ b/package.json
@@ -5,6 +5,7 @@
"description": "Simplifies creation of HTML files to serve your webpack bundles",
"author": "Jan Nicklas (https://github.com/jantimon)",
"main": "index.js",
+ "types": "typings.d.ts",
"files": [
"lib/",
"index.js",
@@ -27,9 +28,11 @@
]
},
"devDependencies": {
+ "@types/html-minifier": "^3.5.2",
"@types/loader-utils": "1.1.3",
"@types/node": "10.11.4",
"@types/tapable": "1.0.4",
+ "@types/webpack": "^4.0.0",
"appcache-webpack-plugin": "^1.4.0",
"commitizen": "3.0.2",
"css-loader": "^1.0.0",
diff --git a/typings.d.ts b/typings.d.ts
index e5fcef72..ed32509c 100644
--- a/typings.d.ts
+++ b/typings.d.ts
@@ -1,139 +1,252 @@
+import { Plugin } from "webpack";
+import { AsyncSeriesWaterfallHook } from "tapable";
+import { Options as HtmlMinifierOptions } from "html-minifier";
-/**
- * The plugin options
- */
-interface HtmlWebpackPluginOptions {
+// https://github.com/Microsoft/TypeScript/issues/15012#issuecomment-365453623
+type Required = T extends object
+ ? { [P in keyof T]-?: NonNullable }
+ : T;
+// https://stackoverflow.com/questions/48215950/exclude-property-from-type
+type Omit = Pick>;
+
+export = HtmlWebpackPlugin;
+
+declare class HtmlWebpackPlugin extends Plugin {
+ constructor(options?: HtmlWebpackPlugin.Options);
+}
+
+declare namespace HtmlWebpackPlugin {
+ type MinifyOptions = HtmlMinifierOptions;
+
+ /**
+ * The plugin options
+ */
+ interface Options {
/**
- * The title to use for the generated HTML document
+ * Emit the file only if it was changed.
+ * Default: `true`.
*/
- title: string,
+ cache?: boolean;
/**
- * The `webpack` require path to the template.
- * @see https://github.com/jantimon/html-webpack-plugin/blob/master/docs/template-option.md
+ * List all entries which should be injected
*/
- template: string,
+ chunks?: "all" | string[];
/**
- * Allow to use a html string instead of reading from a file
+ * Allows to control how chunks should be sorted before they are included to the html.
+ * Default: `'auto'`.
*/
- templateContent:
- false // Use the template option instead to load a file
- | string
- | Promise,
+ chunksSortMode?:
+ | "auto"
+ | "manual"
+ | (((entryNameA: string, entryNameB: string) => number));
/**
- * Allows to overwrite the parameters used in the template
+ * List all entries which should not be injeccted
*/
- templateParameters:
- false // Pass an empty object to the template function
- | ((compilation: any, assets, assetTags: { headTags: Array, bodyTags: Array }, options: HtmlWebpackPluginOptions) => {[option: string]: any})
- | ((compilation: any, assets, assetTags: { headTags: Array, bodyTags: Array }, options: HtmlWebpackPluginOptions) => Promise<{[option: string]: any}>)
- | {[option: string]: any}
+ excludeChunks?: string[];
+ /**
+ * Path to the favicon icon
+ */
+ favicon?: false | string;
/**
* The file to write the HTML to.
* Defaults to `index.html`.
* Supports subdirectories eg: `assets/admin.html`
*/
- filename: string,
+ filename?: string;
/**
* If `true` then append a unique `webpack` compilation hash to all included scripts and CSS files.
* This is useful for cache busting
*/
- hash: boolean,
+ hash?: boolean;
/**
* Inject all assets into the given `template` or `templateContent`.
*/
- inject: false // Don't inject scripts
- | true // Inject scripts into body
- | 'body' // Inject scripts into body
- | 'head' // Inject scripts into head
+ inject?:
+ | false // Don't inject scripts
+ | true // Inject scripts into body
+ | "body" // Inject scripts into body
+ | "head"; // Inject scripts into head
/**
- * Path to the favicon icon
+ * Inject meta tags
*/
- favicon: false | string,
+ meta?:
+ | false // Disable injection
+ | {
+ [name: string]:
+ | string
+ | false // name content pair e.g. {viewport: 'width=device-width, initial-scale=1, shrink-to-fit=no'}`
+ | { [attributeName: string]: string | boolean }; // custom properties e.g. { name:"viewport" content:"width=500, initial-scale=1" }
+ };
/**
* HTML Minification options
* @https://github.com/kangax/html-minifier#options-quick-reference
*/
- minify?: boolean | {},
- cache: boolean,
+ minify?: boolean | MinifyOptions;
/**
* Render errors into the HTML page
*/
- showErrors: boolean,
+ showErrors?: boolean;
/**
- * List all entries which should be injected
+ * The `webpack` require path to the template.
+ * @see https://github.com/jantimon/html-webpack-plugin/blob/master/docs/template-option.md
*/
- chunks: 'all' | string[],
+ template?: string;
/**
- * List all entries which should not be injeccted
+ * Allow to use a html string instead of reading from a file
*/
- excludeChunks: string[],
- chunksSortMode: 'auto' | 'manual' | (((entryNameA: string, entryNameB: string) => number)),
+ templateContent?:
+ | false // Use the template option instead to load a file
+ | string
+ | Promise;
/**
- * Inject meta tags
+ * Allows to overwrite the parameters used in the template
*/
- meta: false // Disable injection
- | {
- [name: string]: string|false // name content pair e.g. {viewport: 'width=device-width, initial-scale=1, shrink-to-fit=no'}`
- | {[attributeName: string]: string|boolean} // custom properties e.g. { name:"viewport" content:"width=500, initial-scale=1" }
- },
+ templateParameters?:
+ | false // Pass an empty object to the template function
+ | ((
+ compilation: any,
+ assets,
+ assetTags: {
+ headTags: HtmlTagObject[];
+ bodyTags: HtmlTagObject[];
+ },
+ options: Options
+ ) => { [option: string]: any })
+ | ((
+ compilation: any,
+ assets,
+ assetTags: {
+ headTags: HtmlTagObject[];
+ bodyTags: HtmlTagObject[];
+ },
+ options: Options
+ ) => Promise<{ [option: string]: any }>)
+ | { [option: string]: any };
+ /**
+ * The title to use for the generated HTML document
+ */
+ title?: string;
/**
* Enforce self closing tags e.g.
*/
- xhtml: boolean
-
+ xhtml?: boolean;
/**
* In addition to the options actually used by this plugin, you can use this hash to pass arbitrary data through
* to your template.
*/
[option: string]: any;
-}
+ }
-/**
- * A tag element according to the htmlWebpackPlugin object notation
- */
-interface HtmlTagObject {
/**
- * Attributes of the html tag
- * E.g. `{'disabled': true, 'value': 'demo'}`
+ * Options interface that matches the expectations of the index.js API:
+ * - All fields are required
+ * - The minify property matches what html-minifier expects (eg either a MinifyOptions or undefined).
+ * html-minifier does not accept a boolean value. As TypeScript does not allow a property to be redefined
+ * in an extended interface we need to omit it and then define it properly
+ *
+ * The Required and Omit types are defined at the top of the file
*/
- attributes: {
- [attributeName: string]: string|boolean
- },
- /**
- * Wether this html must not contain innerHTML
- * @see https://www.w3.org/TR/html5/syntax.html#void-elements
- */
- voidTag: boolean,
+ interface ProcessedOptions extends Required> {
+ minify: MinifyOptions | undefined;
+ }
+
/**
- * The tag name e.g. `'div'`
+ * The values which are available during template execution
+ *
+ * Please keep in mind that the `templateParameter` options allows to change them
*/
- tagName: string,
+ interface TemplateParameter {
+ compilation: any;
+ htmlWebpackPlugin: {
+ tags: {
+ headTags: HtmlTagObject[];
+ bodyTags: HtmlTagObject[];
+ };
+ files: {
+ publicPath: string;
+ js: Array;
+ css: Array;
+ manifest?: string;
+ favicon?: string;
+ };
+ options: Options;
+ };
+ webpackConfig: any;
+ }
+
+ interface Hooks {
+ alterAssetTags: AsyncSeriesWaterfallHook<{
+ assetTags: {
+ scripts: HtmlTagObject[];
+ styles: HtmlTagObject[];
+ meta: HtmlTagObject[];
+ };
+ outputName: string;
+ plugin: HtmlWebpackPlugin;
+ }>;
+
+ alterAssetTagGroups: AsyncSeriesWaterfallHook<{
+ headTags: HtmlTagObject[];
+ bodyTags: HtmlTagObject[];
+ outputName: string;
+ plugin: HtmlWebpackPlugin;
+ }>;
+
+ afterTemplateExecution: AsyncSeriesWaterfallHook<{
+ html: string;
+ headTags: HtmlTagObject[];
+ bodyTags: HtmlTagObject[];
+ outputName: string;
+ plugin: HtmlWebpackPlugin;
+ }>;
+
+ beforeAssetTagGeneration: AsyncSeriesWaterfallHook<{
+ assets: {
+ publicPath: string;
+ js: Array;
+ css: Array;
+ favicon?: string | undefined;
+ manifest?: string | undefined;
+ };
+ outputName: string;
+ plugin: HtmlWebpackPlugin;
+ }>;
+
+ beforeEmit: AsyncSeriesWaterfallHook<{
+ html: string;
+ outputName: string;
+ plugin: HtmlWebpackPlugin;
+ }>;
+
+ afterEmit: AsyncSeriesWaterfallHook<{
+ outputName: string;
+ plugin: HtmlWebpackPlugin;
+ }>;
+ }
+
/**
- * Inner HTML The
+ * A tag element according to the htmlWebpackPlugin object notation
*/
- innerHTML?: string
-}
-
-/**
- * The values which are available during template execution
- *
- * Please keep in mind that the `templateParameter` options allows to change them
- */
-interface HtmlWebpackPluginTemplateParameter {
- compilation: any,
- webpackConfig: any
- htmlWebpackPlugin: {
- tags: {
- headTags: HtmlTagObject[],
- bodyTags: HtmlTagObject[]
- },
- files: {
- publicPath: string,
- js: Array,
- css: Array,
- manifest?: string,
- favicon?: string
- },
- options: HtmlWebpackPluginOptions
+ interface HtmlTagObject {
+ /**
+ * Attributes of the html tag
+ * E.g. `{'disabled': true, 'value': 'demo'}`
+ */
+ attributes: {
+ [attributeName: string]: string | boolean;
+ };
+ /**
+ * The tag name e.g. `'div'`
+ */
+ tagName: string;
+ /**
+ * The inner HTML
+ */
+ innerHTML?: string;
+ /**
+ * Whether this html must not contain innerHTML
+ * @see https://www.w3.org/TR/html5/syntax.html#void-elements
+ */
+ voidTag: boolean;
}
}