return (/^on[a-z]+/).test(attrName);
}
- function canRemoveAttributeQuotes(value, isLast) {
+ function canRemoveAttributeQuotes(value) {
// http://mathiasbynens.be/notes/unquoted-attribute-values
- return (/^[^\x20\t\n\f\r"'`=<>]+$/).test(value) &&
- // make sure trailing slash is not interpreted as HTML self-closing tag
- !(isLast && (/\/$/).test(value));
+ return (/^[^\x20\t\n\f\r"'`=<>]+$/).test(value);
}
function attributesInclude(attributes, attribute) {
return !(/^(?:pre|textarea)$/.test(tag));
}
- function normalizeAttribute(attr, attrs, tag, unarySlash, index, options, isLast) {
+ function normalizeAttribute(attr, attrs, tag, hasUnarySlash, index, options, isLast) {
var attrName = options.caseSensitive ? attr.name : attr.name.toLowerCase(),
attrValue = options.preventAttributesEscaping ? attr.value : attr.escaped,
attrQuote = options.preventAttributesEscaping ? attr.quote : (options.quoteCharacter === '\'' ? '\'' : '"'),
attrFragment,
- emittedAttrValue,
- isTerminalOfUnarySlash = unarySlash && index === attrs.length - 1;
+ emittedAttrValue;
if ((options.removeRedundantAttributes &&
isAttributeRedundant(tag, attrName, attrValue, attrs))
attrValue = cleanAttributeValue(tag, attrName, attrValue, options, attrs);
if (attrValue !== undefined && !options.removeAttributeQuotes ||
- !canRemoveAttributeQuotes(attrValue, isLast) || isTerminalOfUnarySlash) {
+ !canRemoveAttributeQuotes(attrValue)) {
emittedAttrValue = attrQuote + attrValue + attrQuote;
}
+ // make sure trailing slash is not interpreted as HTML self-closing tag
+ else if (isLast && (hasUnarySlash || /\/$/.test(attrValue))) {
+ emittedAttrValue = attrValue + ' ';
+ }
else {
emittedAttrValue = attrValue;
}
}
var openTag = '<' + tag;
- var closeTag = ((unarySlash && options.keepClosingSlash) ? '/' : '') + '>';
+ var hasUnarySlash = unarySlash && options.keepClosingSlash;
+ var closeTag = (hasUnarySlash ? '/' : '') + '>';
if (attrs.length === 0) {
openTag += closeTag;
}
if (lint) {
lint.testAttribute(tag, attrs[i].name.toLowerCase(), attrs[i].escaped);
}
- token = normalizeAttribute(attrs[i], attrs, tag, unarySlash, i, options, isLast);
+ token = normalizeAttribute(attrs[i], attrs, tag, hasUnarySlash, i, options, isLast);
if (isLast) {
token += closeTag;
}
equal(minify(input, { removeAttributeQuotes: true }), '<a href=http://example.com/ title=blah>\nfoo\n\n</a>');
input = '<a title="blah" href="http://example.com/">\nfoo\n\n</a>';
- equal(minify(input, { removeAttributeQuotes: true }), '<a title=blah href="http://example.com/">\nfoo\n\n</a>');
+ equal(minify(input, { removeAttributeQuotes: true }), '<a title=blah href=http://example.com/ >\nfoo\n\n</a>');
input = '<p class=foo|bar:baz></p>';
equal(minify(input, { removeAttributeQuotes: true }), '<p class=foo|bar:baz></p>');
test('keeping trailing slashes in tags', function() {
equal(minify('<img src="test"/>', { keepClosingSlash: true }), '<img src="test"/>');
// https://github.com/kangax/html-minifier/issues/233
- equal(minify('<img src="test"/>', { keepClosingSlash: true, removeAttributeQuotes: true }), '<img src="test"/>');
- equal(minify('<img title="foo" src="test"/>', { keepClosingSlash: true, removeAttributeQuotes: true }), '<img title=foo src="test"/>');
+ equal(minify('<img src="test"/>', { keepClosingSlash: true, removeAttributeQuotes: true }), '<img src=test />');
+ equal(minify('<img title="foo" src="test"/>', { keepClosingSlash: true, removeAttributeQuotes: true }), '<img title=foo src=test />');
});
test('removing optional tags', function() {