Skip to content

Commit aa6e78d

Browse files
feat: omit html tag attribute with null/undefined/false value
Refs #1598
1 parent 33d69f4 commit aa6e78d

File tree

3 files changed

+74
-6
lines changed

3 files changed

+74
-6
lines changed

lib/html-tags.js

+5-5
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,12 @@ const voidTags = ['area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'k
2525
* A tag element according to the htmlWebpackPlugin object notation
2626
*
2727
* @param xhtml {boolean}
28-
* Wether the generated html should add closing slashes to be xhtml compliant
28+
* Whether the generated html should add closing slashes to be xhtml compliant
2929
*/
3030
function htmlTagObjectToString (tagDefinition, xhtml) {
3131
const attributes = Object.keys(tagDefinition.attributes || {})
3232
.filter(function (attributeName) {
33-
return tagDefinition.attributes[attributeName] !== false;
33+
return tagDefinition.attributes[attributeName] === '' || tagDefinition.attributes[attributeName];
3434
})
3535
.map(function (attributeName) {
3636
if (tagDefinition.attributes[attributeName] === true) {
@@ -49,13 +49,13 @@ function htmlTagObjectToString (tagDefinition, xhtml) {
4949
* @param {string} tagName
5050
* the name of the tag e.g. 'div'
5151
*
52-
* @param {{[attributeName: string]: string|boolean}} [attributes]
52+
* @param {{[attributeName: string]: string|boolean|null|undefined}} [attributes]
5353
* tag attributes e.g. `{ 'class': 'example', disabled: true }`
5454
*
5555
* @param {string} [innerHTML]
5656
*
57-
* @param {{[attributeName: string]: string|boolean}} [meta]
58-
* meta information about the tag e.g. `{ 'pluhin': 'html-webpack-plugin' }`
57+
* @param {{[attributeName: string]: string|boolean|null|undefined}} [meta]
58+
* meta information about the tag e.g. `{ 'plugin': 'html-webpack-plugin' }`
5959
*
6060
* @returns {HtmlTagObject}
6161
*/

spec/basic.spec.js

+68
Original file line numberDiff line numberDiff line change
@@ -1232,6 +1232,74 @@ describe('HtmlWebpackPlugin', () => {
12321232
null, done, false, false);
12331233
});
12341234

1235+
it('allows events to remove an attribute by setting it to null', done => {
1236+
const examplePlugin = {
1237+
apply: function (compiler) {
1238+
compiler.hooks.compilation.tap('HtmlWebpackPlugin', compilation => {
1239+
HtmlWebpackPlugin.getHooks(compilation).alterAssetTags.tapAsync('HtmlWebpackPluginTest', (pluginArgs, callback) => {
1240+
pluginArgs.assetTags.scripts = pluginArgs.assetTags.scripts.map(tag => {
1241+
if (tag.tagName === 'script') {
1242+
tag.attributes.async = null;
1243+
}
1244+
return tag;
1245+
});
1246+
callback(null, pluginArgs);
1247+
});
1248+
});
1249+
}
1250+
};
1251+
testHtmlPlugin({
1252+
mode: 'production',
1253+
entry: {
1254+
app: path.join(__dirname, 'fixtures/index.js')
1255+
},
1256+
output: {
1257+
path: OUTPUT_DIR,
1258+
filename: '[name]_bundle.js'
1259+
},
1260+
plugins: [
1261+
new HtmlWebpackPlugin(),
1262+
examplePlugin
1263+
]
1264+
},
1265+
[/<script defer="defer" src="app_bundle.js"><\/script>[\s]*<\/head>/],
1266+
null, done, false, false);
1267+
});
1268+
1269+
it('allows events to remove an attribute by setting it to undefined', done => {
1270+
const examplePlugin = {
1271+
apply: function (compiler) {
1272+
compiler.hooks.compilation.tap('HtmlWebpackPlugin', compilation => {
1273+
HtmlWebpackPlugin.getHooks(compilation).alterAssetTags.tapAsync('HtmlWebpackPluginTest', (pluginArgs, callback) => {
1274+
pluginArgs.assetTags.scripts = pluginArgs.assetTags.scripts.map(tag => {
1275+
if (tag.tagName === 'script') {
1276+
tag.attributes.async = undefined;
1277+
}
1278+
return tag;
1279+
});
1280+
callback(null, pluginArgs);
1281+
});
1282+
});
1283+
}
1284+
};
1285+
testHtmlPlugin({
1286+
mode: 'production',
1287+
entry: {
1288+
app: path.join(__dirname, 'fixtures/index.js')
1289+
},
1290+
output: {
1291+
path: OUTPUT_DIR,
1292+
filename: '[name]_bundle.js'
1293+
},
1294+
plugins: [
1295+
new HtmlWebpackPlugin(),
1296+
examplePlugin
1297+
]
1298+
},
1299+
[/<script defer="defer" src="app_bundle.js"><\/script>[\s]*<\/head>/],
1300+
null, done, false, false);
1301+
});
1302+
12351303
it('provides the options to the afterEmit event', done => {
12361304
let eventArgs;
12371305
const examplePlugin = {

typings.d.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,7 @@ declare namespace HtmlWebpackPlugin {
263263
* E.g. `{'disabled': true, 'value': 'demo'}`
264264
*/
265265
attributes: {
266-
[attributeName: string]: string | boolean;
266+
[attributeName: string]: string | boolean | null | undefined;
267267
};
268268
/**
269269
* The tag name e.g. `'div'`

0 commit comments

Comments
 (0)