within a )
if (options.collapseWhitespace) {
if (!_canTrimWhitespace(tag, attrs)) {
stackNoTrimWhitespace.push(tag);
}
if (!_canCollapseWhitespace(tag, attrs)) {
stackNoCollapseWhitespace.push(tag);
}
}
var openTag = '<' + tag;
var closeTag = ((unarySlash && options.keepClosingSlash) ? '/' : '') + '>';
if ( attrs.length === 0) {
openTag += closeTag;
}
buffer.push(openTag);
lint && lint.testElement(tag);
var token;
for ( var i = 0, len = attrs.length; i < len; i++ ) {
lint && lint.testAttribute(tag, attrs[i].name.toLowerCase(), attrs[i].escaped);
token = normalizeAttribute(attrs[i], attrs, tag, unarySlash, i, options);
if ( i === len - 1 ) {
token += closeTag;
}
buffer.push(token);
}
},
end: function( tag, attrs ) {
if (isIgnoring) {
buffer.push('' + tag + '>');
return;
}
// check if current tag is in a whitespace stack
if (options.collapseWhitespace) {
if (stackNoTrimWhitespace.length &&
tag === stackNoTrimWhitespace[stackNoTrimWhitespace.length - 1]) {
stackNoTrimWhitespace.pop();
}
if (stackNoCollapseWhitespace.length &&
tag === stackNoCollapseWhitespace[stackNoCollapseWhitespace.length - 1]) {
stackNoCollapseWhitespace.pop();
}
}
var isElementEmpty = currentChars === '' && tag === currentTag;
if ((options.removeEmptyElements && isElementEmpty && canRemoveElement(tag, attrs))) {
// remove last "element" from buffer, return
for ( var i = buffer.length - 1; i >= 0; i-- ) {
if ( /^<[^\/!]/.test(buffer[i]) ) {
buffer.splice(i);
break;
}
}
return;
}
else if (options.removeOptionalTags && isOptionalTag(tag)) {
// noop, leave start tag in buffer
return;
}
else {
// push end tag to buffer
buffer.push('' + (options.caseSensitive ? tag : tag.toLowerCase()) + '>');
results.push.apply(results, buffer);
}
// flush buffer
buffer.length = 0;
currentChars = '';
},
chars: function( text, prevTag, nextTag ) {
prevTag = prevTag === '' ? 'comment' : prevTag;
nextTag = nextTag === '' ? 'comment' : nextTag;
if (isIgnoring) {
buffer.push(text);
return;
}
if (currentTag === 'script' || currentTag === 'style') {
if (options.removeCommentsFromCDATA) {
text = removeComments(text, currentTag);
}
if (options.removeCDATASectionsFromCDATA) {
text = removeCDATASections(text);
}
if (options.processScripts) {
text = processScript(text, options, currentAttrs);
}
}
if (currentTag === 'script' && options.minifyJS) {
text = minifyJS(text, options.minifyJS);
}
if (currentTag === 'style' && options.minifyCSS) {
text = minifyCSS(text, options.minifyCSS);
}
if (options.collapseWhitespace) {
if (!stackNoTrimWhitespace.length) {
text = ((prevTag && prevTag !== 'comment') || (nextTag && nextTag !== 'comment')) ?
collapseWhitespaceSmart(text, prevTag, nextTag, options)
: trimWhitespace(text);
}
if (!stackNoCollapseWhitespace.length) {
text = !(prevTag && nextTag || nextTag === 'html') ? collapseWhitespace(text) : text;
}
}
currentChars = text;
lint && lint.testChars(text);
buffer.push(text);
},
comment: function( text, nonStandard ) {
var prefix = nonStandard ? '' : '-->';
if (/^\s*htmlmin:ignore/.test(text)) {
isIgnoring = !isIgnoring;
if (!options.removeComments) {
buffer.push('');
}
return;
}
if (options.removeComments) {
if (isConditionalComment(text)) {
text = prefix + cleanConditionalComment(text) + suffix;
}
else if (isIgnoredComment(text, options)) {
text = '';
}
else {
text = '';
}
}
else {
text = prefix + text + suffix;
}
buffer.push(text);
},
doctype: function(doctype) {
buffer.push(options.useShortDoctype ? '' : collapseWhitespace(doctype));
},
customAttrAssign: options.customAttrAssign,
customAttrSurround: options.customAttrSurround
});
results.push.apply(results, buffer);
var str = joinResultSegments(results, options);
log('minified in: ' + (new Date() - t) + 'ms');
return str;
}
function joinResultSegments( results, options ) {
var str;
var maxLineLength = options.maxLineLength;
if ( maxLineLength ) {
var token;
var lines = [];
var line = '';
for ( var i = 0, len = results.length; i < len; i++ ) {
token = results[i];
if ( line.length + token.length < maxLineLength ) {
line += token;
}
else {
lines.push(line.replace(/^\n/, ''));
line = token;
}
}
lines.push(line);
str = lines.join('\n');
}
else {
str = results.join('');
}
return str;
}
// for CommonJS enviroments, export everything
if ( typeof exports !== 'undefined' ) {
exports.minify = minify;
}
else {
global.minify = minify;
}
}(this));
/*!
* HTMLLint (to be used in conjunction with HTMLMinifier)
*
* Copyright (c) 2010-2013 Juriy "kangax" Zaytsev
* Licensed under the MIT license.
*
*/
(function(global) {
'use strict';
function isPresentationalElement(tag) {
return (/^(?:big|small|hr|blink|marquee)$/).test(tag);
}
function isDeprecatedElement(tag) {
return (/^(?:applet|basefont|center|dir|font|isindex|strike)$/).test(tag);
}
function isEventAttribute(attrName) {
return (/^on[a-z]+/).test(attrName);
}
function isStyleAttribute(attrName) {
return ('style' === attrName.toLowerCase());
}
function isDeprecatedAttribute(tag, attrName) {
return (
(attrName === 'align' &&
(/^(?:caption|applet|iframe|img|imput|object|legend|table|hr|div|h[1-6]|p)$/).test(tag)) ||
(attrName === 'alink' && tag === 'body') ||
(attrName === 'alt' && tag === 'applet') ||
(attrName === 'archive' && tag === 'applet') ||
(attrName === 'background' && tag === 'body') ||
(attrName === 'bgcolor' && (/^(?:table|t[rdh]|body)$/).test(tag)) ||
(attrName === 'border' && (/^(?:img|object)$/).test(tag)) ||
(attrName === 'clear' && tag === 'br') ||
(attrName === 'code' && tag === 'applet') ||
(attrName === 'codebase' && tag === 'applet') ||
(attrName === 'color' && (/^(?:base(?:font)?)$/).test(tag)) ||
(attrName === 'compact' && (/^(?:dir|[dou]l|menu)$/).test(tag)) ||
(attrName === 'face' && (/^base(?:font)?$/).test(tag)) ||
(attrName === 'height' && (/^(?:t[dh]|applet)$/).test(tag)) ||
(attrName === 'hspace' && (/^(?:applet|img|object)$/).test(tag)) ||
(attrName === 'language' && tag === 'script') ||
(attrName === 'link' && tag === 'body') ||
(attrName === 'name' && tag === 'applet') ||
(attrName === 'noshade' && tag === 'hr') ||
(attrName === 'nowrap' && (/^t[dh]$/).test(tag)) ||
(attrName === 'object' && tag === 'applet') ||
(attrName === 'prompt' && tag === 'isindex') ||
(attrName === 'size' && (/^(?:hr|font|basefont)$/).test(tag)) ||
(attrName === 'start' && tag === 'ol') ||
(attrName === 'text' && tag === 'body') ||
(attrName === 'type' && (/^(?:li|ol|ul)$/).test(tag)) ||
(attrName === 'value' && tag === 'li') ||
(attrName === 'version' && tag === 'html') ||
(attrName === 'vlink' && tag === 'body') ||
(attrName === 'vspace' && (/^(?:applet|img|object)$/).test(tag)) ||
(attrName === 'width' && (/^(?:hr|td|th|applet|pre)$/).test(tag))
);
}
function isInaccessibleAttribute(attrName, attrValue) {
return (
attrName === 'href' &&
(/^\s*javascript\s*:\s*void\s*(\s+0|\(\s*0\s*\))\s*$/i).test(attrValue)
);
}
function Lint() {
this.log = [ ];
this._lastElement = null;
this._isElementRepeated = false;
}
Lint.prototype.testElement = function(tag) {
if (isDeprecatedElement(tag)) {
this.log.push(
'Found deprecated <' +
tag + '>
element'
);
}
else if (isPresentationalElement(tag)) {
this.log.push(
'Found presentational <' +
tag + '>
element'
);
}
else {
this.checkRepeatingElement(tag);
}
};
Lint.prototype.checkRepeatingElement = function(tag) {
if (tag === 'br' && this._lastElement === 'br') {
this._isElementRepeated = true;
}
else if (this._isElementRepeated) {
this._reportRepeatingElement();
this._isElementRepeated = false;
}
this._lastElement = tag;
};
Lint.prototype._reportRepeatingElement = function() {
this.log.push('Found <br>
sequence. Try replacing it with styling.');
};
Lint.prototype.testAttribute = function(tag, attrName, attrValue) {
if (isEventAttribute(attrName)) {
this.log.push(
'Found event attribute (' +
attrName + ') on <' + tag + '>
element.'
);
}
else if (isDeprecatedAttribute(tag, attrName)) {
this.log.push(
'Found deprecated ' +
attrName + ' attribute on <' + tag + '>
element.'
);
}
else if (isStyleAttribute(attrName)) {
this.log.push(
'Found style attribute on <' +
tag + '>
element.'
);
}
else if (isInaccessibleAttribute(attrName, attrValue)) {
this.log.push(
'Found inaccessible attribute ' +
'(on <' + tag + '>
element).'
);
}
};
Lint.prototype.testChars = function(chars) {
this._lastElement = '';
if (/( \s*){2,}/.test(chars)) {
this.log.push('Found repeating
sequence. Try replacing it with styling.');
}
};
Lint.prototype.test = function(tag, attrName, attrValue) {
this.testElement(tag);
this.testAttribute(tag, attrName, attrValue);
};
Lint.prototype.populate = function(writeToElement) {
if (this._isElementRepeated) {
this._reportRepeatingElement();
}
if (this.log.length) {
if (writeToElement) {
writeToElement.innerHTML = '- ' + this.log.join('
- ') + '
';
}
else {
var output = ' - ' +
this.log.join('\n - ')
.replace(/(<([^>]+)>)/ig, '')
.replace(/</g, '<')
.replace(/>/g, '>');
console.log(output);
}
}
};
global.HTMLLint = Lint;
})(typeof exports === 'undefined' ? this : exports);