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;}'
> Ox.minify('return a; return 0; return "";')
'return a;return 0;return"";'
> Ox.minify('return\na;\nreturn\n0;\nreturn\n"";')
'return\na;\nreturn\n0;\nreturn\n"";\n'
> Ox.minify('return\na;\nreturn\n0;\nreturn\n\"\";')
'return\na;return\n0;return\n"";'
@*/
Ox.minify = function() {
// see https://github.com/douglascrockford/JSMin/blob/master/README
@ -327,71 +327,86 @@ Ox.minify = function() {
arguments[1](minify(source));
});
}
function minify(source) {
var tokens = Ox.tokenize(source),
length = tokens.length;
function isCommentOrLinebreakOrWhitespace(token) {
return token.type == 'comment' || isLinebreakOrWhitespace(token);
}
function isIdentifierOrNumber(token) {
return [
return Ox.contains([
'constant', 'identifier', 'keyword',
'number', 'method', 'object', 'property'
].indexOf(token.type) > -1;
], token.type);
}
return Ox.filter(Ox.map(tokens, function(token, i) {
var ret = source.substr(token.offset, token.length);
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 : ' ';
function isIdentifierOrNumberOrString(token) {
return isIdentifierOrNumber(token) || token.type == 'string';
}
} else if (token.type == 'linebreak' || token.type == 'whitespace') {
// remove consecutive linebreaks or whitespace
ret = ret[0];
function isLinebreakOrWhitespace(token) {
return Ox.contains(['linebreak', 'whitespace'], token.type);
}
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 (
// strip linebreaks, except between two tokens that
// are both either identifier or number or string
// or identifier in brackets or identifier with
// unary operator or array literal or object literal
//
// strip linebreaks, except after "break", "continue",
// "return", "++" or "--", where the linebreak becomes
// a semicolon
token.type == 'linebreak' && (
i == 0 || i == length - 1
|| (
!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
)
previousToken && nextToken && (
isIdentifierOrNumberOrString(previousToken)
|| Ox.contains([
'++', '--', ')', ']', '}'
], getValue(previousToken))
) && (
isIdentifierOrNumberOrString(nextToken)
|| Ox.contains([
'+', '-', '++', '--', '~', '!', '(', '[', '{'
], getValue(nextToken))
)
) {
ret = null;
} 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;
ret += '\n';
}
} 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;
})).join('');
}
};