fix corner cases in `maxLineLength` (#945)
authorAlex Lam S.L <alexlamsl@gmail.com>
Tue, 10 Jul 2018 05:09:28 +0000 (13:09 +0800)
committerGitHub <noreply@github.com>
Tue, 10 Jul 2018 05:09:28 +0000 (13:09 +0800)
Split lines precisely under `htmlmin:ignore` or `ignoreCustomFragments`

src/htmlminifier.js
tests/minifier.js

index 2285032..35e8b7a 100644 (file)
@@ -1241,10 +1241,8 @@ function minify(value, options, partialMarkup) {
     squashTrailingWhitespace('br');
   }
 
-  var str = joinResultSegments(buffer, options);
-
-  if (uidPattern) {
-    str = str.replace(uidPattern, function(match, prefix, index, suffix) {
+  return joinResultSegments(buffer, options, uidPattern ? function(str) {
+    return str.replace(uidPattern, function(match, prefix, index, suffix) {
       var chunk = ignoredCustomMarkupChunks[+index][0];
       if (options.collapseWhitespace) {
         if (prefix !== '\t') {
@@ -1260,17 +1258,14 @@ function minify(value, options, partialMarkup) {
       }
       return chunk;
     });
-  }
-  if (uidIgnore) {
-    str = str.replace(new RegExp('<!--' + uidIgnore + '([0-9]+)-->', 'g'), function(match, index) {
+  } : identity, uidIgnore ? function(str) {
+    return str.replace(new RegExp('<!--' + uidIgnore + '([0-9]+)-->', 'g'), function(match, index) {
       return ignoredMarkupChunks[+index];
     });
-  }
-
-  return str;
+  } : identity);
 }
 
-function joinResultSegments(results, options) {
+function joinResultSegments(results, options, restoreCustom, restoreIgnore) {
   var str;
   var maxLineLength = options.maxLineLength;
   if (maxLineLength) {
@@ -1279,13 +1274,13 @@ function joinResultSegments(results, options) {
       var len = line.length;
       var end = results[0].indexOf('\n');
       if (end < 0) {
-        line += results.shift();
+        line += restoreIgnore(restoreCustom(results.shift()));
       }
       else {
-        line += results[0].slice(0, end);
+        line += restoreIgnore(restoreCustom(results[0].slice(0, end)));
         results[0] = results[0].slice(end + 1);
       }
-      if (len > 0 && line.length >= maxLineLength) {
+      if (len > 0 && line.length > maxLineLength) {
         lines.push(line.slice(0, len));
         line = line.slice(len);
       }
@@ -1297,11 +1292,10 @@ function joinResultSegments(results, options) {
     if (line) {
       lines.push(line);
     }
-
     str = lines.join('\n');
   }
   else {
-    str = results.join('');
+    str = restoreIgnore(restoreCustom(results.join('')));
   }
   return options.collapseWhitespace ? collapseWhitespace(str, options, true, true) : str;
 }
index bb59cda..004dab4 100644 (file)
@@ -2812,8 +2812,17 @@ QUnit.test('max line length', function(assert) {
   input = '<div data-attr="foo"></div>';
   assert.equal(minify(input, options), '<div data-attr="foo">\n</div>');
 
-  input = '<code>    hello   world  \n    world   hello  </code>';
-  assert.equal(minify(input, options), '<code>\n    hello   world  \n    world   hello  \n</code>');
+  input = [
+    '<code>    hello   world   ',
+    '    world   hello  </code>'
+  ].join('\n');
+  assert.equal(minify(input), input);
+  assert.equal(minify(input, options), [
+    '<code>',
+    '    hello   world   ',
+    '    world   hello  ',
+    '</code>'
+  ].join('\n'));
 
   assert.equal(minify('<p title="</p>">x</p>'), '<p title="</p>">x</p>');
   assert.equal(minify('<p title=" <!-- hello world --> ">x</p>'), '<p title=" <!-- hello world --> ">x</p>');
@@ -2821,10 +2830,28 @@ QUnit.test('max line length', function(assert) {
   assert.equal(minify('<p foo-bar=baz>xxx</p>'), '<p foo-bar="baz">xxx</p>');
   assert.equal(minify('<p foo:bar=baz>xxx</p>'), '<p foo:bar="baz">xxx</p>');
 
-  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>';
-  assert.equal(minify(input), input);
+  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>'
+  ];
+  assert.equal(minify(input.join('')), input.join(''));
+  assert.equal(minify(input.join(''), options), input.join('\n'));
+
+  input = [
+    '<div><div><?foo?><div>',
+    '<div><div><?bar?><div>',
+    '<div><div>',
+    'i\'m 9 levels deep</div>',
+    '</div></div><%baz%></div>',
+    '</div></div><%moo%></div>',
+    '</div>'
+  ];
+  assert.equal(minify(input.join('')), input.join(''));
+  assert.equal(minify(input.join(''), options), input.join('\n'));
 
   assert.equal(minify('<script>alert(\'<!--\')</script>', options), '<script>alert(\'<!--\')\n</script>');
   input = '<script>\nalert(\'<!-- foo -->\')\n</script>';
@@ -2848,11 +2875,18 @@ QUnit.test('max line length', function(assert) {
   assert.equal(minify('<ng-include src="\'views/partial-notification.html\'"></ng-include><div ng-view=""></div>', options),
     '<ng-include \nsrc="\'views/partial-notification.html\'">\n</ng-include><div \nng-view=""></div>'
   );
-  assert.equal(minify('<some-tag-1></some-tag-1><some-tag-2></some-tag-2>', options),
-    '<some-tag-1>\n</some-tag-1>\n<some-tag-2>\n</some-tag-2>'
-  );
+
+  input = [
+    '<some-tag-1></some-tag-1>',
+    '<some-tag-2></some-tag-2>',
+    '<some-tag-3>4',
+    '</some-tag-3>'
+  ];
+  assert.equal(minify(input.join('')), input.join(''));
+  assert.equal(minify(input.join(''), options), input.join('\n'));
+
   assert.equal(minify('[\']["]', options), '[\']["]');
-  assert.equal(minify('<a href="test.html"><div>hey</div></a>', options), '<a href="test.html">\n<div>hey</div></a>');
+  assert.equal(minify('<a href="/test.html"><div>hey</div></a>', options), '<a href="/test.html">\n<div>hey</div></a>');
   assert.equal(minify(':) <a href="http://example.com">link</a>', options), ':) <a \nhref="http://example.com">\nlink</a>');
   assert.equal(minify(':) <a href="http://example.com">\nlink</a>', options), ':) <a \nhref="http://example.com">\nlink</a>');
   assert.equal(minify(':) <a href="http://example.com">\n\nlink</a>', options), ':) <a \nhref="http://example.com">\n\nlink</a>');