UNPKG

htmlnano

Version:

Modular HTML minifier, built on top of the PostHTML

257 lines (254 loc) 5.93 kB
Object.defineProperty(exports, '__esModule', { value: true }); const caseInsensitiveAttributes = { autocomplete: [ 'form' ], charset: [ 'meta', 'script' ], contenteditable: null, crossorigin: [ 'audio', 'img', 'link', 'script', 'video' ], dir: null, draggable: null, dropzone: null, fetchpriority: [ 'img', 'link', 'script' ], formmethod: [ 'button', 'input' ], inputmode: [ 'input', 'textarea' ], kind: [ 'track' ], method: [ 'form' ], preload: [ 'audio', 'video' ], referrerpolicy: null, sandbox: [ 'iframe' ], spellcheck: null, scope: [ 'th' ], shape: [ 'area' ], sizes: [ 'link' ], step: [ 'input' ], translate: null, type: [ 'a', 'link', 'button', 'embed', 'object', 'script', 'source', 'style', 'input', 'menu', 'menuitem' ], wrap: [ 'textarea' ] }; // https://html.spec.whatwg.org/#invalid-value-default const invalidValueDefault = { crossorigin: { tag: null, default: 'anonymous', valid: [ '', 'anonymous', 'use-credentials' ] }, // https://html.spec.whatwg.org/#referrer-policy-attributes // The attribute's invalid value default and missing value default are both the empty string state. referrerpolicy: { tag: null, default: '', valid: [ '', 'url', 'origin', 'no-referrer', 'no-referrer-when-downgrade', 'same-origin', 'origin-when-cross-origin', 'strict-origin-when-cross-origin', 'unsafe-url' ] }, // https://html.spec.whatwg.org/#lazy-loading-attributes loading: { tag: [ 'img', 'iframe' ], default: 'eager', valid: [ 'lazy', 'eager' ] }, // https://html.spec.whatwg.org/#the-img-element // https://html.spec.whatwg.org/#image-decoding-hint decoding: { tag: [ 'img' ], default: 'auto', valid: [ 'auto', 'sync', 'async' ] }, // https://html.spec.whatwg.org/#the-track-element kind: { tag: [ 'track' ], default: 'metadata', valid: [ 'subtitles', 'captions', 'descriptions', 'chapters', 'metadata' ] }, type: { tag: [ 'button' ], default: 'submit', valid: [ 'submit', 'reset', 'button' ] }, wrap: { tag: [ 'textarea' ], default: 'soft', valid: [ 'soft', 'hard' ] }, // https://html.spec.whatwg.org/#the-hidden-attribute hidden: { tag: null, default: 'hidden', valid: [ 'hidden', 'until-found' ] }, // https://html.spec.whatwg.org/#lazy-loading-attributes // https://html.spec.whatwg.org/#fetch-priority-attributes fetchpriority: { tag: [ 'img', 'link', 'script' ], default: 'auto', valid: [ 'high', 'low', 'auto' ] }, // https://html.spec.whatwg.org/#autocapitalization autocapitalize: { tag: null, default: 'sentences', valid: [ 'none', 'off', 'on', 'sentences', 'words', 'characters' ] }, // https://html.spec.whatwg.org/#the-marquee-element behavior: { tag: [ 'marquee' ], default: 'scroll', valid: [ 'scroll', 'slide', 'alternate' ] }, direction: { tag: [ 'marquee' ], default: 'left', valid: [ 'left', 'right', 'up', 'down' ] } }; const mod = { onAttrs () { return (attrs, node)=>{ const newAttrs = attrs; Object.entries(attrs).forEach(([attrName, attrValue])=>{ let newAttrValue = attrValue; const hasCaseInsensitive = Object.hasOwnProperty.call(caseInsensitiveAttributes, attrName) && (caseInsensitiveAttributes[attrName] === null || node.tag && caseInsensitiveAttributes[attrName].includes(node.tag)); const hasInvalidValueDefault = Object.hasOwnProperty.call(invalidValueDefault, attrName); const invalidMeta = hasInvalidValueDefault ? invalidValueDefault[attrName] : undefined; const appliesInvalidValueDefault = Boolean(invalidMeta && (invalidMeta.tag === null || node && node.tag && invalidMeta.tag.includes(node.tag))); const shouldNormalizeCase = hasCaseInsensitive || appliesInvalidValueDefault; if (typeof attrValue === 'string' && shouldNormalizeCase) { newAttrValue = attrValue.trim().toLowerCase(); } if (appliesInvalidValueDefault && invalidMeta) { if (typeof newAttrValue !== 'string' || !invalidMeta.valid.includes(newAttrValue)) { newAttrValue = invalidMeta.default; } } newAttrs[attrName] = newAttrValue; }); return newAttrs; }; } }; exports.default = mod;