better Ox.minify

This commit is contained in:
rolux 2012-05-26 00:02:28 +02:00
parent 5fa84fc9af
commit b4c0060861

View file

@ -314,8 +314,8 @@ Ox.minify <f> Minifies JavaScript
'for(a in b)\n{c=void 0;}' 'for(a in b)\n{c=void 0;}'
> Ox.minify('return a; return 0; return "";') > Ox.minify('return a; return 0; return "";')
'return a;return 0;return"";' 'return a;return 0;return"";'
> Ox.minify('return\na;\nreturn\n0;\nreturn\n"";') > Ox.minify('return\na;\nreturn\n0;\nreturn\n\"\";')
'return\na;\nreturn\n0;\nreturn\n"";\n' 'return\na;return\n0;return\n"";'
@*/ @*/
Ox.minify = function() { Ox.minify = function() {
// see https://github.com/douglascrockford/JSMin/blob/master/README // see https://github.com/douglascrockford/JSMin/blob/master/README
@ -327,71 +327,86 @@ Ox.minify = function() {
arguments[1](minify(source)); arguments[1](minify(source));
}); });
} }
function isCommentOrLinebreakOrWhitespace(token) {
return token.type == 'comment' || isLinebreakOrWhitespace(token);
}
function isIdentifierOrNumber(token) {
return Ox.contains([
'constant', 'identifier', 'keyword',
'number', 'method', 'object', 'property'
], token.type);
}
function isIdentifierOrNumberOrString(token) {
return isIdentifierOrNumber(token) || token.type == 'string';
}
function isLinebreakOrWhitespace(token) {
return Ox.contains(['linebreak', 'whitespace'], token.type);
}
function minify(source) { function minify(source) {
var tokens = Ox.tokenize(source), var tokens = Ox.tokenize(source),
length = tokens.length; length = tokens.length,
function isIdentifierOrNumber(token) { ret = '';
return [ function getValue(token) {
'constant', 'identifier', 'keyword', return source.substr(token.offset, token.length);
'number', 'method', 'object', 'property'
].indexOf(token.type) > -1;
} }
return Ox.filter(Ox.map(tokens, function(token, i) { tokens.forEach(function(token, i) {
var ret = source.substr(token.offset, token.length); var next, nextToken, previousToken;
if (token.type == 'comment') { if (isLinebreakOrWhitespace(token)) {
if (ret[1] == '/') { previousToken = i == 0 ? null : tokens[i - 1];
// replace line comment with newline next = i + 1;
ret = i == length - 1 || tokens[i + 1].type == 'linebreak' while (
? null : '\n'; next < length
} else { && isCommentOrLinebreakOrWhitespace(tokens[next])
// replace block comment with space ) {
ret = i == length - 1 || tokens[i + 1].type == 'whitespace' next++;
? null : ' ';
} }
} else if (token.type == 'linebreak' || token.type == 'whitespace') { nextToken = next == length ? null : tokens[next];
// remove consecutive linebreaks or whitespace
ret = ret[0];
} }
if ( if (token.type == 'linebreak') {
// strip linebreaks, except between two tokens that // replace a linebreak between two tokens that are identifiers
// are both either identifier or number or string // or numbers or strings or unary operators or grouping
// or identifier in brackets or identifier with // operators with a single newline, otherwise remove it
// unary operator or array literal or object literal if (
// previousToken && nextToken && (
// strip linebreaks, except after "break", "continue", isIdentifierOrNumberOrString(previousToken)
// "return", "++" or "--", where the linebreak becomes || Ox.contains([
// a semicolon '++', '--', ')', ']', '}'
token.type == 'linebreak' && ( ], getValue(previousToken))
i == 0 || i == length - 1 ) && (
|| ( isIdentifierOrNumberOrString(nextToken)
!isIdentifierOrNumber(tokens[i - 1]) || Ox.contains([
&& !tokens[i - 1].type == 'string' '+', '-', '++', '--', '~', '!', '(', '[', '{'
&& [')', ']', '}', '++', '--'].indexOf( ], getValue(nextToken))
source.substr(tokens[i - 1].offset, tokens[i - 1].length)
) == -1
) )
|| ( ) {
!isIdentifierOrNumber(tokens[i + 1]) ret += '\n';
&& ['(', '[', '{', '+', '-', '++', '--'].indexOf( }
source.substr(tokens[i + 1].offset, tokens[i + 1].length) } else if (token.type == 'whitespace') {
) == -1 // replace whitespace between two tokens that are identifiers or
) // numbers, or between a token that ends with "+" or "-" and one
) // that begins with "+" or "-", with a single space, otherwise
) { // remove it
ret = null; if (
} else if ( previousToken && nextToken && ((
// strip whitespace, except between two tokens isIdentifierOrNumber(previousToken)
// that are both either identifier or number && isIdentifierOrNumber(nextToken)
token.type == 'whitespace' && ( ) || (
i == 0 || i == length - 1 Ox.contains([
|| !isIdentifierOrNumber(tokens[i - 1]) '+', '-', '++', '--'
|| !isIdentifierOrNumber(tokens[i + 1]) ], getValue(previousToken))
) && Ox.contains([
) { '+', '-', '++', '--'
ret = null; ], getValue(nextToken))
))
) {
ret += ' ';
}
} else if (token.type != 'comment') {
// remove comments and leave all other tokens untouched
ret += getValue(token);
} }
return ret; });
})).join(''); return ret;
} }
}; };