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;}'
|
'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;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue