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 minify(source) { function isCommentOrLinebreakOrWhitespace(token) {
var tokens = Ox.tokenize(source), return token.type == 'comment' || isLinebreakOrWhitespace(token);
length = tokens.length; }
function isIdentifierOrNumber(token) { function isIdentifierOrNumber(token) {
return [ return Ox.contains([
'constant', 'identifier', 'keyword', 'constant', 'identifier', 'keyword',
'number', 'method', 'object', 'property' 'number', 'method', 'object', 'property'
].indexOf(token.type) > -1; ], token.type);
} }
return Ox.filter(Ox.map(tokens, function(token, i) { function isIdentifierOrNumberOrString(token) {
var ret = source.substr(token.offset, token.length); return isIdentifierOrNumber(token) || token.type == 'string';
if (token.type == 'comment') {
if (ret[1] == '/') {
// replace line comment with newline
ret = i == length - 1 || tokens[i + 1].type == 'linebreak'
? null : '\n';
} else {
// replace block comment with space
ret = i == length - 1 || tokens[i + 1].type == 'whitespace'
? null : ' ';
} }
} else if (token.type == 'linebreak' || token.type == 'whitespace') { function isLinebreakOrWhitespace(token) {
// remove consecutive linebreaks or whitespace return Ox.contains(['linebreak', 'whitespace'], token.type);
ret = ret[0];
} }
function minify(source) {
var tokens = Ox.tokenize(source),
length = tokens.length,
ret = '';
function getValue(token) {
return source.substr(token.offset, token.length);
}
tokens.forEach(function(token, i) {
var next, nextToken, previousToken;
if (isLinebreakOrWhitespace(token)) {
previousToken = i == 0 ? null : tokens[i - 1];
next = i + 1;
while (
next < length
&& isCommentOrLinebreakOrWhitespace(tokens[next])
) {
next++;
}
nextToken = next == length ? null : tokens[next];
}
if (token.type == 'linebreak') {
// replace a linebreak between two tokens that are identifiers
// or numbers or strings or unary operators or grouping
// operators with a single newline, otherwise remove it
if ( if (
// strip linebreaks, except between two tokens that previousToken && nextToken && (
// are both either identifier or number or string isIdentifierOrNumberOrString(previousToken)
// or identifier in brackets or identifier with || Ox.contains([
// unary operator or array literal or object literal '++', '--', ')', ']', '}'
// ], getValue(previousToken))
// strip linebreaks, except after "break", "continue", ) && (
// "return", "++" or "--", where the linebreak becomes isIdentifierOrNumberOrString(nextToken)
// a semicolon || Ox.contains([
token.type == 'linebreak' && ( '+', '-', '++', '--', '~', '!', '(', '[', '{'
i == 0 || i == length - 1 ], getValue(nextToken))
|| (
!isIdentifierOrNumber(tokens[i - 1])
&& !tokens[i - 1].type == 'string'
&& [')', ']', '}', '++', '--'].indexOf(
source.substr(tokens[i - 1].offset, tokens[i - 1].length)
) == -1
)
|| (
!isIdentifierOrNumber(tokens[i + 1])
&& ['(', '[', '{', '+', '-', '++', '--'].indexOf(
source.substr(tokens[i + 1].offset, tokens[i + 1].length)
) == -1
)
) )
) { ) {
ret = null; ret += '\n';
} else if (
// strip whitespace, except between two tokens
// that are both either identifier or number
token.type == 'whitespace' && (
i == 0 || i == length - 1
|| !isIdentifierOrNumber(tokens[i - 1])
|| !isIdentifierOrNumber(tokens[i + 1])
)
) {
ret = null;
} }
} else if (token.type == 'whitespace') {
// 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
if (
previousToken && nextToken && ((
isIdentifierOrNumber(previousToken)
&& isIdentifierOrNumber(nextToken)
) || (
Ox.contains([
'+', '-', '++', '--'
], getValue(previousToken))
&& Ox.contains([
'+', '-', '++', '--'
], getValue(nextToken))
))
) {
ret += ' ';
}
} else if (token.type != 'comment') {
// remove comments and leave all other tokens untouched
ret += getValue(token);
}
});
return ret; return ret;
})).join('');
} }
}; };