2021-08-07 04:51:22 -04:00
fn eval_with_cfg ( src : & 'static [ u8 ] , expected : & 'static [ u8 ] , cfg : & super ::Cfg ) {
2020-07-10 06:40:33 -04:00
let mut code = src . to_vec ( ) ;
2021-08-06 03:54:23 -04:00
let min = super ::minify ( & mut code , cfg ) ;
2021-08-06 02:19:36 -04:00
assert_eq! (
2021-08-06 06:36:58 -04:00
std ::str ::from_utf8 ( & min ) . unwrap ( ) ,
2021-08-06 03:54:23 -04:00
std ::str ::from_utf8 ( expected ) . unwrap ( ) ,
2021-08-06 02:19:36 -04:00
) ;
2020-07-30 06:17:55 -04:00
}
2021-08-06 09:18:45 -04:00
fn eval ( src : & 'static [ u8 ] , expected : & 'static [ u8 ] ) {
2021-08-07 04:51:22 -04:00
eval_with_cfg ( src , expected , & super ::Cfg ::new ( ) ) ;
}
fn eval_with_keep_html_head ( src : & 'static [ u8 ] , expected : & 'static [ u8 ] ) -> ( ) {
let mut cfg = super ::Cfg ::new ( ) ;
cfg . keep_html_and_head_opening_tags = true ;
eval_with_cfg ( src , expected , & cfg ) ;
2020-07-30 06:17:55 -04:00
}
2020-07-11 11:29:34 -04:00
#[ cfg(feature = " js-esbuild " ) ]
2020-07-10 11:15:56 -04:00
fn eval_with_js_min ( src : & 'static [ u8 ] , expected : & 'static [ u8 ] ) -> ( ) {
2021-08-07 00:56:20 -04:00
let mut cfg = super ::Cfg ::new ( ) ;
cfg . minify_js = true ;
2021-08-07 04:51:22 -04:00
eval_with_cfg ( src , expected , & cfg ) ;
2021-01-07 08:26:02 -05:00
}
#[ cfg(feature = " js-esbuild " ) ]
fn eval_with_css_min ( src : & 'static [ u8 ] , expected : & 'static [ u8 ] ) -> ( ) {
2021-08-07 00:56:20 -04:00
let mut cfg = super ::Cfg ::new ( ) ;
cfg . minify_css = true ;
2021-08-07 04:51:22 -04:00
eval_with_cfg ( src , expected , & cfg ) ;
2020-07-10 11:15:56 -04:00
}
2020-07-10 06:40:33 -04:00
#[ test ]
fn test_collapse_whitespace ( ) {
eval ( b " <a> \n   </a> " , b " <a> </a> " ) ;
2020-07-29 22:32:53 -04:00
// Tag names should be case insensitive.
eval ( b " <A> \n   </a> " , b " <a> </a> " ) ;
eval ( b " <a> \n   </A> " , b " <a> </a> " ) ;
2020-07-10 06:40:33 -04:00
}
#[ test ]
fn test_collapse_and_trim_whitespace ( ) {
eval ( b " <label> \n   </label> " , b " <label></label> " ) ;
eval ( b " <label> \n  a </label> " , b " <label>a</label> " ) ;
eval ( b " <label> \n  a b </label> " , b " <label>a b</label> " ) ;
2020-07-29 22:32:53 -04:00
// Tag names should be case insensitive.
eval ( b " <lAbEL> \n  a b </LABel> " , b " <label>a b</label> " ) ;
2020-07-10 06:40:33 -04:00
}
#[ test ]
fn test_collapse_destroy_whole_and_trim_whitespace ( ) {
eval ( b " <ul> \n   </ul> " , b " <ul></ul> " ) ;
eval ( b " <ul> \n  a </ul> " , b " <ul>a</ul> " ) ;
eval ( b " <ul> \n  a b </ul> " , b " <ul>a b</ul> " ) ;
2021-08-06 02:19:36 -04:00
eval (
b " <ul> \n  a<pre></pre> <pre></pre>b </ul> " ,
b " <ul>a<pre></pre><pre></pre>b</ul> " ,
) ;
2020-07-29 22:32:53 -04:00
// Tag names should be case insensitive.
eval ( b " <uL> \n  a b </UL> " , b " <ul>a b</ul> " ) ;
2020-07-10 06:40:33 -04:00
}
#[ test ]
fn test_no_whitespace_minification ( ) {
eval ( b " <pre> \n   \t </pre> " , b " <pre> \n \t </pre> " ) ;
2021-08-06 02:19:36 -04:00
eval (
b " <textarea> \n   \t </textarea> " ,
b " <textarea> \n \t </textarea> " ,
) ;
2020-07-29 22:32:53 -04:00
// Tag names should be case insensitive.
eval ( b " <pRe> \n   \t </PRE> " , b " <pre> \n \t </pre> " ) ;
2021-08-06 02:19:36 -04:00
eval (
b " <pre> <span> 1 2 </span> </pre> " ,
b " <pre> <span> 1 2 </span> </pre> " ,
) ;
eval (
b " <pre> <span> 1 <pre> \n </pre> 2 </span> </pre> " ,
b " <pre> <span> 1 <pre> \n </pre> 2 </span> </pre> " ,
) ;
eval (
b " <div> <pre> <span> 1 <pre> \n </pre> 2 </span> </pre> </div> " ,
b " <div><pre> <span> 1 <pre> \n </pre> 2 </span> </pre></div> " ,
) ;
eval (
br #" <pre><code>fn main() {
2021-02-05 08:03:14 -05:00
println! ( " Hello, world! " ) ;
< span > loop {
println! ( " Hello, world! " ) ;
} < / span >
}
2021-08-06 02:19:36 -04:00
< / code > < / pre > " #,
br #" <pre><code>fn main() {
2021-02-05 08:03:14 -05:00
println! ( " Hello, world! " ) ;
< span > loop {
println! ( " Hello, world! " ) ;
} < / span >
}
2021-08-06 02:19:36 -04:00
< / code > < / pre > " #,
) ;
2020-07-10 06:40:33 -04:00
}
2021-08-07 01:59:41 -04:00
#[ test ]
fn test_parsing_extra_head_tag ( ) {
// Extra `<head>` in `<label>` should be dropped, so whitespace around `<head>` should be joined and therefore trimmed due to `<label>` whitespace rules.
2021-08-07 04:51:22 -04:00
eval_with_keep_html_head (
2021-08-07 01:59:41 -04:00
b " <html><head><meta><head><link><head><body><label> <pre> </pre> <head> </label> " ,
b " <html><head><meta><link><body><label><pre> </pre></label> " ,
) ;
// Same as above except it's a `</head>`, which should get reinterpreted as a `<head>`.
2021-08-07 04:51:22 -04:00
eval_with_keep_html_head (
2021-08-07 01:59:41 -04:00
b " <html><head><meta><head><link><head><body><label> <pre> </pre> </head> </label> " ,
b " <html><head><meta><link><body><label><pre> </pre></label> " ,
) ;
// `<head>` gets implicitly closed by `<body>`, so any following `</head>` should be ignored. (They should be anyway, since `</head>` would not be a valid closing tag.)
2021-08-07 04:51:22 -04:00
eval_with_keep_html_head (
2021-08-07 01:59:41 -04:00
b " <html><head><body><label> </head> </label> " ,
b " <html><head><body><label></label> " ,
) ;
}
2021-02-06 09:46:46 -05:00
#[ test ]
2021-02-06 09:55:52 -05:00
fn test_parsing_omitted_closing_tag ( ) {
2021-08-07 04:51:22 -04:00
eval_with_keep_html_head ( b " <html> " , b " <html> " ) ;
eval_with_keep_html_head ( b " <html> \n " , b " <html> " ) ;
eval_with_keep_html_head ( b " <!doctype html> <html> \n " , b " <!doctype html><html> " ) ;
eval_with_keep_html_head (
2021-08-06 02:19:36 -04:00
b " <!doctype html><html><div> <p>Foo</div></html> " ,
b " <!doctype html><html><div><p>Foo</div> " ,
) ;
2021-02-06 09:46:46 -05:00
}
2020-07-10 06:40:33 -04:00
#[ test ]
fn test_self_closing_svg_tag_whitespace_removal ( ) {
eval ( b " <svg><path d=a /></svg> " , b " <svg><path d=a /></svg> " ) ;
eval ( b " <svg><path d=a/ /></svg> " , b " <svg><path d=a/ /></svg> " ) ;
eval ( b " <svg><path d= \" a/ \" /></svg> " , b " <svg><path d=a/ /></svg> " ) ;
eval ( b " <svg><path d= \" a/ \" /></svg> " , b " <svg><path d=a/ /></svg> " ) ;
eval ( b " <svg><path d='a/' /></svg> " , b " <svg><path d=a/ /></svg> " ) ;
eval ( b " <svg><path d='a/'/></svg> " , b " <svg><path d=a/ /></svg> " ) ;
}
2020-07-30 00:38:40 -04:00
#[ test ]
fn test_parsing_with_omitted_tags ( ) {
2021-08-07 04:51:22 -04:00
eval_with_keep_html_head ( b " <ul><li>1<li>2<li>3</ul> " , b " <ul><li>1<li>2<li>3</ul> " ) ;
eval_with_keep_html_head ( b " <rt> " , b " <rt> " ) ;
eval_with_keep_html_head ( b " <rt><rp>1</rp><div></div> " , b " <rt><rp>1</rp><div></div> " ) ;
eval_with_keep_html_head ( b " <div><rt></div> " , b " <div><rt></div> " ) ;
eval_with_keep_html_head ( b " <html><head><body> " , b " <html><head><body> " ) ;
eval_with_keep_html_head ( b " <html><head><body> " , b " <html><head><body> " ) ;
2020-07-30 00:38:40 -04:00
// Tag names should be case insensitive.
2021-08-07 04:51:22 -04:00
eval_with_keep_html_head ( b " <rt> " , b " <rt> " ) ;
2020-07-30 00:38:40 -04:00
}
2020-07-30 06:17:55 -04:00
#[ test ]
fn test_unmatched_closing_tag ( ) {
2021-08-07 04:51:22 -04:00
eval_with_keep_html_head ( b " Hello</p>Goodbye " , b " Hello<p>Goodbye " ) ;
eval_with_keep_html_head ( b " Hello<br></br>Goodbye " , b " Hello<br>Goodbye " ) ;
eval_with_keep_html_head ( b " <div>Hello</p>Goodbye " , b " <div>Hello<p>Goodbye " ) ;
eval_with_keep_html_head ( b " <ul><li>a</p> " , b " <ul><li>a<p> " ) ;
eval_with_keep_html_head ( b " <ul><li><rt>a</p> " , b " <ul><li><rt>a<p> " ) ;
eval_with_keep_html_head (
2021-08-06 02:19:36 -04:00
b " <html><head><body><ul><li><rt>a</p> " ,
2021-08-06 03:54:23 -04:00
b " <html><head><body><ul><li><rt>a<p> " ,
2021-08-06 02:19:36 -04:00
) ;
2020-07-30 06:17:55 -04:00
}
2021-08-07 01:59:41 -04:00
#[ test ]
fn test_removal_of_html_and_head_opening_tags ( ) {
// Even though `<head>` is dropped, it's still parsed, so its content is still subject to `<head>` whitespace minification rules.
eval (
b " <!DOCTYPE html><html><head> <meta> <body> " ,
b " <!DOCTYPE html><meta><body> " ,
) ;
// The tag should not be dropped if it has attributes.
eval (
b " <!DOCTYPE html><html lang=en><head> <meta> <body> " ,
b " <!DOCTYPE html><html lang=en><meta><body> " ,
) ;
}
2020-07-10 06:40:33 -04:00
#[ test ]
fn test_removal_of_optional_tags ( ) {
2021-08-07 04:51:22 -04:00
eval_with_keep_html_head (
2021-08-06 02:19:36 -04:00
b " <ul><li>1</li><li>2</li><li>3</li></ul> " ,
b " <ul><li>1<li>2<li>3</ul> " ,
) ;
2021-08-07 04:51:22 -04:00
eval_with_keep_html_head ( b " <rt></rt> " , b " <rt> " ) ;
eval_with_keep_html_head (
2021-08-06 02:19:36 -04:00
b " <rt></rt><rp>1</rp><div></div> " ,
b " <rt><rp>1</rp><div></div> " ,
) ;
2021-08-07 04:51:22 -04:00
eval_with_keep_html_head ( b " <div><rt></rt></div> " , b " <div><rt></div> " ) ;
eval_with_keep_html_head (
2021-08-06 02:19:36 -04:00
br #"
2020-07-24 05:05:29 -04:00
< html >
< head >
< / head >
< body >
< / body >
< / html >
2021-08-06 02:19:36 -04:00
" #,
b " <html><head><body> " ,
) ;
2020-07-29 22:32:53 -04:00
// Tag names should be case insensitive.
2021-08-07 04:51:22 -04:00
eval_with_keep_html_head ( b " <RT></rt> " , b " <rt> " ) ;
2020-07-10 06:40:33 -04:00
}
#[ test ]
fn test_removal_of_optional_closing_p_tag ( ) {
eval ( b " <p></p><address></address> " , b " <p><address></address> " ) ;
eval ( b " <p></p> " , b " <p> " ) ;
eval ( b " <map><p></p></map> " , b " <map><p></p></map> " ) ;
2021-08-06 02:19:36 -04:00
eval (
b " <map><p></p><address></address></map> " ,
b " <map><p><address></address></map> " ,
) ;
2020-07-10 06:40:33 -04:00
}
#[ test ]
fn test_attr_double_quoted_value_minification ( ) {
eval ( b " <a b= \" hello \" ></a> " , b " <a b= \" hello \" ></a> " ) ;
eval ( b " <a b=' hello '></a> " , b " <a b= \" hello \" ></a> " ) ;
2021-04-13 01:35:39 -04:00
eval ( br # "<a b="/>aaaa"></a>"# , br # "<a b="/>aaaa"></a>"# ) ;
eval ( br # "<a b="</a>a"></a>"# , br # "<a b="</a>a"></a>"# ) ;
2020-07-10 06:40:33 -04:00
eval ( b " <a b= hello ></a> " , b " <a b= \" hello \" ></a> " ) ;
eval ( b " <a b= hello ></a> " , b " <a b= \" hello \" ></a> " ) ;
}
#[ test ]
fn test_attr_single_quoted_value_minification ( ) {
eval ( b " <a b= \" "hello \" ></a> " , b " <a b=' \" hello'></a> " ) ;
eval ( b " <a b=' \" hello'></a> " , b " <a b=' \" hello'></a> " ) ;
2021-04-13 01:35:39 -04:00
eval ( b " <a b='/>a'></a> " , b " <a b= \" />a \" ></a> " ) ;
2021-08-06 02:19:36 -04:00
eval (
b " <a b= he"llo ></a> " ,
b " <a b=' he \" llo '></a> " ,
) ;
2020-07-10 06:40:33 -04:00
}
#[ test ]
fn test_attr_unquoted_value_minification ( ) {
2021-04-20 10:55:39 -04:00
eval ( b " <a b==></a> " , b " <a b==></a> " ) ;
eval ( b " <a b=`' \" <<==/`/></a> " , b " <a b=`' \" <<==/`/></a> " ) ;
2020-07-10 06:40:33 -04:00
eval ( b " <a b= \" hello \" ></a> " , b " <a b=hello></a> " ) ;
eval ( b " <a b='hello'></a> " , b " <a b=hello></a> " ) ;
2021-04-13 01:35:39 -04:00
eval ( b " <a b=/>></a> " , br # "<a b="/>"></a>"# ) ;
2021-04-15 22:19:47 -04:00
eval ( b " <a b=/><a></a> " , br # "<a b="/><a"></a>"# ) ;
2020-07-10 06:40:33 -04:00
eval ( b " <a b=hello></a> " , b " <a b=hello></a> " ) ;
}
2021-08-07 11:45:25 -04:00
#[ test ]
fn test_attr_whatwg_unquoted_value_minification ( ) {
let mut cfg = super ::Cfg ::new ( ) ;
cfg . ensure_spec_compliant_unquoted_attribute_values = true ;
eval_with_cfg ( b " <a b==></a> " , br # "<a b="="></a>"# , & cfg ) ;
eval_with_cfg (
br # "<a b=`'"<<==/`/></a>"# ,
br # "<a b="`'"<<==/`/"></a>"# ,
& cfg ,
) ;
}
2020-07-10 06:40:33 -04:00
#[ test ]
fn test_class_attr_value_minification ( ) {
eval ( b " <a class= c></a> " , b " <a class=c></a> " ) ;
2021-08-06 02:19:36 -04:00
eval (
b " <a class= c  d ></a> " ,
b " <a class= \" c d \" ></a> " ,
) ;
2020-07-10 06:40:33 -04:00
eval ( b " <a class=    ></a> " , b " <a></a> " ) ;
eval ( b " <a class= \" c \n \n \" ></a> " , b " <a class=c></a> " ) ;
eval ( b " <a class= \" c \n \n d \" ></a> " , b " <a class= \" c d \" ></a> " ) ;
eval ( b " <a class= \" \n \n \" ></a> " , b " <a></a> " ) ;
eval ( b " <a class=' c \n \n '></a> " , b " <a class=c></a> " ) ;
eval ( b " <a class=' c \n \n d '></a> " , b " <a class= \" c d \" ></a> " ) ;
eval ( b " <a class=' \n \n '></a> " , b " <a></a> " ) ;
2020-07-29 22:32:53 -04:00
// Attribute names should be case insensitive.
eval ( b " <a CLasS=' \n \n '></a> " , b " <a></a> " ) ;
2020-07-10 06:40:33 -04:00
}
#[ test ]
fn test_d_attr_value_minification ( ) {
eval ( b " <svg><path d= c /></svg> " , b " <svg><path d=c /></svg> " ) ;
2021-08-06 02:19:36 -04:00
eval (
b " <svg><path d= c  d  /></svg> " ,
b " <svg><path d= \" c d \" /></svg> " ,
) ;
eval (
b " <svg><path d=     /></svg> " ,
b " <svg><path/></svg> " ,
) ;
eval (
b " <svg><path d= \" c \n \n \" /></svg> " ,
b " <svg><path d=c /></svg> " ,
) ;
eval (
b " <svg><path d= \" c \n \n d \" /></svg> " ,
b " <svg><path d= \" c d \" /></svg> " ,
) ;
eval (
b " <svg><path d= \" \n \n \" /></svg> " ,
b " <svg><path/></svg> " ,
) ;
eval (
b " <svg><path d=' c \n \n ' /></svg> " ,
b " <svg><path d=c /></svg> " ,
) ;
eval (
b " <svg><path d=' c \n \n d ' /></svg> " ,
b " <svg><path d= \" c d \" /></svg> " ,
) ;
2020-07-10 06:40:33 -04:00
eval ( b " <svg><path d=' \n \n ' /></svg> " , b " <svg><path/></svg> " ) ;
2020-07-29 22:32:53 -04:00
// Attribute names should be case insensitive.
eval ( b " <svg><path D=' \n \n ' /></svg> " , b " <svg><path/></svg> " ) ;
2020-07-10 06:40:33 -04:00
}
#[ test ]
fn test_boolean_attr_value_removal ( ) {
eval ( b " <div hidden= \" true \" ></div> " , b " <div hidden></div> " ) ;
eval ( b " <div hidden= \" false \" ></div> " , b " <div hidden></div> " ) ;
eval ( b " <div hidden= \" 1 \" ></div> " , b " <div hidden></div> " ) ;
eval ( b " <div hidden= \" 0 \" ></div> " , b " <div hidden></div> " ) ;
eval ( b " <div hidden= \" abc \" ></div> " , b " <div hidden></div> " ) ;
eval ( b " <div hidden= \" \" ></div> " , b " <div hidden></div> " ) ;
eval ( b " <div hidden></div> " , b " <div hidden></div> " ) ;
2020-07-29 22:32:53 -04:00
// Attribute names should be case insensitive.
eval ( b " <div HIDden= \" true \" ></div> " , b " <div hidden></div> " ) ;
2020-07-10 06:40:33 -04:00
}
#[ test ]
fn test_empty_attr_removal ( ) {
eval ( b " <div lang= \" \" ></div> " , b " <div lang= \" \" ></div> " ) ;
eval ( b " <div lang= \" \" ></div> " , b " <div></div> " ) ;
eval ( b " <div lang=''></div> " , b " <div></div> " ) ;
eval ( b " <div lang=></div> " , b " <div></div> " ) ;
eval ( b " <div lang></div> " , b " <div></div> " ) ;
}
#[ test ]
fn test_default_attr_value_removal ( ) {
eval ( b " <a target= \" _self \" ></a> " , b " <a></a> " ) ;
eval ( b " <a target='_self'></a> " , b " <a></a> " ) ;
eval ( b " <a target=_self></a> " , b " <a></a> " ) ;
2020-07-29 22:32:53 -04:00
// Attribute names should be case insensitive.
eval ( b " <a taRGET='_self'></a> " , b " <a></a> " ) ;
2020-07-10 06:40:33 -04:00
}
#[ test ]
fn test_script_type_attr_value_removal ( ) {
2021-08-06 02:19:36 -04:00
eval (
b " <script type= \" application/ecmascript \" ></script> " ,
b " <script></script> " ,
) ;
eval (
b " <script type= \" application/javascript \" ></script> " ,
b " <script></script> " ,
) ;
eval (
b " <script type= \" text/jscript \" ></script> " ,
b " <script></script> " ,
) ;
eval (
b " <script type= \" text/plain \" ></script> " ,
b " <script type=text/plain></script> " ,
) ;
2020-07-29 22:32:53 -04:00
// Tag and attribute names should be case insensitive.
2021-08-06 02:19:36 -04:00
eval (
b " <SCRipt TYPE= \" application/ecmascript \" ></SCrIPT> " ,
b " <script></script> " ,
) ;
2020-07-10 06:40:33 -04:00
}
#[ test ]
fn test_empty_attr_value_removal ( ) {
eval ( b " <div a= \" \" ></div> " , b " <div a= \" \" ></div> " ) ;
eval ( b " <div a= \" \" ></div> " , b " <div a></div> " ) ;
eval ( b " <div a=''></div> " , b " <div a></div> " ) ;
eval ( b " <div a=></div> " , b " <div a></div> " ) ;
eval ( b " <div a></div> " , b " <div a></div> " ) ;
}
#[ test ]
fn test_space_between_attrs_minification ( ) {
2021-08-06 02:19:36 -04:00
eval (
b " <div a= \" \" b= \" \" ></div> " ,
b " <div a= \" \" b= \" \" ></div> " ,
) ;
2020-07-10 06:40:33 -04:00
eval ( b " <div a=' ' b= \" \" ></div> " , b " <div a= \" \" b= \" \" ></div> " ) ;
2021-08-06 02:19:36 -04:00
eval (
b " <div a=  b= \" \" ></div> " ,
b " <div a= \" \" b= \" \" ></div> " ,
) ;
2020-07-10 06:40:33 -04:00
eval ( b " <div a= \" 1 \" b= \" \" ></div> " , b " <div a=1 b= \" \" ></div> " ) ;
eval ( b " <div a='1' b= \" \" ></div> " , b " <div a=1 b= \" \" ></div> " ) ;
eval ( b " <div a= \" a \" b= \" b \" ></div> " , b " <div a=a b=b></div> " ) ;
}
#[ test ]
fn test_hexadecimal_entity_decoding ( ) {
2020-08-24 07:48:58 -04:00
eval ( b " . " , b " . " ) ;
eval ( b " / " , b " / " ) ;
eval ( b " / " , b " / " ) ;
eval ( b " � " , b " \0 " ) ;
2020-07-10 06:40:33 -04:00
eval ( b " 0 " , b " 0 " ) ;
eval ( b " 0 " , b " 0 " ) ;
eval ( b " 0 " , b " 0 " ) ;
eval ( b " 0 " , b " 0 " ) ;
eval ( b " 0 " , b " 0 " ) ;
eval ( b " 0 " , b " 0 " ) ;
eval ( b " ᅑ " , b " \xe1 \x85 \x91 " ) ;
eval ( b " � " , b " \xef \xbf \xbd " ) ;
2021-08-06 02:19:36 -04:00
eval (
b " � " ,
b " \xef \xbf \xbd " ,
) ;
2020-07-10 06:40:33 -04:00
}
#[ test ]
fn test_decimal_entity_decoding ( ) {
eval ( b " 0 " , b " 0 " ) ;
eval ( b " 0 " , b " 0 " ) ;
eval ( b " 0 " , b " 0 " ) ;
eval ( b " 0 " , b " 0 " ) ;
eval ( b " 0 " , b " 0 " ) ;
eval ( b " 0 " , b " 0 " ) ;
eval ( b " ᅑ " , b " \xe1 \x85 \x91 " ) ;
eval ( b " � " , b " \xef \xbf \xbd " ) ;
2021-08-06 02:19:36 -04:00
eval (
b " � " ,
b " \xef \xbf \xbd " ,
) ;
2020-07-10 06:40:33 -04:00
}
#[ test ]
fn test_named_entity_decoding ( ) {
eval ( b " > " , b " > " ) ;
eval ( b " > " , b " > " ) ;
eval ( b " & " , b " & " ) ;
eval ( b " & " , b " & " ) ;
eval ( b " &xxxyyyzzz " , b " &xxxyyyzzz " ) ;
eval ( b " &ere " , b " &ere " ) ;
eval ( b " They & Co. " , b " They & Co. " ) ;
eval ( b " if (this && that) " , b " if (this && that) " ) ;
// These entities decode to longer UTF-8 sequences, so we keep them encoded.
eval ( b " ≪⃒ " , b " ≪⃒ " ) ;
eval ( b " ≪⃒abc " , b " ≪⃒abc " ) ;
eval ( b " ≫⃒ " , b " ≫⃒ " ) ;
2021-04-15 22:19:47 -04:00
// Named entities not ending with ';' in attr values are not decoded if immediately
// followed by an alphanumeric or `=` character. (See parser for more details.)
2021-08-06 02:19:36 -04:00
eval (
br # "<a href="exam ple?>a=5"></a>"# ,
br # "<a href="exam ple?>a=5"></a>"# ,
) ;
eval (
br # "<a href="exam ple?>=5"></a>"# ,
br # "<a href="exam ple?>=5"></a>"# ,
) ;
eval (
br # "<a href="exam ple?>~5"></a>"# ,
br # "<a href="exam ple?>~5"></a>"# ,
) ;
2020-07-10 06:40:33 -04:00
}
#[ test ]
fn test_unintentional_entity_prevention ( ) {
eval ( b " &amp " , b " &amp " ) ;
eval ( b " &amp; " , b " &amp; " ) ;
eval ( b " &amp " , b " &amp " ) ;
eval ( b " &amp; " , b " &amp; " ) ;
eval ( b " &amp; " , b " &amp; " ) ;
eval ( b " &amp; " , b " &amp; " ) ;
eval ( b " &amp " , b " &amp " ) ;
eval ( b " &amp " , b " &amp " ) ;
eval ( b " &amp; " , b " &amp; " ) ;
eval ( b " &amp; " , b " &amp; " ) ;
eval ( b " &amp; " , b " &amp; " ) ;
eval ( b " &amp; " , b " &amp; " ) ;
eval ( b " &lt " , b " &lt " ) ;
eval ( b " &lt " , b " &lt " ) ;
eval ( b " &lt; " , b " &lt; " ) ;
eval ( b " &lt; " , b " &lt; " ) ;
eval ( b " &lt " , b " &lt " ) ;
eval ( b " &lt; " , b " &lt; " ) ;
eval ( b " &am&amp " , b " &am&amp " ) ;
eval ( b " &am&amp; " , b " &am&amp; " ) ;
eval ( b " &≪⃒ " , b " &≪⃒ " ) ;
eval ( b " &am≪⃒ " , b " &am≪⃒ " ) ;
eval ( b " &am≪⃒a " , b " &am≪⃒a " ) ;
eval ( b " &am&nLt " , b " &am&nLt " ) ;
}
#[ test ]
2020-09-02 03:07:02 -04:00
fn test_left_chevron_in_content ( ) {
eval ( b " <pre><</pre> " , b " <pre><</pre> " ) ;
eval ( b " <pre>< </pre> " , b " <pre>< </pre> " ) ;
eval ( b " <pre> < </pre> " , b " <pre> < </pre> " ) ;
2020-09-02 03:13:09 -04:00
eval ( b " <pre> <a </pre> " , b " <pre> <a </pre> " ) ;
2020-09-02 03:07:02 -04:00
eval ( b " <pre> <a </pre> " , b " <pre> <a </pre> " ) ;
2020-09-02 03:13:09 -04:00
eval ( b " <pre> <a </pre> " , b " <pre> <a </pre> " ) ;
eval ( b " <pre> <a </pre> " , b " <pre> <a </pre> " ) ;
eval ( b " <pre> <? </pre> " , b " <pre> <? </pre> " ) ;
2020-09-02 03:07:02 -04:00
eval ( b " <pre> <? </pre> " , b " <pre> <? </pre> " ) ;
2020-09-02 03:13:09 -04:00
eval ( b " <pre> <? </pre> " , b " <pre> <? </pre> " ) ;
eval ( b " <pre> <? </pre> " , b " <pre> <? </pre> " ) ;
2020-09-02 03:07:02 -04:00
eval ( b " <pre> </ </pre> " , b " <pre> </ </pre> " ) ;
2020-09-02 03:13:09 -04:00
eval ( b " <pre> <! </pre> " , b " <pre> <! </pre> " ) ;
2020-09-02 03:07:02 -04:00
eval ( b " < " , b " < " ) ;
eval ( b " < " , b " < " ) ;
eval ( b " <; " , b " <; " ) ;
eval ( b " <; " , b " <; " ) ;
eval ( b " <; " , b " <; " ) ;
eval ( b " < " , b " < " ) ;
eval ( b " < " , b " < " ) ;
eval ( b " <; " , b " <; " ) ;
eval ( b " <; " , b " <; " ) ;
eval ( b " <; " , b " <; " ) ;
eval ( b " <a " , b " <a " ) ;
eval ( b " <a " , b " <a " ) ;
eval ( b " <a; " , b " <a; " ) ;
eval ( b " <a; " , b " <a; " ) ;
eval ( b " <a; " , b " <a; " ) ;
eval ( b " <a;; " , b " <a;; " ) ;
eval ( b " <! " , b " <! " ) ;
eval ( b " <& " , b " <& " ) ;
eval ( b " </ " , b " </ " ) ;
eval ( b " <? " , b " <? " ) ;
eval ( b " <@ " , b " <@ " ) ;
2020-07-10 06:40:33 -04:00
}
2020-07-10 11:15:56 -04:00
2020-07-11 08:52:27 -04:00
#[ test ]
fn test_comments_removal ( ) {
2021-08-06 02:19:36 -04:00
eval (
b " <pre>a <!-- akd--sj \n <!-- \t \0 f--ajk--df->lafj --> b</pre> " ,
b " <pre>a b</pre> " ,
) ;
2020-07-11 08:52:27 -04:00
eval ( b " &a<!-- akd--sj \n <!-- \t \0 f--ajk--df->lafj -->mp " , b " & " ) ;
2021-08-06 02:19:36 -04:00
eval (
b " <script><!-- akd--sj \n <!-- \t \0 f--ajk--df->lafj --></script> " ,
b " <script><!-- akd--sj \n <!-- \t \0 f--ajk--df->lafj --></script> " ,
) ;
2020-07-11 08:52:27 -04:00
}
#[ test ]
fn test_processing_instructions ( ) {
eval ( b " <?php hello??? >> ?> " , b " <?php hello??? >> ?> " ) ;
eval ( b " av<?xml 1.0 ?>g " , b " av<?xml 1.0 ?>g " ) ;
}
#[ cfg(feature = " js-esbuild " ) ]
2020-07-10 11:15:56 -04:00
#[ test ]
fn test_js_minification ( ) {
eval_with_js_min ( b " <script>let a = 1;</script> " , b " <script>let a=1;</script> " ) ;
2021-08-06 02:19:36 -04:00
eval_with_js_min (
br #"
2020-07-22 04:57:47 -04:00
< script > let a = 1 ; < / script >
< script > let b = 2 ; < / script >
2021-08-06 02:19:36 -04:00
" #,
b " <script>let a=1;</script><script>let b=2;</script> " ,
) ;
eval_with_js_min (
b " <scRIPt type=text/plain> alert(1.00000); </scripT> " ,
b " <script type=text/plain> alert(1.00000); </script> " ,
) ;
eval_with_js_min (
br #"
2021-01-26 05:25:08 -05:00
< script >
// This is a comment.
let a = 1 ;
< / script >
2021-08-06 02:19:36 -04:00
" #,
b " <script>let a=1;</script> " ,
) ;
2020-07-10 11:15:56 -04:00
}
2021-01-07 08:26:02 -05:00
2021-04-14 10:18:16 -04:00
#[ cfg(feature = " js-esbuild " ) ]
#[ test ]
fn test_js_minification_unintentional_closing_tag ( ) {
2021-08-06 02:19:36 -04:00
eval_with_js_min (
br # "<script>let a = "</" + "script>";</script>"# ,
br # "<script>let a="<\/script>";</script>"# ,
) ;
eval_with_js_min (
br # "<script>let a = "</S" + "cRiPT>";</script>"# ,
br # "<script>let a="<\/ScRiPT>";</script>"# ,
) ;
eval_with_js_min (
br # "<script>let a = "\u003c/script>";</script>"# ,
br # "<script>let a="<\/script>";</script>"# ,
) ;
eval_with_js_min (
br # "<script>let a = "\u003c/scrIPt>";</script>"# ,
br # "<script>let a="<\/scrIPt>";</script>"# ,
) ;
2021-04-14 10:18:16 -04:00
}
2021-01-07 08:26:02 -05:00
#[ cfg(feature = " js-esbuild " ) ]
#[ test ]
fn test_css_minification ( ) {
2021-08-07 04:59:54 -04:00
// `<style>` contents.
2021-08-06 02:19:36 -04:00
eval_with_css_min (
b " <style>div { color: yellow }</style> " ,
b " <style>div{color:#ff0}</style> " ,
) ;
2021-08-07 04:59:54 -04:00
// `style` attributes.
eval_with_css_min (
2021-08-07 10:56:24 -04:00
br # "<div style="color: yellow;"></div>"# ,
br # "<div style=color:#ff0></div>"# ,
2021-08-07 04:59:54 -04:00
) ;
2021-08-07 10:56:24 -04:00
// `style` attributes are removed if fully minified away.
eval_with_css_min ( br # "<div style=" /* */ "></div>"# , br # "<div></div>"# ) ;
2021-01-07 08:26:02 -05:00
}