Skip to content

Commit 3640d84

Browse files
authored
Merge pull request #720 from kangax/minify-custom-fragments
handle line-breaks around custom fragments gracefully
2 parents 89c2968 + 3391adc commit 3640d84

File tree

2 files changed

+53
-18
lines changed

2 files changed

+53
-18
lines changed

src/htmlminifier.js

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -858,36 +858,38 @@ function minify(value, options, partialMarkup) {
858858
return token;
859859
});
860860

861+
function escapeFragments(text) {
862+
return text.replace(uidPattern, function(match, prefix, index) {
863+
var chunks = ignoredCustomMarkupChunks[+index];
864+
return chunks[1] + uidAttr + index + chunks[2];
865+
});
866+
}
867+
861868
var customFragments = options.ignoreCustomFragments.map(function(re) {
862869
return re.source;
863870
});
864871
if (customFragments.length) {
865-
var reCustomIgnore = new RegExp('\\s*(?:' + customFragments.join('|') + ')+\\s*', 'g');
872+
var reCustomIgnore = new RegExp('(\\s*)(?:' + customFragments.join('|') + ')+(\\s*)', 'g');
866873
// temporarily replace custom ignored fragments with unique attributes
867-
value = value.replace(reCustomIgnore, function(match) {
874+
value = value.replace(reCustomIgnore, function(match, prefix, suffix) {
868875
if (!uidAttr) {
869876
uidAttr = uniqueId(value);
870877
uidPattern = new RegExp('(\\s*)' + uidAttr + '([0-9]+)(\\s*)', 'g');
871878
var minifyCSS = options.minifyCSS;
872879
if (minifyCSS) {
873880
options.minifyCSS = function(text) {
874-
return minifyCSS(text).replace(uidPattern, function(match, prefix, index, suffix) {
875-
return (prefix && '\t') + uidAttr + index + (suffix && '\t');
876-
});
881+
return minifyCSS(escapeFragments(text));
877882
};
878883
}
879884
var minifyJS = options.minifyJS;
880885
if (minifyJS) {
881-
var pattern = new RegExp('(\\\\t|)' + uidAttr + '([0-9]+)(\\\\t|)', 'g');
882886
options.minifyJS = function(text, inline) {
883-
return minifyJS(text, inline).replace(pattern, function(match, prefix, index, suffix) {
884-
return (prefix && '\t') + uidAttr + index + (suffix && '\t');
885-
});
887+
return minifyJS(escapeFragments(text), inline);
886888
};
887889
}
888890
}
889891
var token = uidAttr + ignoredCustomMarkupChunks.length;
890-
ignoredCustomMarkupChunks.push(match);
892+
ignoredCustomMarkupChunks.push([match, prefix, suffix]);
891893
return '\t' + token + '\t';
892894
});
893895
}
@@ -1248,7 +1250,7 @@ function minify(value, options, partialMarkup) {
12481250

12491251
if (uidPattern) {
12501252
str = str.replace(uidPattern, function(match, prefix, index, suffix) {
1251-
var chunk = ignoredCustomMarkupChunks[+index];
1253+
var chunk = ignoredCustomMarkupChunks[+index][0];
12521254
if (options.collapseWhitespace) {
12531255
if (prefix !== '\t') {
12541256
chunk = prefix + chunk;

tests/minifier.js

Lines changed: 40 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,10 @@ QUnit.test('space normalization around text', function(assert) {
252252
assert.equal(minify('<p>foo<wbr>bar</p>', { collapseWhitespace: true }), '<p>foo<wbr>bar</p>');
253253
assert.equal(minify('<p>foo <wbr>bar</p>', { collapseWhitespace: true }), '<p>foo <wbr>bar</p>');
254254
assert.equal(minify('<p>foo<wbr> bar</p>', { collapseWhitespace: true }), '<p>foo<wbr> bar</p>');
255+
assert.equal(minify('<p>foo <wbr baz moo=""> bar</p>', { collapseWhitespace: true }), '<p>foo<wbr baz moo=""> bar</p>');
256+
assert.equal(minify('<p>foo<wbr baz moo="">bar</p>', { collapseWhitespace: true }), '<p>foo<wbr baz moo="">bar</p>');
257+
assert.equal(minify('<p>foo <wbr baz moo="">bar</p>', { collapseWhitespace: true }), '<p>foo <wbr baz moo="">bar</p>');
258+
assert.equal(minify('<p>foo<wbr baz moo=""> bar</p>', { collapseWhitespace: true }), '<p>foo<wbr baz moo=""> bar</p>');
255259
assert.equal(minify('<p> <a href="#"> <code>foo</code></a> bar</p>', { collapseWhitespace: true }), '<p><a href="#"><code>foo</code></a> bar</p>');
256260
assert.equal(minify('<p><a href="#"><code>foo </code></a> bar</p>', { collapseWhitespace: true }), '<p><a href="#"><code>foo</code></a> bar</p>');
257261
assert.equal(minify('<p> <a href="#"> <code> foo</code></a> bar </p>', { collapseWhitespace: true }), '<p><a href="#"><code>foo</code></a> bar</p>');
@@ -1887,16 +1891,45 @@ QUnit.test('minification of scripts with different mimetypes', function(assert)
18871891

18881892
input = '<script type="text/html"><!-- ko if: true -->\n\n\n<div></div>\n\n\n<!-- /ko --></script>';
18891893
assert.equal(minify(input, { minifyJS: true }), input);
1894+
});
1895+
1896+
QUnit.test('minification of scripts with custom fragments', function(assert) {
1897+
var input, output;
18901898

1891-
input = '<script type=""><?php ?></script>';
1899+
input = '<script><?php ?></script>';
18921900
assert.equal(minify(input, { minifyJS: true }), input);
18931901

1894-
input = '<script type="">function f(){ return <?php ?> }</script>';
1895-
output = '<script type="">function f(){return <?php ?> }</script>';
1902+
input = '<script>\n<?php ?></script>';
1903+
assert.equal(minify(input, { minifyJS: true }), input);
1904+
1905+
input = '<script><?php ?>\n</script>';
1906+
assert.equal(minify(input, { minifyJS: true }), input);
1907+
1908+
input = '<script>\n<?php ?>\n</script>';
1909+
assert.equal(minify(input, { minifyJS: true }), input);
1910+
1911+
input = '<script>// <% ... %></script>';
1912+
output = '<script></script>';
18961913
assert.equal(minify(input, { minifyJS: true }), output);
18971914

1898-
input = '<script type="">function f(){ return "<?php ?>" }</script>';
1899-
output = '<script type="">function f(){return"<?php ?>"}</script>';
1915+
input = '<script>// \n<% ... %></script>';
1916+
output = '<script> \n<% ... %></script>';
1917+
assert.equal(minify(input, { minifyJS: true }), output);
1918+
1919+
input = '<script>// <% ... %>\n</script>';
1920+
output = '<script></script>';
1921+
assert.equal(minify(input, { minifyJS: true }), output);
1922+
1923+
input = '<script>// \n<% ... %>\n</script>';
1924+
output = '<script> \n<% ... %>\n</script>';
1925+
assert.equal(minify(input, { minifyJS: true }), output);
1926+
1927+
input = '<script>function f(){ return <?php ?> }</script>';
1928+
output = '<script>function f(){return <?php ?> }</script>';
1929+
assert.equal(minify(input, { minifyJS: true }), output);
1930+
1931+
input = '<script>function f(){ return "<?php ?>" }</script>';
1932+
output = '<script>function f(){return"<?php ?>"}</script>';
19001933
assert.equal(minify(input, { minifyJS: true }), output);
19011934
});
19021935

@@ -1989,7 +2022,7 @@ QUnit.test('style minification', function(assert) {
19892022

19902023
input = '<div style="background: url(\'images/<% image %>\')"></div>';
19912024
assert.equal(minify(input), input);
1992-
output = '<div style="background:url(\'images/<% image %>\')"></div>';
2025+
output = '<div style="background:url(images/<% image %>)"></div>';
19932026
assert.equal(minify(input, { minifyCSS: true }), output);
19942027
assert.equal(minify(input, {
19952028
collapseWhitespace: true,
@@ -2007,7 +2040,7 @@ QUnit.test('style minification', function(assert) {
20072040

20082041
input = '<style>p { background: url("images/<% image %>") }</style>';
20092042
assert.equal(minify(input), input);
2010-
output = '<style>p{background:url("images/<% image %>")}</style>';
2043+
output = '<style>p{background:url(images/<% image %>)}</style>';
20112044
assert.equal(minify(input, { minifyCSS: true }), output);
20122045
assert.equal(minify(input, {
20132046
collapseWhitespace: true,

0 commit comments

Comments
 (0)