Fix logic error with charset attribute check.
authorJuriy Zaytsev <kangax@gmail.com>
Thu, 11 Feb 2010 21:03:26 +0000 (16:03 -0500)
committerJuriy Zaytsev <kangax@gmail.com>
Thu, 11 Feb 2010 21:03:26 +0000 (16:03 -0500)
Write more tests for removing redundant attributes.

index.html
src/htmlminifier.js
tests/index.html

index 3f65e02..1f46526 100644 (file)
       <div id="todo">
         TODO:
         <ul>
-          <li>Write more unit tests (~70 so far)</li>
+          <li>Write more unit tests (~80 so far)</li>
           <li>Detect repeating attributes (e.g. multiple styles, classes, etc.)</li>
           <li>Strip whitespace from attributes where allowed</li>
           <li>Report deprecated (or presentational) attributes (e.g.: <code>&lt;td width="..." height="..."></code>)</li>
index e2321c2..e918b35 100644 (file)
@@ -48,7 +48,7 @@
   }
   
   function isAttributeRedundant(tag, attrName, attrValue, attrs) {
-    attrValue = attrValue.toLowerCase();
+    attrValue = trimWhitespace(attrValue.toLowerCase());
     return (
         (tag === 'script' && 
         attrName === 'language' && 
@@ -64,7 +64,7 @@
         
         (tag === 'script' &&
         attrName === 'charset' &&
-        attributesInclude(attrs, 'src')) ||
+        !attributesInclude(attrs, 'src')) ||
         
         (tag === 'a' &&
         attrName === 'name' &&
index d2b567b..cf59346 100644 (file)
@@ -20,7 +20,7 @@
       
       (function(global){
         
-        var minify = global.minify;
+        var minify = global.minify, input, output;
         
         test('parsing non-trivial markup', function() {
           equals(minify('<p title="</p>">x</p>'), '<p title="</p>">x</p>');
@@ -29,7 +29,7 @@
           equals(minify('<p foo-bar=baz>xxx</p>'), '<p foo-bar="baz">xxx</p>');
           equals(minify('<p foo:bar=baz>xxx</p>'), '<p foo:bar="baz">xxx</p>');
           
-          var input = '<div><div><div><div><div><div><div><div><div><div>'+
+          input = '<div><div><div><div><div><div><div><div><div><div>'+
                         'i\'m 10 levels deep'+
                       '</div></div></div></div></div></div></div></div></div></div>';
                       
@@ -45,7 +45,7 @@
         });
         
         test('options', function() {
-          var input = '<p>blah<span>blah 2<span>blah 3</span></span></p>';
+          input = '<p>blah<span>blah 2<span>blah 3</span></span></p>';
           equals(minify(input), input);
           equals(minify(input, {}), input);
         });
         });
         
         test('doctype normalization', function() {
-          var html401doctype = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"\n    "http://www.w3.org/TR/html4/strict.dtd">';
-          var actual = minify(html401doctype, { useShortDoctype: true });
-          var expected = '<!DOCTYPE html>';
+          input = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"\n    "http://www.w3.org/TR/html4/strict.dtd">';
+          equals(minify(input, { useShortDoctype: true }), '<!DOCTYPE html>');
           
-          equals(actual, expected);
+          input = '<!DOCTYPE html>';
+          equals(minify(input, { useShortDoctype: true }), input);
           
-          equals(minify('<!DOCTYPE html>', { useShortDoctype: true }), '<!DOCTYPE html>');
-          
-          actual = minify(html401doctype, { useShortDoctype: false });
-          expected = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">';
-          
-          equals(actual, expected);
+          input = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">';
+          equals(minify(input, { useShortDoctype: false }), input);
         });
         
         test('removing comments', function(){
-          var input = '<!-- test -->';
+          input = '<!-- test -->';
           equals(minify(input, { removeComments: true }), '');
           
           input = '<!-- foo --><div>baz</div><!-- bar\n\n moo -->';
         });
         
         test('conditional comments', function(){
-          var input = '<!--[if IE 6]> test <![endif]-->';
+          input = '<!--[if IE 6]> test <![endif]-->';
           equals(minify(input, { removeComments: true }), input);
           
           input = '<!--[if lt IE 5.5]> test <![endif]-->';
         });
         
         test('remove comments from scripts/styles', function(){
-          var input = '<script><!--alert(1)--><\/script>';
-          var output = '<script>alert(1)<\/script>';
+          input = '<script><!--alert(1)--><\/script>';
+          output = '<script>alert(1)<\/script>';
           equals(minify(input, { removeCommentsFromCDATA: true }), output);
           
           input = '<style type="text/css"><!-- p { color: red } --><\/style>';
         });
         
         test('remove CDATA sections from scripts/styles', function(){
-          var input = '<script>/*<![CDATA[*/alert(1)/*]]>*/<\/script>';
-          var output = '<script>alert(1)<\/script>';
+          input = '<script>/*<![CDATA[*/alert(1)/*]]>*/<\/script>';
+          output = '<script>alert(1)<\/script>';
           equals(minify(input, { removeCDATASectionsFromCDATA: true }), output);
           
           input = '<script>//<![CDATA[\nalert(1)\n//]]><\/script>';
         });
         
         test('empty attributes', function(){
-          var input = '<p id="" class="" STYLE=" " title="\n" lang="" dir="">x</p>';
+          input = '<p id="" class="" STYLE=" " title="\n" lang="" dir="">x</p>';
           equals(minify(input, { removeEmptyAttributes: true }), '<p>x</p>');
           
           input = '<p onclick=""   ondblclick=" " onmousedown="" ONMOUSEUP="" onmouseover=" " onmousemove="" onmouseout="" '+
         });
         
         test('cleaning attributes', function(){
-          var input = '<p class=" foo bar  ">foo bar baz</p>', output;
+          input = '<p class=" foo bar  ">foo bar baz</p>', output;
           equals(minify(input, { cleanAttributes: true }), '<p class="foo bar">foo bar baz</p>');
           
           input = '<p class=" foo      ">foo bar baz</p>';
           equals(minify(input, { cleanAttributes: true }), output);
         });
         
-        test('removing redundant attributes (... = "javascript: ...")', function(){
-          var input = '<p onclick="javascript:alert(1)">x</p>';
+        test('removing redundant attributes (&lt;form method="get" ...>)', function(){
+          input = '<form method="get">hello world</form>';
+          equals(minify(input, { removeRedundantAttributes: true }), '<form>hello world</form>');
+          
+          input = '<form method="post">hello world</form>';
+          equals(minify(input, { removeRedundantAttributes: true }), '<form method="post">hello world</form>');
+        });
+        
+        test('removing redundant attributes (&lt;input type="text" ...>)', function(){
+          input = '<input type="text">';
+          equals(minify(input, { removeRedundantAttributes: true }), '<input>');
+          
+          input = '<input type="  TEXT  " value="foo">';
+          equals(minify(input, { removeRedundantAttributes: true }), '<input value="foo">');
+          
+          input = '<input type="checkbox">';
+          equals(minify(input, { removeRedundantAttributes: true }), '<input type="checkbox">');
+        });
+        
+        test('removing redundant attributes (&lt;a name="..." id="..." ...>)', function(){
+          input = '<a id="foo" name="foo">blah</a>';
+          equals(minify(input, { removeRedundantAttributes: true }), '<a id="foo">blah</a>');
+          
+          input = '<input id="foo" name="foo">';
+          equals(minify(input, { removeRedundantAttributes: true }), input);
+          
+          input = '<a name="foo">blah</a>';
+          equals(minify(input, { removeRedundantAttributes: true }), input);
+          
+          input = '<a href="..." name="  bar  " id="bar" >blah</a>';
+          equals(minify(input, { removeRedundantAttributes: true }), '<a href="..." id="bar">blah</a>');
+        });
+        
+        test('removing redundant attributes (&lt;script src="..." charset="...">)', function(){
+          input = '<script type="text/javascript" charset="UTF-8">alert(222);<\/script>';
+          output = '<script type="text/javascript">alert(222);<\/script>';
+          equals(minify(input, { removeRedundantAttributes: true }), output);
+          
+          input = '<script type="text/javascript" src="http://example.com" charset="UTF-8">alert(222);<\/script>';
+          equals(minify(input, { removeRedundantAttributes: true }), input);
+          
+          input = '<script CHARSET=" ... ">alert(222);<\/script>';
+          output = '<script>alert(222);<\/script>';
+          equals(minify(input, { removeRedundantAttributes: true }), output);
+        });
+        
+        test('removing redundant attributes (&lt;... language="javascript" ...>)', function(){
+          input = '<script language="Javascript">x=2,y=4<\/script>';
+          equals(minify(input, { removeRedundantAttributes: true }), '<script>x=2,y=4<\/script>');
+          
+          input = '<script LANGUAGE = "  javaScript  ">x=2,y=4<\/script>';
+          equals(minify(input, { removeRedundantAttributes: true }), '<script>x=2,y=4<\/script>');
+        });
+        
+        test('removing redundant attributes (&lt;... = "javascript: ..." ...>)', function(){
+          input = '<p onclick="javascript:alert(1)">x</p>';
           equals(minify(input, { cleanAttributes: true }), '<p onclick="alert(1)">x</p>');
           
           input = '<p onclick="javascript:x">x</p>';
         });
         
         test('removing attribute quotes', function(){
-          var input = '<p title="blah" class="a23B-foo.bar_baz:qux" id="moo">foo</p>';
+          input = '<p title="blah" class="a23B-foo.bar_baz:qux" id="moo">foo</p>';
           equals(minify(input, { removeAttributeQuotes: true }), '<p title=blah class=a23B-foo.bar_baz:qux id=moo>foo</p>');
           
           input = '<input value="hello world">';
         });
         
         test('collapsing whitespace', function() {
-          var input = '<script type="text/javascript">  \n\t   alert(1) \n\n\n  \t <\/script>', 
-              output = '<script type="text/javascript">alert(1)<\/script>';
+          input = '<script type="text/javascript">  \n\t   alert(1) \n\n\n  \t <\/script>';
+          output = '<script type="text/javascript">alert(1)<\/script>';
           equals(minify(input, { collapseWhitespace: true }), output);
           
           input = '<p>foo</p>    <p> bar</p>\n\n   \n\t\t  <div title="quz">baz  </div>';
           equals(minify('<p>x</p>', { removeEmptyElements: true }), '<p>x</p>');
           equals(minify('<p></p>', { removeEmptyElements: true }), '');
           
-          var input = '<p>foo<span>bar</span><span></span></p>';
-          var output = '<p>foo<span>bar</span></p>';
+          input = '<p>foo<span>bar</span><span></span></p>';
+          output = '<p>foo<span>bar</span></p>';
           equals(minify(input, { removeEmptyElements: true }), output);
           
           input = '<a href="http://example/com" title="hello world"></a>';
           output = '<div>hello<span>world</span></div>';
           equals(minify(input, { removeEmptyElements: true }), output);
         });
-        
-        
-        
       })(this);
     </script>
   </body>