use js::token;
pub fn minify(source: &str) -> String {
let mut v = token::tokenize(source);
token::clean_tokens(&mut v);
v.to_string()
}
pub fn minify_and_replace_keywords(source: &str,
keywords_to_replace: &[(token::Keyword, &str)]) -> String {
let mut v = token::tokenize(source);
token::clean_tokens(&mut v);
for &(keyword, replacement) in keywords_to_replace {
for token in v.0.iter_mut() {
if match token.get_keyword() {
Some(ref k) => *k == keyword,
_ => false,
} {
*token = token::Token::Other(replacement);
}
}
}
v.to_string()
}
#[test]
fn simple_quote() {
let source = r#"var x = "\\";"#;
let expected_result = r#"var x="\\";"#;
assert_eq!(minify(source), expected_result);
}
#[test]
fn js_minify_test() {
let source = r##"
var foo = "something";
var another_var = 2348323;
// who doesn't like comments?
/* and even longer comments?
like
on
a
lot
of
lines!
Fun!
*/
function far_away(x, y) {
var x2 = x + 4;
return x * x2 + y;
}
// this call is useless
far_away(another_var, 12);
// this call is useless too
far_away(another_var, 12);
"##;
let expected_result = "var foo=\"something\";var another_var=2348323;function far_away(x,y){\
var x2=x+4;return x*x2+y;}far_away(another_var,12);far_away(another_var,\
12);";
assert_eq!(minify(source), expected_result);
}
#[test]
fn another_js_test() {
let source = r#"
/*! let's keep this license
*
* because everyone likes licenses!
*
* right?
*/
function forEach(data, func) {
for (var i = 0; i < data.length; ++i) {
func(data[i]);
}
}
forEach([0, 1, 2, 3, 4,
5, 6, 7, 8, 9], function (x) {
console.log(x);
});
// I think we're done?
console.log('done!');
"#;
let expected_result = r#"/*! let's keep this license
*
* because everyone likes licenses!
*
* right?
*/function forEach(data,func){for(var i=0;i<data.length;++i){func(data[i]);}}forEach([0,1,2,3,4,5,6,7,8,9],function(x){console.log(x);});console.log('done!');"#;
assert_eq!(minify(source), expected_result);
}
#[test]
fn comment_issue() {
let source = r#"
search_input. {
// Do NOT e.preventDefault() here. It will prevent pasting.
clearTimeout(searchTimeout);
// zero-timeout necessary here because at the time of event handler execution the
// pasted content is not in the input field yet. Shouldn’t make any difference for
// change, though.
setTimeout(search, 0);
};
"#;
let expected_result = "search_input. class="syntax-punctuation syntax-separator syntax-continuation syntax-line syntax-rust">\
setTimeout(search,0);};";
assert_eq!(minify(source), expected_result);
}
#[test]
fn missing_whitespace() {
let source = r#"
for (var entry in results) {
if (results.hasOwnProperty(entry)) {
ar.push(results[entry]);
}
}"#;
let expected_result = "for(var entry in results){if(results.hasOwnProperty(entry)){\
ar.push(results[entry]);}}";
assert_eq!(minify(source), expected_result);
}
#[test]
fn weird_regex_issue() {
let source = r#"
val = val.replace(/\_/g, "");
var valGenerics = extractGenerics(val);"#;
let expected_result = "val=val.replace(/\\_/g,\"\");var valGenerics=extractGenerics(val);";
assert_eq!(minify(source), expected_result);
}
#[test]
fn replace_keyword() {
let source = r#"
var x = ['a', 'b', null, 'd', {'x': null, 'e': null, 'z': 'w'}];
var n = null;
"#;
let expected_result = "var x=['a','b',N,'d',{'x':N,'e':N,'z':'w'}];var n=N;";
assert_eq!(minify_and_replace_keywords(source, &[(token::Keyword::Null, "N")]),
expected_result);
}