better Ox.minify
This commit is contained in:
parent
5fa84fc9af
commit
b4c0060861
1 changed files with 75 additions and 60 deletions
|
@ -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('');
|
||||
}
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue