GithubHelp home page GithubHelp logo

terser / html-minifier-terser Goto Github PK

View Code? Open in Web Editor NEW
344.0 8.0 27.0 15.67 MB

actively maintained fork of html-minifier - minify HTML, CSS and JS code using terser - supports ES6 code

Home Page: https://terser.org/html-minifier-terser

License: MIT License

JavaScript 99.92% Shell 0.08%
minify uglify compress uglify-js uglifyjs terser cli es6 ecmascript6

html-minifier-terser's Introduction

HTMLMinifier

NPM version Build Status

HTMLMinifier is a highly configurable, well-tested, JavaScript-based HTML minifier.

Installation

From NPM for use as a command line app:

npm install html-minifier-terser -g

From NPM for programmatic use:

npm install html-minifier-terser

Usage

Note that almost all options are disabled by default. Experiment and find what works best for you and your project.

For command line usage please see html-minifier-terser --help for a list of available options.

Sample command line:

html-minifier-terser --collapse-whitespace --remove-comments --minify-js true

Node.js

const { minify } = require('html-minifier-terser');

const result = await minify('<p title="blah" id="moo">foo</p>', {
  removeAttributeQuotes: true,
});
result; // '<p title=blah id=moo>foo</p>'

See corresponding blog post for all the gory details of how it works, description of each option, testing results and conclusions.

Also see corresponding Ruby wrapper, and for Node.js, Grunt plugin, Gulp plugin, Koa middleware wrapper and Express middleware wrapper.

For lint-like capabilities take a look at HTMLLint.

Minification comparison

How does HTMLMinifier compare to other solutions — HTML Minifier from Will Peavy (1st result in Google search for "html minifier") as well as htmlcompressor.com and minimize?

Site Original size (KB) HTMLMinifier minimize Will Peavy htmlcompressor.com
Google 52 48 52 54 n/a
Stack Overflow 177 143 154 154 n/a
HTMLMinifier 252 171 230 250 n/a
Bootstrap CSS 271 260 269 229 n/a
BBC 355 324 353 344 n/a
Amazon 466 430 456 474 n/a
Twitter 469 394 462 513 n/a
Wikipedia 703 569 682 708 n/a
Eloquent Javascript 870 815 840 864 n/a
NBC 1701 1566 1689 1705 n/a
New York Times 1731 1583 1726 1680 n/a
ES draft 6296 5538 5733 n/a n/a

Options Quick Reference

Most of the options are disabled by default.

Option Description Default
caseSensitive Treat attributes in case sensitive manner (useful for custom HTML tags) false
collapseBooleanAttributes Omit attribute values from boolean attributes false
collapseInlineTagWhitespace Don't leave any spaces between display:inline; elements when collapsing. Must be used in conjunction with collapseWhitespace=true false
collapseWhitespace Collapse white space that contributes to text nodes in a document tree false
conservativeCollapse Always collapse to 1 space (never remove it entirely). Must be used in conjunction with collapseWhitespace=true false
continueOnParseError Handle parse errors instead of aborting. false
customAttrAssign Arrays of regex'es that allow to support custom attribute assign expressions (e.g. '<div flex?="{{mode != cover}}"></div>') [ ]
customAttrCollapse Regex that specifies custom attribute to strip newlines from (e.g. /ng-class/)
customAttrSurround Arrays of regex'es that allow to support custom attribute surround expressions (e.g. <input {{#if value}}checked="checked"{{/if}}>) [ ]
customEventAttributes Arrays of regex'es that allow to support custom event attributes for minifyJS (e.g. ng-click) [ /^on[a-z]{3,}$/ ]
decodeEntities Use direct Unicode characters whenever possible false
html5 Parse input according to HTML5 specifications true
ignoreCustomComments Array of regex'es that allow to ignore certain comments, when matched [ /^!/, /^\s*#/ ]
ignoreCustomFragments Array of regex'es that allow to ignore certain fragments, when matched (e.g. <?php ... ?>, {{ ... }}, etc.) [ /<%[\s\S]*?%>/, /<\?[\s\S]*?\?>/ ]
includeAutoGeneratedTags Insert tags generated by HTML parser true
keepClosingSlash Keep the trailing slash on singleton elements false
maxLineLength Specify a maximum line length. Compressed output will be split by newlines at valid HTML split-points
minifyCSS Minify CSS in style elements and style attributes (uses clean-css) false (could be true, Object, Function(text, type))
minifyJS Minify JavaScript in script elements and event attributes (uses Terser) false (could be true, Object, Function(text, inline))
minifyURLs Minify URLs in various attributes (uses relateurl) false (could be String, Object, Function(text))
noNewlinesBeforeTagClose Never add a newline before a tag that closes an element false
preserveLineBreaks Always collapse to 1 line break (never remove it entirely) when whitespace between tags include a line break. Must be used in conjunction with collapseWhitespace=true false
preventAttributesEscaping Prevents the escaping of the values of attributes false
processConditionalComments Process contents of conditional comments through minifier false
processScripts Array of strings corresponding to types of script elements to process through minifier (e.g. text/ng-template, text/x-handlebars-template, etc.) [ ]
quoteCharacter Type of quote to use for attribute values (' or ")
removeAttributeQuotes Remove quotes around attributes when possible false
removeComments Strip HTML comments false
removeEmptyAttributes Remove all attributes with whitespace-only values false (could be true, Function(attrName, tag))
removeEmptyElements Remove all elements with empty contents false
removeOptionalTags Remove optional tags false
removeRedundantAttributes Remove attributes when value matches default. false
removeScriptTypeAttributes Remove type="text/javascript" from script tags. Other type attribute values are left intact false
removeStyleLinkTypeAttributes Remove type="text/css" from style and link tags. Other type attribute values are left intact false
removeTagWhitespace Remove space between attributes whenever possible. Note that this will result in invalid HTML! false
sortAttributes Sort attributes by frequency false
sortClassName Sort style classes by frequency false
trimCustomFragments Trim white space around ignoreCustomFragments. false
useShortDoctype Replaces the doctype with the short (HTML5) doctype false

Sorting attributes / style classes

Minifier options like sortAttributes and sortClassName won't impact the plain-text size of the output. However, they form long repetitive chains of characters that should improve compression ratio of gzip used in HTTP compression.

Special cases

Ignoring chunks of markup

If you have chunks of markup you would like preserved, you can wrap them <!-- htmlmin:ignore -->.

Minifying JSON-LD

You can minify script tags with JSON-LD by setting the option { processScripts: ['application/ld+json'] }. Note that this minification is very rudimentary, it is mainly useful for removing newlines and excessive whitespace.

Preserving SVG tags

SVG tags are automatically recognized, and when they are minified, both case-sensitivity and closing-slashes are preserved, regardless of the minification settings used for the rest of the file.

Working with invalid markup

HTMLMinifier can't work with invalid or partial chunks of markup. This is because it parses markup into a tree structure, then modifies it (removing anything that was specified for removal, ignoring anything that was specified to be ignored, etc.), then it creates a markup out of that tree and returns it.

Input markup (e.g. <p id="">foo)

Internal representation of markup in a form of tree (e.g. { tag: "p", attr: "id", children: ["foo"] })

Transformation of internal representation (e.g. removal of id attribute)

Output of resulting markup (e.g. <p>foo</p>)

HTMLMinifier can't know that original markup was only half of the tree; it does its best to try to parse it as a full tree and it loses information about tree being malformed or partial in the beginning. As a result, it can't create a partial/malformed tree at the time of the output.

Running benchmarks

Benchmarks for minified HTML:

cd benchmarks
npm install
npm run benchmark

Running local server

npm run serve

html-minifier-terser's People

Contributors

adamchal avatar alexlamsl avatar amerllica avatar bryanerayner avatar damiendart avatar danielruf avatar dependabot[bot] avatar duncanbeevers avatar jakobjingleheimer avatar jonathantneal avatar jshcrowthe avatar kangax avatar kotnik avatar laurentgoderre avatar laurentpayot avatar mathiasbynens avatar mhulse avatar papandreou avatar rsp avatar sibiraj-s avatar silverwind avatar sindresorhus avatar stereobooster avatar stevenvachon avatar stieler-it avatar tombyrer avatar tssajo avatar willfarrell avatar xhmikosr avatar ybiquitous avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

html-minifier-terser's Issues

`&quot;//` was incorrectly converted to `&quot;/`

Environment

  • html-minifier-terser version: 5.1.1
  • node.js version - node -v: v10.23.0
  • operating system: macos 10.15.7

Input

const { minify } = require('html-minifier-terser');
const output = minify(`
<div style="background-image:url(&quot;//www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png&quot;)"></div>
`, {
  minifyCSS: true,
});
console.log(output)

Actual output

<div style="background-image:url(&quot;/www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png&quot;)"></div>

Expected output

<div style="background-image:url(&quot;//www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png&quot;)"></div>

After opening minifyCSS, &quot;// will be converted into &quot;/. Eventually cause the picture to fail

[FEATURE] `collapseBooleanAttributes` doesn't work with custom attributes

const minify = require("html-minifier-terser").minify;

console.log(
  minify(
    '<a href="#" router="true" another="another" variant=variant test=true>Test</a>',
    {
      collapseBooleanAttributes: true
    }
  )
);

result

<a href="#" router="true" another="another" variant="variant" test="true">Test</a>

expected result

<a href="#" router another variant test>Test</a>

Are my expectations incorrect?

Missing dependency in 6.0.0 version

Version

Webpack log:

ERROR in ./.yarn/cache/terser-npm-5.7.2-c24448e930-143029e7f7.zip/node_modules/terser/dist/bundle.min.js 27467:31-53
Module not found: Error: Can't resolve 'acorn' in '/mnt/data/Repositorios/portfolio/.yarn/cache/terser-npm-5.7.2-c24448e930-143029e7f7.zip/node_modules/terser/dist'
resolve 'acorn' in '/mnt/data/Repositorios/portfolio/.yarn/cache/terser-npm-5.7.2-c24448e930-143029e7f7.zip/node_modules/terser/dist'
  Parsed request is a module
  using description file: /mnt/data/Repositorios/portfolio/.yarn/cache/terser-npm-5.7.2-c24448e930-143029e7f7.zip/node_modules/terser/dist/package.json (relative path: .)
    resolve as module
      request is not managed by the pnpapi
        terser tried to access acorn, but it isn't declared in its dependencies; this makes the require call ambiguous and unsound.
        Required package: acorn
        Required by: terser@npm:5.7.2 (via /mnt/data/Repositorios/portfolio/.yarn/cache/terser-npm-5.7.2-c24448e930-143029e7f7.zip/node_modules/terser/dist/)

Command yarn info html-minifier-terser:

└─ html-minifier-terser@npm:6.0.0
   ├─ Version: 6.0.0
   │
   ├─ Exported Binaries
   │  └─ html-minifier-terser
   │
   └─ Dependencies
      ├─ camel-case@npm:^4.1.2 → npm:4.1.2
      ├─ clean-css@npm:^5.1.3 → npm:5.1.5
      ├─ commander@npm:^7.2.0 → npm:7.2.0
      ├─ he@npm:^1.2.0 → npm:1.2.0
      ├─ param-case@npm:^3.0.4 → npm:3.0.4
      ├─ relateurl@npm:^0.2.7 → npm:0.2.7
      └─ terser@npm:^5.7.1 → npm:5.7.2

Returning to version 5.1.1 the issue is fixed

Messes with cases when it shouldn't

If you have some liquid statements like

{% if fooBar %} baz {% endif %}

For some reason it outputs foobar, removing the capital letter, even with the option caseSensitive: true.

A quick workaround is to add the rule:

ignoreCustomFragments: [
  /(?<={%)(.*?)(?=%})/, // {% this %} 
]

But it's not ideal of course, and the bug seemed a little unexpected.

PS: Love the plugin, fantastically useful!

Trying to get in touch regarding a security issue

Hey there!

I'd like to report a security issue but cannot find contact instructions on your repository.

If not a hassle, might you kindly add a SECURITY.md file with an email, or another contact method? GitHub recommends this best practice to ensure security issues are responsibly disclosed, and it would serve as a simple instruction for security researchers in the future.

Thank you for your consideration, and I look forward to hearing from you!

(cc @huntr-helper)

Test CLI

93ac5b3 and 03bc8d1 broke the require statement as they are different now. This was fixed in 9f2d234

But this was just found while manually testing with the CLI. So we should also test the CLI.

customAttrCollapse doesn't respect conservativeCollapse

In our angular.js based app we have attributes with long expressions which we sometimes spread over multiple lines like this:

repeat="role in modal.roles |
        filter: {displayName: $select.search}
        track by role.id"

Earlier we used minimize to minify HTML and that stuff would be collapsed correctly into:

repeat="role in modal.roles | filter: {displayName: $select.search} track by role.id"

Now after switching to webpack + html-loader we noticed that such attributes are not processed at all by default. customAttrCollapse + conservativeCollapse looked like exactly what we need, however it turned out that they don't work together. Is there a way to work around that?

Invalid arg type error with --input-dir / --output-dir options

html-minifier-terser version: 6.0.1
OS: Ubuntu 21.04

On node 14.0.0 and above if I use the following command:

npx --package [email protected] -- html-minifier-terser --file-ext html --input-dir src --output-dir dist

I get:

internal/fs/utils.js:656
    throw new ERR_INVALID_ARG_TYPE(
    ^

TypeError [ERR_INVALID_ARG_TYPE]: The "data" argument must be of type string or an instance of Buffer, TypedArray, or DataView. Received an instance of Promise
    at Object.writeFile (fs.js:1356:5)
    at /home/laurent/projects/myproject/node_modules/html-minifier-terser/cli.js:245:8
    at FSReqCallback.readFileAfterClose [as oncomplete] (internal/fs/read_file_context.js:63:3) {
  code: 'ERR_INVALID_ARG_TYPE'
}

On node 13.14.0 the following command generates no error:

npx --package [email protected] -- html-minifier-terser --file-ext html --input-dir src --output-dir dist

but the content of the minified html file is:

 [object Promise]

Everything was working fine with html-minifier-terser v5.1.1

after set "conservativeCollapse: false", still leave a white space between html elements

Expected behaviour

with "conservativeCollapse: false", it should remove white spaces between html elements entirely.

<div><a href="#">123</a><a href="#">456</a><a href="#">test 3</a></div>

Current behaviour

Still leave a white space between html elements.

<div><a href="#">123</a> <a href="#">456</a> <a href="#">test 3</a></div>

Environment

Node.js v12.14.0
linux 5.0.0-37-generic
npm 6.13.4
[email protected]
[email protected]

Config

  plugins: [
    new HtmlWebpackPlugin({
      chunks: ['index'],
      template: './src/index.html',
      filename: './index.html',
      minify: { removeComments: true, removeEmptyAttributes: true, removeRedundantAttributes: false, collapseWhitespace: true, conservativeCollapse: false }
    }),
    new HtmlWebpackPlugin({
      chunks: ['sub'],
      template: './src/sub.html',
      filename: './sub.html',
      minify: { removeComments: true, removeEmptyAttributes: true, removeRedundantAttributes: false, collapseWhitespace: true, conservativeCollapse: false }
    })
  ],

Copy your template file if it is part of this issue:

<!DOCTYPE html>
<html>
    <head>
        <title>My App</title>
    </head>
    <body>
                <div>
                        <a href="#">123</a>
                        <a href="#">456</a>
                        <a href="#">test 3</a>
                </div>
    </body>
</html>

Relevant Links

Additional context

Compress script data block

For google datasets to work it requires Schema.org JSON-LD inline script tag on a page. Compression of this by default or behind a flag would be awesome.

Example

<script type="application/ld+json">
{
        "@context": {
            "@vocab":"https://schema.org/"
        },
        "@type": "Dataset"
}
</script>

no CHANGELOG and release notes

It's pretty hard to understand what has changed and fixed, will be great to have CHANGELOG or release notes on each version in future

Escape special chars

Hi @DanielRuf

Try it out https://danielruf.github.io/html-minifier-terser/

<h2><a aria-hidden="true" tabindex="-1" class="anchor" id="initial-setup--8"></a><a aria-hidden="true" tabindex="-1" class="hash-link" href="#initial-setup--8" title="Direct link to heading">#</a><div>Initial setup < 8</div></h2>

Output:

Error: Parse Error: < 8

How to avoid this? Is it possible to escape special characters?

Fix array length check

var length = array.length < 0 ? 0 : checked(array.length) | 0

That makes not much sense as it can never be smaller than 0.

[FEATURE]: Add new CLI argument to add extra content to the output file

It would be good, to have a new CLI argument to add extra stuff to the output file automatically. My NetBeans plugin has a JEditorPane and when I add stuff there, every file that is will be minifed needs to have this content automatically added to the outpuf file. Yes, I can add this in another way like after the output file was created, I can add this, but I think it would be better to have such a cli argument. What do you think?

terser option mangle fails on / breaks document with several scripts

When enabling JavaScript mangling in terser (e.g. --minify-js {"compress":{"drop_console":"true"},"mangle":{"toplevel":"true"}} my page breaks (TypeError: e is not a function).

Test case:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>title</title>
    <script>
        function functiona(param1) {
            return functionb(param1);
        }
    </script>
</head>
<body>
    Some text in body.
    <div id="target">target</div>
    <script>
        function functionb(param2) {
          return param2;
        }
        document.addEventListener("OnDOMContentLoaded", function(){
            console.log("loaded");
            var test = functiona(undefined);
        });
    </script>
</body>
</html>

turns into

<!doctype html>
<html lang=en>
<meta charset=UTF-8>
<meta name=viewport content="width=device-width,initial-scale=1">
<title>title</title>
<script>
    function n(n) {
        return functionb(n)
    }
</script>Some text in body.<div id=target>target</div>
<script>
    function n(n) {
        return n
    }
    document.addEventListener("OnDOMContentLoaded", (function () {
        functiona(void 0)
    }))
</script>

It seems html-minifier-terser minifies these individually, rather than in the same "namespace" - correct? This of course also would explain the TypeError I am seeing with my actual HTML page.

Is there an option to prevent this? If not, and this is not in the scope of the project, is there a workaround?


For reference

Invalid Arg Type Error on minify

I installed version 6.0.0 from html-minifier-terser. In the CLI I tried -> html-minifier-terser index.html --output index.min.html and I got this error:

C:\temp>html-minifier-terser index.html --output index.min.html
internal/streams/writable.js:285
      throw new ERR_INVALID_ARG_TYPE(
      ^

TypeError [ERR_INVALID_ARG_TYPE]: The "chunk" argument must be of type string or an instance of Buffer or Uint8Array. Received an instance of Promise
←[90m    at WriteStream.Writable.write (internal/streams/writable.js:285:13)←[39m
    at writeMinify (C:\Users\Chris\AppData\Roaming\npm\node_modules\←[4mhtml-minifier-terser←[24m\cli.js:288:24)
    at Object.<anonymous> (C:\Users\Chris\AppData\Roaming\npm\node_modules\←[4mhtml-minifier-terser←[24m\cli.js:305:3)
←[90m    at Module._compile (internal/modules/cjs/loader.js:1063:30)←[39m
←[90m    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1092:10)←[39m
←[90m    at Module.load (internal/modules/cjs/loader.js:928:32)←[39m
←[90m    at Function.Module._load (internal/modules/cjs/loader.js:769:14)←[39m
←[90m    at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:72:12)←[39m
←[90m    at internal/main/run_main_module.js:17:47←[39m {
  code: ←[32m'ERR_INVALID_ARG_TYPE'←[39m
}

Did I miss smth or did the syntax for the CLI changed?

Windows 10 (64bit)
Node: 14.16.0
NPM: 7.5.2

html-webpack-plugin dependency has node version mismatch

webpack 4 supports node 6.x

therefore html-webpack-plugin tries to do the same.

html-minifier also supports node 6.x https://github.com/kangax/html-minifier/blob/51ce10f4daedb1de483ffbcccecc41be1c873da2/package.json#L50

also terser supports node 6.x
https://github.com/terser/terser/blob/6589965fe372124ce94410c9e0e7389732a3c8ea/package.json#L9

unfortunately html-minfier-terser is not compatible to the webpack 4 eco system:
https://github.com/DanielRuf/html-minifier-terser/blob/47cbb36f294dd49e20779213be721238a80f6c47/package.json#L52

is there any way to support node 6.x?

See also jantimon/html-webpack-plugin#1313

Implement a synchronous `minify` method in v6+

Hi @DanielRuf,

Is there a possibility to implement/bring back a minify() method for doing minification stuff synchronously?
In my case, I have a webpack setup that uses html-minifier-terser inside a plugin that call his own hooks synchronously... that's why I am unable to call it asynchronously. I don't want to be "stucked" in the future in version 5+.

I really understand the point of implementing async/await, but it makes the plugin impossible to use in some cases.

Working with [email protected], [email protected] and [email protected] at this moment of writing.

New release has a weird bug!

Hello again, Based on this issue I send this PR for updating Clean-CSS, and when this package was released on version 6+, I updated this package on my project, but after bundle I just see {} for rendered HTML on browser.

We downgrade to 5.1.1 and everything is ok now.

I considered it my duty to report it. if need any more data please tell me. I will share to prevent this weird bug.

minifier removes script-type-module attribute. it should not.

hi,
test case:

input (test.html):

<script type="module">console.log('hello')</script>

command:

./node_modules/.bin/html-minifier-terser --remove-script-type-attributes test.html

output:

<script>console.log('hello')</script>

as you see, the type="module" part got removed. it should not be removed, because when a script tag has type-module, it's content will be executed differently. also, the documentation for the flag says:
"
--remove-script-type-attributes Remove type="text/javascript" from script tags. Other type attribute values are left intact.
"
which is not correct with the behavior.

Unexpected behavior when minifying HTML containing SVG

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.

update terser to latest version (5)

Will be great to do it ASAP to avoid multiple dependencies, thanks for work on the package, plus update old deps too 😄 If you need I can help at the end of week

Strange behaviour in conversion of link tag attribute onload="this.media='all'"

I have below tag in my html file:

<link rel="stylesheet" href="styles.56ec616e3d29e712c590.css" media="print" onload="this.media='all'">

When I run html-minifier-terser -o dist/index.html dist/index.html --remove-comments --collapse-whitespace --minify-js --minify-css

I generates:

<link rel="stylesheet" href="styles.56ec616e3d29e712c590.css" media="print" onload='this.media="all"'>

i.e. surrounds onload in single quote.

I want to keep this tag as it is therefore I tried

--quote-character "

But with this option it generates:

<link rel="stylesheet" href="styles.56ec616e3d29e712c590.css" media="print" onload="this.media=&#34;all&#34;">

Can anyone please help?

Minifying issue with CSS

Unfortunately, html-minifier-terser during minifying with the minifyCSS: true, we faced this issue. my code is like this:

div * {
  color: red;
}

Bu my code is changed to this:

div*{color:red}

And browser cannot understand this selector div* it should be div *, even in the production level after minifying, is there any property for preventing that issue or is it a bug?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.