npm package: @fortnight/html-webpack-tags-plugin
Description: lets you define html tags to inject with html-webpack-plugin.Hank's sp ver.
Author: Hank Xu
Latest version: 2.0.17

Tags Plugin for the HTML Webpack Plugin
========================================
[![npm version](https://badge.fury.io/js/html-webpack-tags-plugin.svg)](https://badge.fury.io/js/html-webpack-tags-plugin) [![Build Status](https://travis-ci.org/jharris4/html-webpack-tags-plugin.svg?branch=master)](https://travis-ci.org/jharris4/html-webpack-tags-plugin) [![js-semistandard-style](https://img.shields.io/badge/code%20style-semistandard-brightgreen.svg?style=flat-square)](https://github.com/Flet/semistandard)

Enhances [html-webpack-plugin](https://github.com/ampedandwired/html-webpack-plugin)
by letting you specify script or link tags to inject.

Prior Version
------------

- `html-webpack-tags-plugin` requires **Node >= 8.6**.
- This plugin used to be called `html-webpack-include-assets-plugin`.
- For older version of Node, please install [html-webpack-include-assets-plugin version 1.x](https://github.com/jharris4/html-webpack-tags-plugin/releases/tag/1.0.10).

Motivation
------------

When using a plugin such as [copy-webpack-plugin](https://github.com/webpack-contrib/copy-webpack-plugin) you may have assets output to your build directory that are not detected/output by the html-webpack-plugin.

This plugin lets you manually resolve such issues, and also lets you inject the webpack `publicPath` or compilation `hash` into your tag paths if you so choose.

Installation
------------
You must be running webpack on node 8.x or higher

Install the plugin with npm:
```shell
$ npm install --save-dev html-webpack-tags-plugin
```

Deployment
----------

[html-webpack-deploy-plugin](https://github.com/jharris4/html-webpack-deploy-plugin) is a plugin that enhances this plugin with capabilities such as:
 - copying your local files and injecting them as html tags with easy to use syntax
 - copying package files from your local node_modules and having them versioned automatically as they are injected as html tags
 - easy configuration to stop webpack from processing certain node_modules packages so you can handle shipping certain package bundles yourself
 - easy to use CDN settings so you can inject package tags that serve from a CDN for optimal performance

Basic Usage
-----------
Require the plugin in your webpack config:

```javascript
var HtmlWebpackTagsPlugin = require('html-webpack-tags-plugin');
```

Add the plugin to your webpack config:

```javascript
output: {
  publicPath: '/abc/'
},
plugins: [
  new HtmlWebpackPlugin(),
  new HtmlWebpackTagsPlugin({ tags: ['a.js', 'b.css'], append: true })
]
```

Which will generate html like this:

```html
<head>
  <!-- other head content -->
  <link rel="stylesheet" href="/abc/b.css"/>
</head>
<body>
  <!-- other body content -->
  <script type="text/javascript" src="/abc/a.js"></script>
</body>
```

Configuration
-------

### Default Options

This plugin will run and do nothing if no options are provided.

The default options for this plugin are shown below:

```js
const url = require('url');

const DEFAULT_OPTIONS = {
  append: true,
  prependExternals: true,
  jsExtensions: ['.js'],
  cssExtensions: ['.css'],
  useHash: false,
  addHash: (assetPath, hash) => assetPath + '?' + hash,
  hash: undefined,
  usePublicPath: true,
  addPublicPath: (assetPath, publicPath) => url.resolve(publicPath, assetPath),
  publicPath: undefined,
  tags: [],
  links: [],
  scripts: [],
  metas: undefined
};
```

---
### Options

All options for this plugin are validated as soon as the plugin is instantiated.

The available options are:

|Name|Type|Default|Description|
|:--:|:--:|:-----:|:----------|
|**`append`**|`{Boolean}`|`true`|Whether to prepend or append the injected tags relative to any existing or webpack bundle tags (should be set to **false** when using any `script` tag **`external`**) |
|**`prependExternals`**|`{Boolean}`|`true`|Whether to default **`append`** to **false** for any `<script>` `tag` that has an **`external`** option specified|
|**`files`**|`{Array<String>}`|`[]`|If specified this plugin will only inject tags into the html-webpack-plugin instances that are injecting into these files  (uses [minimatch](https://github.com/isaacs/minimatch))|
|**`jsExtensions`**|`{String\|Array<String>}`|`['.js']`|The file extensions to use when determining if a `tag` in the `tags` option is a `script`|
|**`cssExtensions`**|`{String\|Array<String>}`|`['.css']`|The file extensions to use when determining if a `tag` in the `tags` option is a `link`|
|**`useHash`**|`{Boolean}`|`false`|Whether to inject the webpack `compilation.hash` into the tag paths|
|**`addHash`**|`{Function(assetPath:String, hash:String):String}`|`see above`|The function to call when injecting the `hash` into the tag paths|
|**`hash`**|`{Boolean\|String\|Function}`|`undefined`|Shortcut to specifying `useHash` and `addHash`|
|**`usePublicPath`**|`{Boolean}`|`true`|Whether to inject the (webpack) `publicPath` into the tag paths|
|**`addPublicPath`**|`{Function(assetPath:String, publicPath:String):String}`|`see above`|Whether to inject the `publicPath` into the tag paths|
|**`publicPath`**|`{Boolean\|String\|Function}`|`undefined`|Shortcut to specifying `usePublicPath` and `addPublicPath`|
|**`links`**|`{String\|Object\|Array<String\|Object>}`|`[]`|The tags to inject as `<link>` html tags|
|**`scripts`**|`{String\|Object\|Array<String\|Object>}`|`[]`|The tags to inject as `<script>` html tags|
|**`tags`**|`{String\|Object\|Array<String\|Object>}`|`[]`|The tags to inject as `<link>` or `<script>` html tags depending on the tag `type`|
|**`metas`**|`{Object\|Array<Object>}`|`undefined`|The tags to inject as `<meta>` html tags|

---

The **`append`** option controls whether tags are injected before or after `webpack` or `template` tags.

If multiple plugins are used with **`append`** set to **false** then the **tags will be injected in reverse order**.

This option has no effect on **`meta`** tags.

This sample `index.html` template:

```html
<html>
  <head><link href="template-link"></head>
  <body><script src="template-script"></script></body>
</html>
```

And this sample `webpack` config:
```js
{
  entry: {
    'app': 'app.js',
    'style': 'style.css' // also generates style.js
  },
  plugins: [
    new HtmlWebpackTagsPlugin({
      append: false, links: 'plugin-a-link', script: 'plugin-a-script'
    }),
    new HtmlWebpackTagsPlugin({
      append: false, links: 'plugin-b-link', script: 'plugin-b-script'
    }),
    new HtmlWebpackTagsPlugin({
      append: true, links: 'plugin-c-link', script: 'plugin-c-script'
    }),
    new HtmlWebpackTagsPlugin({
      append: true, links: 'plugin-d-link', script: 'plugin-d-script'
    })
  ]
}
```

Will generate approximately this html:
```html
<head>
  <link href="plugin-b-link">
  <link href="plugin-a-link">
  <link href="template-link">
  <link href="style.css">
  <link href="plugin-c-link">
  <link href="plugin-d-link">
</head>
<body>
  <script src="plugin-b-script"></script>
  <script src="plugin-a-script"></script>
  <script src="template-script"></script>
  <script src="app.js"></script>
  <script src="style.js"></script>
  <script src="plugin-c-link"></script>
  <script src="plugin-d-link"></script>
</body>
```

---

The **`hash`** option is a shortcut that overrides the **`useHash`** and **`addHash`** options:

```js
const shortcutFunction = {
  hash: (path, hash) => path + '?' + hash
}
const isTheSameAsFunction = {
  useHash: true,
  addHash: (path, hash) => path + '?' + hash
}

const shortcutDisabled = {
  hash: false
}
const isTheSameAsDisabled = {
  useHash: false,
}
```

---

The **`publicPath`** option is a shortcut that overrides the **`usePublicPath`** and **`addPublicPath`** options:

```js
const shortcutFunction = {
  publicPath: (path, publicPath) => publicPath + path
}
const isTheSameAsFunction = {
  usePublicPath: true,
  addPublicPath: (path, publicPath) => publicPath + path
}

const shortcutDisabled = {
  publicPath: false
}
const isTheSameAsDisabled = {
  usePublicPath: false,
}

const shortcutString = {
  publicPath: 'myValue'
}
const isTheSameAsString = {
  usePublicPath: true,
  addPublicPath: (path) => 'myValue' + path
}

```

---

When the **`tags`** option is used the type of the specified tag(s) is inferred either from the file extension or an optional **`type`** option that may be one of: `'js' \| 'css'`|

The inferred type is used to split the **`tags`** option into `tagLinks` and `tagScripts` that are injected **before** any specified **`links`** or **`scripts`** options.

The following are functionally equivalent:

```js
new HtmlWebpackTagsPlugin({
  tags: [
    'style-1.css',
    { path: 'script-2.js' },
    { path: 'script-3-not-js.css', type: 'js' },
    'style-4.css'
  ]
});

new HtmlWebpackTagsPlugin({
  links: [
    'style-1.css',
    'style-4.css'
  ],
  scripts: [
    { path: 'script-2.js' },
    { path: 'script-3-not-js.css' }
  ]
});
```
---

The `value` of the **`tags`**, **`links`** or **`scripts`** options can be specified in several ways:

- as a **String**:

```js
new HtmlWebpackTagsPlugin({ tags: 'style.css' });
```

- as an **Object**:

```js
new HtmlWebpackTagsPlugin({ links: { path: 'style.css' } });
```

- as an **Array** of **String**s or **Object**s:

```js
new HtmlWebpackTagsPlugin({
  scripts: [
    'aScript.js',
    {
      path: 'bScript.js'
    },
    'cScript.js'
  ]
});
```

---

When tags are specified as **Object**s, the following `tag object` options are available:

|Name|Type|Default|Description|
|:--:|:--:|:-----:|:----------|
|**`path`**|`{String}`|**`required*`**|The tag file path (used for `<link href />` or `<script src />` or `<meta content />`) **`(* not required for meta tags)`**|
|**`append`**|`{Boolean}`|`undefined`| This can be used to override the plugin level **`append`** option at a tag level|
|**`type`**|`{'js'\|'css'}`|`undefined`|For **`tags`** assets this may be used to specify whether the tag is a `link` or a `script`|
|**`glob`**, **`globPath`**|`{String, String}`|`undefined`|Together these two options specify a [glob](https://github.com/isaacs/node-glob) to run, inserting a tag with path for each match result|
|**`globFlatten`**|`{Boolean}`|`false`|When used with **`glob`** and **`globPath`** this flag controls whether glob-matched files are output with with full path (`false`) or just the filename (`true`)|
|**`attributes`**|`{Object}`|`undefined`|The attributes to be injected into the html tags. Some attributes are filtered out by `html-webpack-plugin`. **(Recommended:** set `html-webpack-plugin` option: `{ inject: true }`**)**|
|**`sourcePath`**|`{String}`|`undefined`|Specify a source path to be added as an entry to `html-webpack-plugin`. Useful to trigger webpack recompilation after the asset has changed|
|**`hash`**|`{Boolean\|String\|Function}`|`undefined`|Whether & how to inject the the webpack `compilation.hash` into the tag's path|
|**`publicPath`**|`{Boolean\|String\|Function}`|`undefined`|Whether & how to inject the (webpack) `publicPath` into the tag's path|
|**`external`**|`{Object({ packageName: String, variableName: String})}`|`undefined`|When specified for **script** tags causes `{ packageName: variableName }` to be added to the [webpack config's externals](https://webpack.js.org/configuration/externals/)|

---

The `tag object` **`hash`** option may be used to override the main **`hash`** option:

```js
const pluginOptions = {
  hash: true,
  tags: [
    {
      path: 'will-have-hash-injected'
    },
    {
      path: 'will-NOT-have-hash-injected',
      hash: false
    },
    {
      path: 'will-be-sandwhiched-by-hash',
      hash: (path, hash) => hash + path + hash
    }
  ]
}
// or
const pluginOptionsDisabled = {
  hash: false,
  tags: [
    {
      path: 'will-NOT-have-hash-injected'
    },
    {
      path: 'will-have-hash-injected',
      hash: true
    },
  ]
}
```

---

The `tag object` **`publicPath`** option may be used to override the main **`publicPath`** option:

```js
const pluginOptions = {
  publicPath: true,
  tags: [
    {
      path: 'will-have-public-path-injected'
    },
    {
      path: 'will-NOT-have-public-path-injected',
      publicPath: false
    },
    {
      path: 'will-be-sandwhiched-by-public-path',
      publicPath: (path, publicPath) => publicPath + path + publicPath
    }
  ]
}
// or
const pluginOptionsDisabled = {
  publicPath: false,
  tags: [
    {
      path: 'will-NOT-have-public-path-injected'
    },
    {
      path: 'will-have-public-path-injected',
      publicPath: true
    },
  ]
}
```

-----

Examples
-------

_____

Using `HtmlWebpackTagsPlugin` and `CopyWebpackPlugin` to inject copied assets from a `node_modules` package:

```javascript
plugins: [
  new CopyWebpackPlugin([
    { from: 'node_modules/bootstrap/dist/css', to: 'css/'},
    { from: 'node_modules/bootstrap/dist/fonts', to: 'fonts/'}
  ]),
  new HtmlWebpackPlugin(),
  new HtmlWebpackTagsPlugin({
    links: ['css/bootstrap.min.css', 'css/bootstrap-theme.min.css']
  })
]
```

_____

Using the **`append`** option set to **true** and **false** at the same time:

## **Note on Plugin Ordering**

When **`append`** is set to **false** and there are multiple instances of this plugins, the second plugin's tags will be inserted before the first plugin's tags.

```javascript
plugins: [
  new CopyWebpackPlugin([
    { from: 'node_modules/bootstrap/dist/css', to: 'css/'},
    { from: 'node_modules/bootstrap/dist/fonts', to: 'fonts/'}
  ]),
  new HtmlWebpackPlugin(),
  new HtmlWebpackTagsPlugin({
    links: ['css/bootstrap.min.css', 'css/bootstrap-theme.min.css'],
    append: false
  }),
  new HtmlWebpackTagsPlugin({
    links: ['css/custom.css'],
    append: true
  })
]
```

_____

Using custom **`jsExtensions`**:

```javascript
plugins: [
  new HtmlWebpackPlugin(),
  new HtmlWebpackTagsPlugin({
    tags: ['dist/output.js', 'lib/content.jsx'],
    jsExtensions: ['.js', '.jsx']
  })
]
```

_____

Using custom **`publicPath`**:

```javascript
plugins: [
  new CopyWebpackPlugin([
    { from: 'node_modules/bootstrap/dist/css', to: 'css/'},
    { from: 'node_modules/bootstrap/dist/fonts', to: 'fonts/'}
  ]),
  new HtmlWebpackPlugin(),
  new HtmlWebpackTagsPlugin({
    tags: ['css/bootstrap.min.css', 'css/bootstrap-theme.min.css'],
    publicPath: 'myPublicPath/'
  })
]
```

This will override `webpack`'s `publicPath` setting for the purposes of path prefixing.

_____

Or to inject `tag objects` **without** prepending the **`publicPath`**:

```javascript
plugins: [
  new HtmlWebpackPlugin(),
  new HtmlWebpackTagsPlugin({
    tags: ['css/no-public-path.min.css', 'http://some.domain.com.js'],
    publicPath: false
  })
]
```

_____

Manually specifying a tag `tag object` **`type`**:

```javascript
plugins: [
  new CopyWebpackPlugin([
    { from: 'node_modules/bootstrap/dist/js', to: 'js/'},
    { from: 'node_modules/bootstrap/dist/css', to: 'css/'},
    { from: 'node_modules/bootstrap/dist/fonts', to: 'fonts/'}
  ]),
  new HtmlWebpackPlugin(),
  new HtmlWebpackTagsPlugin({
    tags: [
      '/js/bootstrap.min.js',
      '/css/bootstrap.min.css',
      '/css/bootstrap-theme.min.css',
      {
        path: 'https://fonts.googleapis.com/css?family=Material+Icons',
        type: 'css'
      }
    ]
  })
]
```

_____

Adding custom **`attributes`** to `tag objects`:

The bootstrap-theme `<link>` tag will be given an `id="bootstrapTheme"` attribute.

```javascript
plugins: [
  new CopyWebpackPlugin([
    { from: 'node_modules/bootstrap/dist/css', to: 'css/'},
    { from: 'node_modules/bootstrap/dist/fonts', to: 'fonts/'}
  ]),
  new HtmlWebpackPlugin(),
  new HtmlWebpackTagsPlugin({
    tags: [
      '/css/bootstrap.min.css',
      { path: '/css/bootstrap-theme.min.css', attributes: { id: 'bootstrapTheme' } }
    ],
    append: false,
    publicPath: ''
  })
]
```

_____

Using the **`hash`** option to inject the webpack compilation hash:

When the **`hash`** option is set to `true`, tag paths will be injected with a hash value.

The **`addHash`** option can be used to control how the hash is injected.

```javascript
  plugins: [
    new CopyWebpackPlugin([
      { from: 'node_modules/bootstrap/dist/css', to: 'css/'},
      { from: 'node_modules/bootstrap/dist/fonts', to: 'fonts/'}
    ]),
    new HtmlWebpackPlugin(),
    new HtmlWebpackTagsPlugin({
      tags: ['css/bootstrap.min.css', 'css/bootstrap-theme.min.css'],
      append: false,
      hash: true
    })
  ]
```

_____

Using the **`hash`** option to customize the injection of the webpack compilation hash:

When the **`hash`** option is set to a `function`, tag paths will be replaced with the result of executing that function.

```javascript
plugins: [
  new CopyWebpackPlugin([
    { from: 'somepath/somejsfile.js', to: 'js/somejsfile.[hash].js' },
    { from: 'somepath/somecssfile.css', to: 'css/somecssfile.[hash].css' }
  ]),
  new HtmlWebpackPlugin(),
  new HtmlWebpackTagsPlugin({
    tags: [{ path: 'js', glob: '*.js', globPath: 'somepath' }],
    tags: [{ path: 'css', glob: '*.css', globPath: 'somepath' }],
    append: false,
    hash: function(assetName, hash) {
      assetName = assetName.replace(/\.js$/, '.' + hash + '.js');
      assetName = assetName.replace(/\.css$/, '.' + hash + '.css');
      return assetName;
    }
  })
]
```

_____

Specifying specific `html-webpack-plugin` instances to inject to with the **`files`** option:

```javascript
plugins: [
  new CopyWebpackPlugin([
    { from: 'node_modules/bootstrap/dist/css', to: 'css/'},
    { from: 'node_modules/bootstrap/dist/fonts', to: 'fonts/'}
  ]),
  new HtmlWebpackPlugin({
    filename: 'a/index.html'
  }),
  new HtmlWebpackPlugin({
    filename: 'b/index.html'
  }),
  new HtmlWebpackTagsPlugin({
    files: ['a/**/*.html'],
    tags: ['css/a.css'],
    append: true
  }),
  new HtmlWebpackTagsPlugin({
    files: ['b/**/*.html'],
    tags: ['css/b.css'],
    append: true
  })
]
```

_____

Specifying `tag object` path searches usings a **`glob`**:

Note that since `copy-webpack-plugin` does not actually copy the files to webpack's output directory until *after* `html-webpack-plugin` has completed, it is necessary to use the **`globPath`** to retrieve filename matches relative to the original location of any such files.

```javascript
plugins: [
  new CopyWebpackPlugin([
    { from: 'node_modules/bootstrap/dist/css', to: 'css/'},
    { from: 'node_modules/bootstrap/dist/fonts', to: 'fonts/'}
  ]),
  new HtmlWebpackPlugin(),
  new HtmlWebpackTagsPlugin({
    tags: [{ path: 'css', glob: '*.css', globPath: 'node_modules/bootstrap/dist/css/' }],
    append: true
  })
]
```

_____

Using the **`links`** option to inject `link` tags:

```javascript
output: {
  publicPath: '/my-public-path/'
},
plugins: [
  new CopyWebpackPlugin([
    { from: 'node_modules/bootstrap/dist/css', to: 'css/'},
    { from: 'node_modules/bootstrap/dist/fonts', to: 'fonts/'}
  ]),
  new HtmlWebpackPlugin(),
  new HtmlWebpackTagsPlugin({
    tags: [],
    links: [
      {
        path: 'asset/path',
        attributes: {
          rel: 'icon'
        }
      },
      {
        path: '/absolute/asset/path',
        publicPath: false,
        attributes: {
          rel: 'manifest'
        }
      }
    ]
  })
]
```

Will append the following `<link>` elements into the index template html

```html
<head>
  <!-- previous header content -->
  <link rel="icon" href="/my-public-path/asset/path">
  <link rel="manifest" href="/absolute/asset/path">
</head>
```

Note that the second link's href was not prefixed with the webpack `publicPath` because the second link asset's **`publicPath`** was set to `false`.


_____

Using the **`scripts`** option to inject `script` tags:

```javascript
output: {
  publicPath: '/my-public-path/'
},
plugins: [
  new CopyWebpackPlugin([
    { from: 'node_modules/bootstrap/dist/js', to: 'js/'}
  ]),
  new HtmlWebpackPlugin(),
  new HtmlWebpackTagsPlugin({
    tags: [],
    scripts: [
      {
        path: 'asset/path',
        attributes: {
          type: 'text/javascript'
        }
      }
    ]
  })
]
```

Will append the following `<script>` element into the index template html

```html
<body>
  <!-- previous body content -->
  <script src="/my-public-path/asset/path" type="text/javascript"></script>
</body>
```


_____

Specifying **`scripts`** with **`external`** options:

```javascript
output: {
  publicPath: '/my-public-path/'
},
plugins: [
  new CopyWebpackPlugin([
    { from: 'node_modules/bootstrap/dist/js', to: 'js/'}
  ]),
  new HtmlWebpackPlugin(),
  new HtmlWebpackTagsPlugin({
    tags: [],
    scripts: [
      {
        path: 'asset/path',
        external: {
          packageName: 'react',
          variableName: 'React'
        },
        attributes: {
          type: 'text/javascript'
        }
      }
    ]
  })
]
```

Will add the following `properties` to the `webpack.compilation.options.externals`:

```js
const compilationConfig = {
  ...otherProperties,
  externals: {
    "react": "React"
  }
};
```

This can be useful to control which packages webpack is bundling versus ones you can serve from a CDN.

Note that `script` tags with **`external`** specified need to be placed **before** the webpack bundle tags.

This means that you should always set **`append`** to **false** when using the `script` **`external`** option.

The **`prependExternals`** option was added in `2.0.10` to handle this case automatically.


_____

Using the **`metas`** option to inject `meta` tags:

```javascript
output: {
  publicPath: '/my-public-path/'
},
plugins: [
  new CopyWebpackPlugin([
    { from: 'node_modules/bootstrap/dist/js', to: 'js/'}
  ]),
  new HtmlWebpackPlugin(),
  new HtmlWebpackTagsPlugin({
    metas: [
      {
        path: 'asset/path',
        attributes: {
          name: 'the-meta-name'
        }
      }
    ]
  })
]
```

Will inject the following `<meta>` element into the index template html

```html
<head>
  <!-- previous header content -->
  <meta content="/my-public-path/asset/path" name="the-meta-name">
</head>
```

Note that the **`append`** settings has no effect on how the `<meta>` elements are injected.


_____

Caveats
-------

___

#### Plugin Ordering

Some users have encountered issues with plugin ordering.

- It is advisable to always place any `HtmlWebpackPlugin` plugins **before** any `HtmlWebpackTagsPlugin` plugins in your webpack config.

- When **`append`** is **false** tags are injected before any other tags. This means that if you have two instances of this plugin both with append set to false, then the `second` plugin's tags will be injected **before** the `first` plugin's tags.

---

#### Webpack `externals`

Setting the **`external`** option for a `script` `tag object` requires caution to ensure that the scripts are in the correct order.

- It is advisable to always set **`append`** to **false** so that `external` \<script\> tags are always inserted **before** the `webpack` bundle \<script\> tags.

- The order that you use when you specify a list of external links matters. For example, `<script src="react.js"/>` should come before `<script src="react-router.s"/>` if `react-router` has a peer dependency on `react`.

---

#### HtmlWebpackPlugin `inject` option

Changing HtmlWebpackPlugin **`inject`** option from its `default value` of **true** may cause issues.

- This plugin **recommends** that the HtmlWebpackPlugin **`inject`** option to be **true** for attribute injection to work.

**Disabling injection** means that you are agreeing to template how the tags should be generated in your `templates/index.html` file like this:

```html
<html>
  <head>
    <!-- other head content -->
    <% for (var cssIndex = 0; cssIndex < htmlWebpackPlugin.files.css.length; cssIndex++) { %>
    <link rel="stylesheet" href="<%= htmlWebpackPlugin.files.css[cssIndex] %>">
    <% } %>
  </head>
  <body>
    <!-- other body content -->
    <% for (var jsIndex = 0; jsIndex < htmlWebpackPlugin.files.js.length; jsIndex++) { %>
    <script src="<%= htmlWebpackPlugin.files.js[jsIndex] %>"></script>
    <% } %>
  </body>
</html>
```

The default templating engine for `html-webpack-plugin` seems to be based on **`lodash`**.

With the above template we might use the following `webpack` config which **disables** **`inject`**:

```javascript
output: {
  publicPath: '/the-public-path/'
},
plugins: [
  new HtmlWebpackPlugin({ <b>inject: false</b> }),
  new HtmlWebpackTagsPlugin({
    tags: [{ path: 'css/bootstrap-theme.min.css', attributes: { id: 'bootstrapTheme' } }],
    links: [{ href: 'the-ref', attributes: { rel: 'icon' } }],
    append: true
  })
]
```

The problem is that the `template syntax` does not seem to allow injection of more than `one attribute value`, namely the `path` (**`href`** or **`src`**)

This means it will **generate** an `index.html` that is **missing** all of the script **`attributes`** like this:

```html
<head>
  <link href="/the-public-path/css/bootstrap-theme.min.css">
  <link href="/the-public-path/the-ref">
</head>
```

If the templating engine supports injection of **entire tags** instead of just the `href`/`src` attribute value then working with **`inject`** set to **false** may be possible.