Git Product home page Git Product logo

html-minifier's Introduction

HTMLMinifier

npm version Build Status Dependency Status

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

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

Test suite is available online.

Also see corresponding Ruby wrapper, and for Node.js, Grunt plugin, Gulp module, 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 46 42 46 48 46
HTMLMinifier 125 98 111 117 111
Twitter 207 165 200 224 200
Stack Overflow 253 195 207 215 204
Bootstrap CSS 271 260 269 228 269
BBC 298 239 290 291 280
Amazon 422 316 412 425 n/a
NBC 553 530 552 553 534
Wikipedia 565 461 548 569 548
New York Times 678 606 675 670 n/a
Eloquent Javascript 870 815 840 864 n/a
ES6 table 5911 5051 5595 n/a n/a
ES draft 6126 5495 5664 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 [ /^!/ ]
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 UglifyJS) false (could be true, Object, Function(text, inline))
minifyURLs Minify URLs in various attributes (uses relateurl) false (could be String, Object, Function(text))
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 -->.

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.

Installation Instructions

From NPM for use as a command line app:

npm install html-minifier -g

From NPM for programmatic use:

npm install html-minifier

From Git:

git clone git://github.com/kangax/html-minifier.git
cd html-minifier
npm link .

Usage

Note that almost all options are disabled by default. For command line usage please see html-minifier --help for a list of available options. Experiment and find what works best for you and your project.

  • Sample command line: html-minifier --collapse-whitespace --remove-comments --remove-optional-tags --remove-redundant-attributes --remove-script-type-attributes --remove-tag-whitespace --use-short-doctype --minify-css true --minify-js true

Node.js

var minify = require('html-minifier').minify;
var result = minify('<p title="blah" id="moo">foo</p>', {
  removeAttributeQuotes: true
});
result; // '<p title=blah id=moo>foo</p>'

Gulp

const { src, dest, series } = require('gulp');
const htmlMinify = require('html-minifier');

const options = {
  includeAutoGeneratedTags: true,
  removeAttributeQuotes: true,
  removeComments: true,
  removeRedundantAttributes: true,
  removeScriptTypeAttributes: true,
  removeStyleLinkTypeAttributes: true,
  sortClassName: true,
  useShortDoctype: true,
  collapseWhitespace: true
};

function html() {
  return src('app/**/*.html')
    .on('data', function(file) {
      const buferFile = Buffer.from(htmlMinify.minify(file.contents.toString(), options))
      return file.contents = buferFile
    })
    .pipe(dest('build'))
}

exports.html = series(html)

Running benchmarks

Benchmarks for minified HTML:

node benchmark.js

html-minifier's People

Contributors

adamchal avatar alexlamsl avatar bryanerayner avatar damiendart avatar duncanbeevers avatar jakobjingleheimer avatar jonathantneal avatar jshcrowthe avatar kangax avatar kotnik avatar laurentgoderre avatar mathiasbynens avatar mhulse avatar papandreou avatar rsp avatar shinyaohira avatar sigvef avatar silverwind avatar simontabor avatar sindresorhus avatar soviut avatar stereobooster avatar stevenvachon avatar stieler-it avatar tombyrer avatar tssajo avatar willfarrell avatar xhmikosr avatar ybiquitous avatar yodasws 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  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

html-minifier's Issues

html-minifier and valid content in <object> tags?

This is following on from my comment here: #45 (comment)

I've done a little more experimenting and discovered that certain html tags work inside <object> tags and others don't (they are moved to after the object tag).

For example, <img>, <span> and <i> all work ok, but <p> and <div> don't, i.e. inline level elements work, but not block level.

Having read up a little more on the <object> tag apparently you are allowed zero, or any number of <param> elements, plus 'transparent' content, i.e. content that is valid HTML5 even if these tags are removed.

I suspect therefore, that html-minifier is acting as intended and merely respecting valid html markup, but if you have any other insight into this I'd love to know :)

minifier inserts whitespace

I'm using AngularJS, so some tags use dashes... (e.g. ng-repeat)
When I ran html-minifier on my source, I would end up with spaces inserted into some of my tags (e.g. ng -repeat)

Honestly, I haven't checked using the latest version (I was using grunt-contrib-htmlmin) but I figured I'd mention it here, just in case...

The sequence [']["] transformed wrong.

The sequence [']["] transformed wrong (I've added brackets to split chars). After the minifying it looks as ["][]["]. I hope it shouldn't be changed.

Incorrect minification of custom tags containing a dash in their name

Hi, I'm using AngularJS and I have some directives using dashes in their name:

<google-map ... ...></google-map>

After minification my app breaks because a whitespace is added before the dash:

<google -map ... ...></google -map>

Is there an option I'm missing or is it really a bug?

v0.5.1 breaks grunt-contrib-htlmmin

The new update breaks grunt-contrib-htmlmin. When trying to use grunt, it will crash with the following error:

Loading "htmlmin.js" tasks...ERROR
Error: Cannot find module 'html-minifier'

The problem is package.json for the npm package. Line "main": "./dist/all.js" reference a path that does not exist in node_module html-minifier v0.5.1. Removing this line of code does fix the issue.

Future: Collapsing white-space

Collapsing white-space is one of the most useful features of this library, in my opinion, since it actually makes my document smaller (mainly by removing indentation). I really like the considerations in the blog post about how to improve it, so I'm opening this issue to track how things are going.

Replacing stretches of white-space with a single space character, like the browser does, is definitely a good idea, and I'd very much like to see it implemented.

Currently, my biggest issue, as one might imagine, is around phrasing (i.e. inline) content, so I also like the idea of being able to white-list certain elements, the contents of which won't be touched; in my case it would primarily be <p>.

Another option (a bit more advanced, but nice) would be specifying elements around which white-space won't be removed - such as <strong> and <em>.

I hope the development of this feature hasn't been forgotten - thanks for the great work so far! :)

HTML entities

E.g. &copy;© or &#00000000000000000000000000000169;©

You could use he’s he.decode() (combined with he.escape(), perhaps) for this. It implements the character reference decoding algorithm described in the HTML spec and support the special “attribute value mode” as well.

Feature request: Mark comment as untouched

It would be great to have the ability to strip comments but to leave out specially marked banner comments (for instance). I don't suppose this can be achieved already?

How disabled html parser

I need to minify html-pattern like this:

<dl {{IF baz}}data-baz="1"{{END IF}}>
  <dt>foo</dt>
  <dd>bar</dd>
</dl>

but it can't be validated although it's absolutely correct.

html-minifier produces invalid inline SVG

This is the original SVG in my HTML:

<body>
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20">
    <rect width="20" height="3" y="2" fill="#fff"/>
    <rect width="20" height="3" y="8.5" fill="#fff"/>
    <rect width="20" height="3" y="15" fill="#fff"/>
</svg>
</body>

And here is the result after html-minifier:

<body>
<svg xmlns="http://www.w3.org/2000/svg" width=20 height=20>
    <rect width=20 height=3 y=2 fill="#fff">
    <rect width=20 height=3 y=8.5 fill="#fff">
    <rect width=20 height=3 y=15 fill="#fff">
</svg>

The SVG will not display properly any more (only the first rect is displayed). If I add ending slashes in the rect elements, it will display property, but it's still not valid SVG.

So maybe html-minifier shouldn't touch SVGs?

I originally reported it against gruntjs/grunt-contrib-htmlmin#19, that uses html-minifier.

Javascript / CSS minification support

Hi pal ... it will great to minify javascript / css too ...

like:

http://www.willpeavy.com/minifier/

from:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.1//EN" "http://www.openmobilealliance.org/tech/DTD/xhtml-mobile11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="es" lang="es" dir="ltr">
  <head>
    <meta http-equiv="Pragma" content="no-cache">
    <meta http-equiv="Expires" content="-1">
    <meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1; minimum-scale=1; user-scalable=0;">
    <title>Login</title>
    <link rel="shortcut icon" href="/assets/images/favicon.ico?_swc=1367872762551" type="image/vnd.microsoft.icon">
    <link rel="icon" type="image/png" href="/assets/images/favicon.png?_swc=1367872762551">
    <link rel="stylesheet" href="/build/css/mobile.css?_swc=1367872762551" type="text/css" media="screen">
  </head>
  <body>
    <div id="content">
      <div id="container">
        <div id="header">
          <div class="logo" id="logo_ct"><img border="0" src="/assets/images/header_small.png?_swc=1367872762551"></div>
          <div class="title">
            <p>Login</p>
          </div>
        </div>
        <div id="main">
          <div id="error_ct" class="error" style="display: none;">La combinaci&oacute;n de usuario y clave es incorrecta.</div>
          <form id="form" action="/" method="post">
            <div class="label">Usuario</div>
            <input type="text" name="username" class="field">
            <div class="label">Clave</div>
            <input class="field" type="password" name="password" autocomplete="off">
            <input type="submit" value="Ingresar" class="button">
          </form>
        </div>
      </div>
    </div>
    <script type="text/javascript" src="build/mobile.js?_swc=1367872762551"></script>
    <script type="text/javascript" src="build/mobile.modules.js?_swc=1367872762551"></script>

<script type="text/javascript">
  <!--
    Platform.Mobile.Bootstrap.init(function () {
      Platform.Mobile.Core.Navigation.go("Login", {
        "error": ""
      });
    });
  //-->
</script>

  </body>
</html>

to:

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.1//EN" "http://www.openmobilealliance.org/tech/DTD/xhtml-mobile11.dtd"><html xmlns="http://www.w3.org/1999/xhtml" xml:lang="es" lang="es" dir="ltr"><head><meta http-equiv="Pragma" content="no-cache"><meta http-equiv="Expires" content="-1"><meta name="viewport" content="width=device-width;initial-scale=1.0;maximum-scale=1;minimum-scale=1;user-scalable=0;"><title>Login</title><link rel="shortcut icon" href="/assets/images/favicon.ico?_swc=1367872762551" type="image/vnd.microsoft.icon"><link rel="icon" type="image/png" href="/assets/images/favicon.png?_swc=1367872762551"><link rel="stylesheet" href="/build/css/mobile.css?_swc=1367872762551" type="text/css" media="screen"></head><body><div id="content"><div id="container"><div id="header"><div class="logo" id="logo_ct"><img border="0" src="/assets/images/header_small.png?_swc=1367872762551"></div><div class="title"><p>Login</p></div></div><div id="main"><div id="error_ct" class="error" style="display: none;">La combinación de usuario y clave es incorrecta.</div><form id="form" action="/" method="post"><div class="label">Usuario</div><input type="text" name="username" class="field"><div class="label">Clave</div><input class="field" type="password" name="password" autocomplete="off"><input type="submit" value="Ingresar" class="button"></form></div></div></div><script type="text/javascript" src="build/mobile.js?_swc=1367872762551"></script><script type="text/javascript" src="build/mobile.modules.js?_swc=1367872762551"></script><script type="text/javascript"><!-- Platform.Mobile.Bootstrap.init(function (){Platform.Mobile.Core.Navigation.go("Login",{"error": ""});});//--></script></body></html>

minified HTML was empty

Hi,
when i use this i get the following error message:

"Destination not written because minified HTML was empty."

Fails to minify input (sample included)

While all config is on default.

Input:

      <div class="meaning well">
        <div class="form-inline meaning-higher-part">
          <select class="word-type">
          </select>
          <div class="sex-checkbox">
            <span class="sex-checkbox-text">Neutre</span>
          </div>
          <input type="text" class="meaning" placeholder="Meaning">
          <a class="btn btn-danger pull-right remove-meaning">Remove</a>
        </div>
        <div class="meaning-lower-part">
          <div class="meaning-example-part">
            <label>Example usage</label>
            <textarea rows="3" class="usage"></textarea>
          </div>
          <div>
            <label>Notes on context</label>
            <textarea rows="3" class="notes"></textarea>
          </div>
        </div>
        <hr>
      </div>

Output:
http://chopapp.com/#m51d5v16

Parse error on custom data attribute with value with leading dot

I'm using the bootstrap collpase plugin. I need to add an attribute with a target selector, like this. (data-attribute=".nav-collapse")

<button class="btn btn-navbar" data-target=".nav-collapse" data-toggle="collapse" type="button">
    <span class="icon-bar"></span>
    <span class="icon-bar"></span>
    <span class="icon-bar"></span>
</button>

When running htmlmin I'm getting a parse error:

Warning: app/views/header.html
    Parse Error: <button class="btn btn-navbar" data-target=".nav-collapse" data-toggle="collapse" type="button">
    <span class="icon-bar"></span>
    <span class="icon-bar"></span>
    <span class="icon-bar"></span>
</button>

What I found is that htmlmin doen't like the dot inside the attribute data-toggle (.nav-collapse), if I remove it htmlmin pass without errors.

In the w3c specification I don't see any restriction about custom data attributes that have a leading dot. http://www.w3.org/html/wg/drafts/html/master/dom.html#embedding-custom-non-visible-data-with-the-data-*-attributes

Grunt PHP

I have installed grunt php plugin from https://github.com/sindresorhus/grunt-php guidelines.Now i can run my php file under grunt command in 5000 port.But problem is i have some js files, when i am runing my php code which call those js files throw syntax error in js files.But those errors are not valid errors.
do i need to install soome other grunt php dependencies ?

wrong HTML element nesting after minification

Found a bug when minifying HTML with <button> inside a <span>

Input:

<span>
     <button>
         Hit me
     </button>
</span>

Output produced by html-minifier:

<span></span><button>Hit me</button>

Should be:

<span><button>Hit me</button></span>

Thanks.

Problem with comments in tags

Hello,

There is a problem when there is some comments in tags. I wrote a test and make a pull request to reproduce the problem.

<div <!-- HTML COMMENT --> class="one-class"></div>

The sequence of empty non-HTML-tags transformed wrong

The sequence:
<some-tag-1></some-tag-1>
<some-tag-2></some-tag-2>
transformed to:
<some-tag-1><some-tag-2></some-tag-2></some-tag-1>. The minifying should keep original sequence. As workaround I should wrap each group by <div>-tags.

html-manifier is chocking on esprima/doc/index.html

Warning: index.html
Parse Error: < 1) ? "baby" :
(age < 5) ? "toddler" :
(age < 18) ? "child": "adult";
....

I'm running html-minifier through grunt / grunt-contrib-htmlmin.

Please let me know if you need more info

Removes end of revealed IE conditional comments

The html minifier quite impressively abstains from removing IE conditional comments -- with one exception: The end of (valid) revealed comments. Meaning this exact string:

<!--<![endif]-->

The beginning of the conditional comment stays, but the end is removed. This messes up my file quite a bit... :)

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.