diff --git a/src/server/generators/attribute.js b/src/server/generators/attribute.js
index 618e8d5..03e29bf 100644
--- a/src/server/generators/attribute.js
+++ b/src/server/generators/attribute.js
@@ -1,3 +1,4 @@
+import { booleanHtmlAttributes } from '../../shared/constants'
import { isUndefined } from '../../shared/typeof'
/**
@@ -17,7 +18,7 @@ export default function attributeGenerator({ attribute } = {}, type, data) {
if (data.hasOwnProperty(attr)) {
watchedAttrs.push(attr)
- attributeStr += isUndefined(data[attr])
+ attributeStr += isUndefined(data[attr]) || booleanHtmlAttributes.includes(attr)
? attr
: `${attr}="${data[attr]}"`
diff --git a/src/shared/constants.js b/src/shared/constants.js
index 190e9fd..42bcc0c 100644
--- a/src/shared/constants.js
+++ b/src/shared/constants.js
@@ -51,3 +51,48 @@ export const tagsWithInnerContent = ['noscript', 'script', 'style']
// Attributes which are inserted as childNodes instead of HTMLAttribute
export const tagAttributeAsInnerContent = ['innerHTML', 'cssText']
+
+// from: https://github.com/kangax/html-minifier/blob/gh-pages/src/htmlminifier.js#L202
+export const booleanHtmlAttributes = [
+ 'allowfullscreen',
+ 'async',
+ 'autofocus',
+ 'autoplay',
+ 'checked',
+ 'compact',
+ 'controls',
+ 'declare',
+ 'default',
+ 'defaultchecked',
+ 'defaultmuted',
+ 'defaultselected',
+ 'defer',
+ 'disabled',
+ 'enabled',
+ 'formnovalidate',
+ 'hidden',
+ 'indeterminate',
+ 'inert',
+ 'ismap',
+ 'itemscope',
+ 'loop',
+ 'multiple',
+ 'muted',
+ 'nohref',
+ 'noresize',
+ 'noshade',
+ 'novalidate',
+ 'nowrap',
+ 'open',
+ 'pauseonexit',
+ 'readonly',
+ 'required',
+ 'reversed',
+ 'scoped',
+ 'seamless',
+ 'selected',
+ 'sortable',
+ 'truespeed',
+ 'typemustmatch',
+ 'visible'
+]
diff --git a/test/utils/meta-info-data.js b/test/utils/meta-info-data.js
index 5b67346..cff7c3a 100644
--- a/test/utils/meta-info-data.js
+++ b/test/utils/meta-info-data.js
@@ -141,7 +141,13 @@ const metaInfoData = {
},
change: {
data: [{ src: 'src', async: true, defer: true, [defaultOptions.tagIDKeyName]: 'content2' }],
- expect: ['']
+ expect: [''],
+ test(side, defaultTest) {
+ if (side === 'client') {
+ // jsdom doesnt generate valid boolean attributes
+ this.expect[0] = this.expect[0].replace('defer', 'defer="true"')
+ }
+ }
},
remove: {
data: [],