Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unexpected behavior when minifying HTML containing SVG #80

Closed
kgryte opened this issue Sep 13, 2021 · 5 comments
Closed

Unexpected behavior when minifying HTML containing SVG #80

kgryte opened this issue Sep 13, 2021 · 5 comments

Comments

@kgryte
Copy link

kgryte commented Sep 13, 2021

Given the following SVG (derived from this HTML document)

<svg xmlns:xlink="http://www.w3.org/1999/xlink" width="23.947ex" height="6.343ex" style="vertical-align: -2.838ex;" viewBox="0 -1508.9 10310.5 2730.8" role="img" focusable="false" xmlns="http://www.w3.org/2000/svg" aria-labelledby="MathJax-SVG-1-Title">
<title id="MathJax-SVG-1-Title">e r f left-parenthesis x right-parenthesis equals StartFraction 2 Over StartRoot pi EndRoot EndFraction integral Subscript 0 Superscript x Baseline e Superscript minus t squared Baseline normal d t</title>
<defs aria-hidden="true">
<path stroke-width="1" id="E1-MJMAIN-65" d="M28 218Q28 273 48 318T98 391T163 433T229 448Q282 448 320 430T378 380T406 316T415 245Q415 238 408 231H126V216Q126 68 226 36Q246 30 270 30Q312 30 342 62Q359 79 369 104L379 128Q382 131 395 131H398Q415 131 415 121Q415 117 412 108Q393 53 349 21T250 -11Q155 -11 92 58T28 218ZM333 275Q322 403 238 411H236Q228 411 220 410T195 402T166 381T143 340T127 274V267H333V275Z"></path>
<path stroke-width="1" id="E1-MJMAIN-72" d="M36 46H50Q89 46 97 60V68Q97 77 97 91T98 122T98 161T98 203Q98 234 98 269T98 328L97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 60 434T96 436Q112 437 131 438T160 441T171 442H174V373Q213 441 271 441H277Q322 441 343 419T364 373Q364 352 351 337T313 322Q288 322 276 338T263 372Q263 381 265 388T270 400T273 405Q271 407 250 401Q234 393 226 386Q179 341 179 207V154Q179 141 179 127T179 101T180 81T180 66V61Q181 59 183 57T188 54T193 51T200 49T207 48T216 47T225 47T235 46T245 46H276V0H267Q249 3 140 3Q37 3 28 0H20V46H36Z"></path>
<path stroke-width="1" id="E1-MJMAIN-66" d="M273 0Q255 3 146 3Q43 3 34 0H26V46H42Q70 46 91 49Q99 52 103 60Q104 62 104 224V385H33V431H104V497L105 564L107 574Q126 639 171 668T266 704Q267 704 275 704T289 705Q330 702 351 679T372 627Q372 604 358 590T321 576T284 590T270 627Q270 647 288 667H284Q280 668 273 668Q245 668 223 647T189 592Q183 572 182 497V431H293V385H185V225Q185 63 186 61T189 57T194 54T199 51T206 49T213 48T222 47T231 47T241 46T251 46H282V0H273Z"></path>
<path stroke-width="1" id="E1-MJMAIN-28" d="M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z"></path>
<path stroke-width="1" id="E1-MJMATHI-78" d="M52 289Q59 331 106 386T222 442Q257 442 286 424T329 379Q371 442 430 442Q467 442 494 420T522 361Q522 332 508 314T481 292T458 288Q439 288 427 299T415 328Q415 374 465 391Q454 404 425 404Q412 404 406 402Q368 386 350 336Q290 115 290 78Q290 50 306 38T341 26Q378 26 414 59T463 140Q466 150 469 151T485 153H489Q504 153 504 145Q504 144 502 134Q486 77 440 33T333 -11Q263 -11 227 52Q186 -10 133 -10H127Q78 -10 57 16T35 71Q35 103 54 123T99 143Q142 143 142 101Q142 81 130 66T107 46T94 41L91 40Q91 39 97 36T113 29T132 26Q168 26 194 71Q203 87 217 139T245 247T261 313Q266 340 266 352Q266 380 251 392T217 404Q177 404 142 372T93 290Q91 281 88 280T72 278H58Q52 284 52 289Z"></path>
<path stroke-width="1" id="E1-MJMAIN-29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z"></path>
<path stroke-width="1" id="E1-MJMAIN-3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z"></path>
<path stroke-width="1" id="E1-MJMAIN-32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z"></path>
<path stroke-width="1" id="E1-MJMATHI-3C0" d="M132 -11Q98 -11 98 22V33L111 61Q186 219 220 334L228 358H196Q158 358 142 355T103 336Q92 329 81 318T62 297T53 285Q51 284 38 284Q19 284 19 294Q19 300 38 329T93 391T164 429Q171 431 389 431Q549 431 553 430Q573 423 573 402Q573 371 541 360Q535 358 472 358H408L405 341Q393 269 393 222Q393 170 402 129T421 65T431 37Q431 20 417 5T381 -10Q370 -10 363 -7T347 17T331 77Q330 86 330 121Q330 170 339 226T357 318T367 358H269L268 354Q268 351 249 275T206 114T175 17Q164 -11 132 -11Z"></path>
<path stroke-width="1" id="E1-MJMAIN-221A" d="M95 178Q89 178 81 186T72 200T103 230T169 280T207 309Q209 311 212 311H213Q219 311 227 294T281 177Q300 134 312 108L397 -77Q398 -77 501 136T707 565T814 786Q820 800 834 800Q841 800 846 794T853 782V776L620 293L385 -193Q381 -200 366 -200Q357 -200 354 -197Q352 -195 256 15L160 225L144 214Q129 202 113 190T95 178Z"></path>
<path stroke-width="1" id="E1-MJSZ2-222B" d="M114 -798Q132 -824 165 -824H167Q195 -824 223 -764T275 -600T320 -391T362 -164Q365 -143 367 -133Q439 292 523 655T645 1127Q651 1145 655 1157T672 1201T699 1257T733 1306T777 1346T828 1360Q884 1360 912 1325T944 1245Q944 1220 932 1205T909 1186T887 1183Q866 1183 849 1198T832 1239Q832 1287 885 1296L882 1300Q879 1303 874 1307T866 1313Q851 1323 833 1323Q819 1323 807 1311T775 1255T736 1139T689 936T633 628Q574 293 510 -5T410 -437T355 -629Q278 -862 165 -862Q125 -862 92 -831T55 -746Q55 -711 74 -698T112 -685Q133 -685 150 -700T167 -741Q167 -789 114 -798Z"></path>
<path stroke-width="1" id="E1-MJMAIN-30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z"></path>
<path stroke-width="1" id="E1-MJMATHI-65" d="M39 168Q39 225 58 272T107 350T174 402T244 433T307 442H310Q355 442 388 420T421 355Q421 265 310 237Q261 224 176 223Q139 223 138 221Q138 219 132 186T125 128Q125 81 146 54T209 26T302 45T394 111Q403 121 406 121Q410 121 419 112T429 98T420 82T390 55T344 24T281 -1T205 -11Q126 -11 83 42T39 168ZM373 353Q367 405 305 405Q272 405 244 391T199 357T170 316T154 280T149 261Q149 260 169 260Q282 260 327 284T373 353Z"></path>
<path stroke-width="1" id="E1-MJMAIN-2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z"></path>
<path stroke-width="1" id="E1-MJMATHI-74" d="M26 385Q19 392 19 395Q19 399 22 411T27 425Q29 430 36 430T87 431H140L159 511Q162 522 166 540T173 566T179 586T187 603T197 615T211 624T229 626Q247 625 254 615T261 596Q261 589 252 549T232 470L222 433Q222 431 272 431H323Q330 424 330 420Q330 398 317 385H210L174 240Q135 80 135 68Q135 26 162 26Q197 26 230 60T283 144Q285 150 288 151T303 153H307Q322 153 322 145Q322 142 319 133Q314 117 301 95T267 48T216 6T155 -11Q125 -11 98 4T59 56Q57 64 57 83V101L92 241Q127 382 128 383Q128 385 77 385H26Z"></path>
<path stroke-width="1" id="E1-MJMAIN-64" d="M376 495Q376 511 376 535T377 568Q377 613 367 624T316 637H298V660Q298 683 300 683L310 684Q320 685 339 686T376 688Q393 689 413 690T443 693T454 694H457V390Q457 84 458 81Q461 61 472 55T517 46H535V0Q533 0 459 -5T380 -11H373V44L365 37Q307 -11 235 -11Q158 -11 96 50T34 215Q34 315 97 378T244 442Q319 442 376 393V495ZM373 342Q328 405 260 405Q211 405 173 369Q146 341 139 305T131 211Q131 155 138 120T173 59Q203 26 251 26Q322 26 373 103V342Z"></path>
</defs>
<g stroke="currentColor" fill="currentColor" stroke-width="0" transform="matrix(1 0 0 -1 0 0)" aria-hidden="true">
 <use xlink:href="#E1-MJMAIN-65"></use>
 <use xlink:href="#E1-MJMAIN-72" x="444" y="0"></use>
 <use xlink:href="#E1-MJMAIN-66" x="837" y="0"></use>
 <use xlink:href="#E1-MJMAIN-28" x="1143" y="0"></use>
 <use xlink:href="#E1-MJMATHI-78" x="1533" y="0"></use>
 <use xlink:href="#E1-MJMAIN-29" x="2105" y="0"></use>
 <use xlink:href="#E1-MJMAIN-3D" x="2772" y="0"></use>
<g transform="translate(3551,0)">
<g transform="translate(397,0)">
<rect stroke="none" width="1527" height="60" x="0" y="220"></rect>
 <use xlink:href="#E1-MJMAIN-32" x="513" y="676"></use>
<g transform="translate(60,-797)">
 <use xlink:href="#E1-MJMAIN-221A" x="0" y="-84"></use>
<rect stroke="none" width="573" height="60" x="833" y="657"></rect>
 <use xlink:href="#E1-MJMATHI-3C0" x="833" y="0"></use>
</g>
</g>
</g>
<g transform="translate(5762,0)">
 <use xlink:href="#E1-MJSZ2-222B" x="0" y="0"></use>
 <use transform="scale(0.707)" xlink:href="#E1-MJMATHI-78" x="1500" y="1540"></use>
 <use transform="scale(0.707)" xlink:href="#E1-MJMAIN-30" x="787" y="-1270"></use>
</g>
<g transform="translate(7495,0)">
 <use xlink:href="#E1-MJMATHI-65" x="0" y="0"></use>
<g transform="translate(466,412)">
 <use transform="scale(0.707)" xlink:href="#E1-MJMAIN-2212" x="0" y="0"></use>
<g transform="translate(550,0)">
 <use transform="scale(0.707)" xlink:href="#E1-MJMATHI-74" x="0" y="0"></use>
 <use transform="scale(0.574)" xlink:href="#E1-MJMAIN-32" x="445" y="446"></use>
</g>
</g>
</g>
 <use xlink:href="#E1-MJMAIN-64" x="9392" y="0"></use>
 <use xlink:href="#E1-MJMATHI-74" x="9948" y="0"></use>
</g>
</svg>

the minifier generates the following (derived from this HTML document)

<svg xmlns:xlink="http://www.w3.org/1999/xlink" width="23.947ex" height="6.343ex" style="vertical-align:-2.838ex" viewBox="0 -1508.9 10310.5 2730.8" role="img" focusable="false" xmlns="http://www.w3.org/2000/svg" aria-labelledby="MathJax-SVG-1-Title"><title id="MathJax-SVG-1-Title">e r f left-parenthesis x right-parenthesis equals StartFraction 2 Over StartRoot pi EndRoot EndFraction integral Subscript 0 Superscript x Baseline e Superscript minus t squared Baseline normal d t</title><defs aria-hidden="true"></defs><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="matrix(1 0 0 -1 0 0)" aria-hidden="true"><g transform="translate(3551,0)"><g transform="translate(397,0)"><g transform="translate(60,-797)"></g></g></g><g transform="translate(5762,0)"></g><g transform="translate(7495,0)"><g transform="translate(466,412)"><g transform="translate(550,0)"></g></g></g></g></svg>

As can be observed in the output, all the <path>, <rect>, and <use> elements have been removed from the original SVG, which is not desirable.

The output was generated via the following command:

html-minifier-terser --remove-comments --collapse-whitespace --remove-empty-elements --minify-css true --minify-js true

This is potentially due to the use of non-self-closing tags and --remove-empty-elements?

If so, this may not be desirable for SVG, where "empty" elements are fairly commonplace and valid. If the minifier is unable to modify its behavior, may be worth noting in the package README that, if HTML includes SVG, may not want to use --remove-empty-elements.

@kgryte
Copy link
Author

kgryte commented Sep 13, 2021

Related issue: kangax/html-minifier#1092.

kgryte added a commit to stdlib-js/www that referenced this issue Sep 13, 2021
See terser/html-minifier-terser#80. In
short, the HTML minifier strips empty SVG elements, thus breaking
equations. This is not desired.
@DanielRuf
Copy link
Contributor

Since this is documented, can be tested on https://terser.org/html-minifier-terser/ and there is also a way to prevent all optimizations (https://github.com/terser/html-minifier-terser#ignoring-chunks-of-markup) I'm closing this issue.

There are good reasons why all optimizations are disabled by default and why this is in red:
Bildschirmfoto 2021-09-14 um 00 18 27

Option Description Default
removeEmptyElements Remove all elements with empty contents false

@kgryte
Copy link
Author

kgryte commented Sep 13, 2021

Ignoring chunks of markup is fine, so long as you are authoring the HTML in question. Otherwise, one needs to dynamically modify the received markup in order to preserve empty elements in SVG.

@DanielRuf
Copy link
Contributor

True. Normally this is done in webpack setups with the right plugins which replace texts or before compilation using sed or other solutions.

In general this case is currently not covered by the tests as it is not recommended to enable removeEmptyElements since this can break and will break things.

So far only html elements are not affected by this:

https://github.com/terser/html-minifier-terser/blob/v6.0.2/src/htmlminifier.js#L429
https://github.com/terser/html-minifier-terser/blob/v6.0.2/src/htmlminifier.js#L1134
https://github.com/terser/html-minifier-terser/blob/v6.0.2/src/htmlminifier.js#L517-L545

I'm not sure if it makes sense to add svg and xml elements to this function by default but this could lead to the case, that we will have to add many more tags to this function to prevent such issues and that this has to be correctly tested.

But as this is marked as red / breaking, I'm opting for keeping as it is and removing the option from the CLI like you already did.

If this is not in your interest, you may want to check https://github.com/tdewolff/minify#html

https://go.tacodewolff.nl/minify

@kgryte
Copy link
Author

kgryte commented Sep 13, 2021

Thanks for the details and links. :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants