function collapseWhitespace(str) {
return str.replace(/\s+/g, ' ');
}
+
+ function collapseWhitespaceSmart(str, prevTag, nextTag) {
+ // array of tags that will maintain a single space outside of them
+ var tags = ['a', 'b', 'big', 'button', 'em', 'font','i', 'img', 'mark', 's', 'small', 'span', 'strike', 'strong', 'sub', 'sup', 'tt', 'u'];
+
+ if (prevTag && (prevTag.substr(0,1) !== '/'
+ || ( prevTag.substr(0,1) === '/' && tags.indexOf(prevTag.substr(1)) === -1))) {
+ str = str.replace(/^\s+/, '');
+ }
+
+ if (nextTag && (nextTag.substr(0,1) === '/'
+ || ( nextTag.substr(0,1) !== '/' && tags.indexOf(nextTag) === -1))) {
+ str = str.replace(/\s+$/, '');
+ }
+
+ if (prevTag && nextTag) {
+ // strip non space whitespace then compress spaces to one
+ return str.replace(/[\t\n\r]+/g, '').replace(/[ ]+/g, ' ');
+ }
+
+ return str;
+ }
function isConditionalComment(text) {
return ((/\[if[^\]]+\]/).test(text) || (/\s*(<!\[endif\])$/).test(text));
buffer.length = 0;
currentChars = '';
},
- chars: function( text ) {
+ chars: function( text, prevTag, nextTag ) {
if (currentTag === 'script' || currentTag === 'style') {
if (options.removeCommentsFromCDATA) {
text = removeComments(text, currentTag);
}
if (options.collapseWhitespace) {
if (!stackNoTrimWhitespace.length && _canTrimWhitespace(currentTag, currentAttrs)) {
- text = trimWhitespace(text);
+ text = (prevTag || nextTag) ? collapseWhitespaceSmart(text, prevTag, nextTag) : trimWhitespace(text);
}
if (!stackNoCollapseWhitespace.length && _canCollapseWhitespace(currentTag, currentAttrs)) {
text = collapseWhitespace(text);
var reCache = { }, stackedTag, re;
var HTMLParser = global.HTMLParser = function( html, handler ) {
- var index, chars, match, stack = [], last = html;
+ var index, chars, match, stack = [], last = html, prevTag, nextTag;
stack.last = function(){
return this[ this.length - 1 ];
};
if ( match ) {
html = html.substring( match[0].length );
match[0].replace( endTag, parseEndTag );
+ prevTag = '/'+match[1];
chars = false;
}
if ( match ) {
html = html.substring( match[0].length );
match[0].replace( startTag, parseStartTag );
+ prevTag = match[1];
chars = false;
}
}
var text = index < 0 ? html : html.substring( 0, index );
html = index < 0 ? "" : html.substring( index );
+ // next tag
+ tagMatch = html.match( startTag );
+ if (tagMatch) {
+ nextTag = tagMatch[1];
+ } else {
+ tagMatch = html.match( endTag );
+ if (tagMatch) {
+ nextTag = '/'+tagMatch[1];
+ } else {
+ nextTag = '';
+ }
+ }
+
if ( handler.chars )
- handler.chars( text );
+ handler.chars(text, prevTag, nextTag);
+
}
} else {
}
return obj;
}
-})(typeof exports === 'undefined' ? this : exports);
\ No newline at end of file
+})(typeof exports === 'undefined' ? this : exports);
input = '<p> foo bar</p>';
output = '<p>foo bar</p>';
equal(minify(input, { collapseWhitespace: true }), output);
-
- input = '<p> foo <span> blah 22 </span> bar <img src=""></p>';
- output = '<p>foo<span>blah 22</span>bar<img src=""></p>';
+
+ input = '<p> foo <span> blah <i> 22</i> </span> bar <img src=""></p>';
+ output = '<p>foo <span>blah <i>22</i></span> bar <img src=""></p>';
equal(minify(input, { collapseWhitespace: true }), output);
input = '<textarea> foo bar baz \n\n x \t y </textarea>';