Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

minimize

Package Overview
Dependencies
Maintainers
1
Versions
65
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

minimize - npm Package Compare versions

Comparing version 1.8.1 to 2.0.0

13

lib/helpers.js

@@ -163,2 +163,15 @@ 'use strict';

/**
* Proxy to render HTML.
*
* @param {Object} element
* @return {String}
* @api public
*/
Helpers.prototype.open = function open(element) {
if (element.type in this) {
return this[element.type](element);
}
};
/**
* Provide closing tag for element if required.

@@ -165,0 +178,0 @@ *

209

lib/minimize.js

@@ -6,4 +6,4 @@ 'use strict';

//
var debug = require('diagnostics')('minimize')
, EventEmitter = require('events').EventEmitter
var EventEmitter = require('events').EventEmitter
, debug = require('diagnostics')('minimize')
, Helpers = require('./helpers')

@@ -20,3 +20,3 @@ , html = require('htmlparser2')

* @Constructor
* @param {Mixed} HTMLParser2 instance, i.e. to support SVG if required.
* @param {Function} parser HTMLParser2 instance, i.e. to support SVG if required.
* @param {Object} options parsing options, optional

@@ -32,5 +32,5 @@ * @api public

this.emits = emits;
this.plugins = Object.create(null);
this.helpers = new Helpers(options);
this.plugins = Object.create(null);
this.emits = emits;

@@ -64,9 +64,23 @@ //

Minimize.prototype.parse = function parse(content, callback) {
if (typeof callback !== 'function') throw new Error('No callback provided');
var id = uuid.v4();
var minimize = this
, id = uuid.v4()
, sync = false
, output;
if (typeof callback !== 'function') {
sync = true;
callback = function parsed(error, result) {
if (error) {
minimize.emit('error', error);
}
output = result;
}
}
//
// Listen to DOM parsing, so the htmlparser callback can trigger it.
//
this.once('read', this.minifier.bind(this, id));
this.once('read', this.minifier.bind(this, id, sync));
this.once('parsed:' + id, callback);

@@ -78,2 +92,7 @@

this.htmlparser.parseComplete(content);
//
// Return content if generated synchronously otherwise undefined.
//
return output;
};

@@ -86,5 +105,6 @@

* @param {Object} dom presented as traversable object
* @returns {Void}
* @api private
*/
Minimize.prototype.minifier = function minifier(id, error, dom) {
Minimize.prototype.minifier = function minifier(id, sync, error, dom) {
if (error) throw new Error('Minifier failed to parse DOM', error);

@@ -95,3 +115,3 @@

//
this.traverse(dom, '', this.emits('parsed:' + id));
return this.traverse(dom, '', sync, this.emits('parsed:' + id));
};

@@ -108,3 +128,3 @@

*/
Minimize.prototype.traverse = function traverse(data, html, done) {
Minimize.prototype.traverse = function traverse(data, html, sync, done) {
var minimize = this

@@ -114,47 +134,117 @@ , plugins = Object.keys(this.plugins);

//
// Reduce all provided elements to minimized HTML.
// Ensure data can be reduced.
//
debug('Reducing %d parsed HTML elements', data.length);
async.reduce(data, html, function reduce(html, element, step) {
var children;
data = data || [];
/**
* Close element in HTML.
*
* @param {Error} error
* @param {String} html
* @api private
*/
function close(error, html) {
if (error) {
debug('Error received by #close %s', error.message);
return step(error);
}
/**
* (A)synchronously return or callback with HTML.
*
* @param {Error} error Runtime error
* @param {String} html minimized HTML
* @param {Function} cb optional callback
* @returns {String} HTML
* @api private
*/
function returns(error, html, cb) {
var fn = typeof cb === 'function';
html += minimize.helpers.close(element);
step(null, html);
if (error) {
debug('Error received: %s', error.message);
if (fn) cb(error);
return minimize.emit('error', error);
}
/**
* Enter element in HTML.
*
* @param {Error} error
* @api private
*/
function enter(error) {
if (error) {
debug('Error received by #enter %s', error.message);
return done(error);
if (fn) return cb(null, html);
return html;
}
/**
* For all children run same iterator.
*
* @param {Object} element Current element
* @param {String} content Current minimized HTML, memo.
* @param {Function} next Completion callback.
* @returns {Function} Runner.
* @api private
*/
function traverser(element, content, next) {
return function () {
return minimize.traverse(element.children, content, sync, step(element, 'close', next))
};
}
/**
* Minimize single level of HTML.
*
* @param {Object} element Properties
* @param {String} type Element type
* @param {Function} cb Completion callback
* @api private
*/
function step(element, type, cb) {
return function generate(error, html) {
html += minimize.helpers[type](element);
return returns(error, html, cb);
}
}
/**
* Traverse children of current element.
*
* @param {Object} element Properties
* @param {Function} cb Completion callback
* @api private
*/
function run(element, cb) {
return function level(error, content) {
debug('Traversing children of element %s', element.name);
if (sync) {
return traverser(element, content, cb)();
}
children = element.children;
html += minimize.helpers[element.type](element);
if (!children) return close(null, html);
setImmediate(traverser(element, content, cb));
}
}
debug('Traversing %d children of element %s', children.length, element.name);
setImmediate(function delay() {
traverse.call(minimize, children, html, close);
});
/**
* Create opening string of element.
*
* @param {Object} element Properties
* @param {String} html Current minimized HTML, memo.
* @param {Function} cb Completion callback
* @returns {String} Result
* @api private
*/
function open(element, html, cb) {
return step(element, 'open', cb)(null, html);
}
/**
* Create plugins for element.
*
* @param {Object} element Properties.
* @return {Function} Plugin function to run.
* @api private
*/
function createPlug(element) {
return function plug(plugin, fn) {
fn = fn || minimize.emits('plugin');
debug('Running plugin for element %s', element.name);
minimize.plugins[plugin].element.call(minimize, element, fn);
}
}
/**
* Reduce each HTML element and its children.
*
* @param {String} html Current compiled HTML, memo.
* @param {Object} element Current element.
* @param {Function} step Completion callback
* @returns {String} minimized HTML.
* @api private
*/
function reduce(html, element, next) {
//

@@ -164,8 +254,23 @@ // Run the registered plugins before the element is processed.

//
if (!plugins.length) return enter();
async.eachSeries(plugins, function plug(plugin, next) {
debug('Running plugin for element %s', element.name);
minimize.plugins[plugin].element.call(minimize, element, next);
}, enter);
}, done);
if (sync) {
plugins.forEach(createPlug(element));
return open(element, html, run(element, next));
}
async.eachSeries(plugins, createPlug(element), function finished(error) {
if (error) return next(error);
return open(element, html, run(element, next));
});
}
//
// Reduce all provided elements to minimized HTML.
//
if (sync) {
debug('Synchronously reducing %d parsed HTML elements', data.length);
return done(null, data.reduce(reduce, html));
}
debug('Asynchronously reducing %d parsed HTML elements', data.length);
return async.reduce(data, html, reduce, done);
};

@@ -172,0 +277,0 @@

{
"name": "minimize",
"version": "1.8.1",
"version": "2.0.0",
"description": "Minimize HTML",

@@ -17,15 +17,15 @@ "main": "./lib/minimize",

"argh": "~0.1.4",
"async": "~1.5.2",
"async": "~2.0.0-rc.6",
"cli-color": "~1.1.0",
"diagnostics": "~1.0.1",
"emits": "~3.0.0",
"htmlparser2": "~3.9.0",
"htmlparser2": "~3.9.1",
"node-uuid": "~1.4.7"
},
"devDependencies": {
"chai": "~3.4.1",
"istanbul": "~0.4.2",
"mocha": "~2.3.4",
"pre-commit": "~1.1.2",
"sinon": "~1.17.2",
"chai": "~3.5.0",
"istanbul": "~0.4.3",
"mocha": "~2.5.3",
"pre-commit": "~1.1.3",
"sinon": "~1.17.4",
"sinon-chai": "~2.8.0"

@@ -32,0 +32,0 @@ },

@@ -34,20 +34,18 @@ # HTML minifier

```javascript
```js
var Minimize = require('minimize')
, minimize = new Minimize({
empty: true, // KEEP empty attributes
cdata: true, // KEEP CDATA from scripts
comments: true, // KEEP comments
ssi: true, // KEEP Server Side Includes
conditionals: true, // KEEP conditional internet explorer comments
spare: true, // KEEP redundant attributes
quotes: true, // KEEP arbitrary quotes
loose: true, // KEEP one whitespace
dom: { // options of !(htmlparser2)[https://github.com/fb55/htmlparser2]
xmlMode: false, // Disables the special behavior for script/style tags (false by default)
lowerCaseAttributeNames: true, // call .toLowerCase for each attribute name (true if xmlMode is `false`)
lowerCaseTags: true // call .toLowerCase for each tag name (true if xmlMode is `false`)
}
});
, content = new Minimize().parse(content);
console.log(content);
```
#### Asynchronous usage
Simply pass a callback as second argument. This is relevant is plugins perform
asynchronous operations.
```js
var Minimize = require('minimize')
, minimize = new Minimize();
minimize.parse(content, function (error, data) {

@@ -58,6 +56,26 @@ console.log(data);

#### Options
List of available options. Note that all options are set to `false` by default and
need to be explicitly enabled by providing `true`. For example `empty: true`.
- [empty](#empty)
- [cdata](#cdata)
- [comments](#comments)
- [ssi](#server-side-includes-ssi)
- [conditionals](#conditionals)
- [spare](#spare)
- [quotes](#quotes)
- [loose](#loose)
- [dom](#dom)
- xmlMode
- lowerCaseAttributeNames
- lowerCaseTags
#### Custom parser
Supplying a custom instance to do the HTML parsing is possible. I.e. this can
be useful if the HTML contains SVG or if you need to specific options to the parser.
```javascript
```js
var Minimize = require('minimize')

@@ -79,3 +97,3 @@ , html = require('htmlparser2')

**Empty**
###### Empty

@@ -86,3 +104,3 @@ Empty attributes can usually be removed, by default all are removed, excluded

```javascript
```js
var Minimize = require('minimize')

@@ -99,3 +117,3 @@ , minimize = new Minimize({ empty: true });

**CDATA**
###### CDATA

@@ -106,3 +124,3 @@ CDATA is only required for HTML to parse as valid XML. For normal webpages this

```javascript
```js
var Minimize = require('minimize')

@@ -119,3 +137,3 @@ , minimize = new Minimize({ cdata: true });

**Comments**
###### Comments

@@ -128,3 +146,3 @@ Comments inside HTML are usually beneficial while developing. Hiding your

```javascript
```js
var Minimize = require('minimize')

@@ -141,3 +159,3 @@ , minimize = new Minimize({ comments: true });

**Server Side Includes (SSI)**
###### Server Side Includes (SSI)

@@ -148,3 +166,3 @@ Server side includes are special set of commands that are support by several

```javascript
```js
var Minimize = require('minimize')

@@ -161,3 +179,3 @@ , minimize = new Minimize({ ssi: true });

**Conditionals**
###### Conditionals

@@ -169,3 +187,3 @@ Conditional comments only work in IE, and are thus excellently suited to give

```javascript
```js
var Minimize = require('minimize')

@@ -182,3 +200,3 @@ , minimize = new Minimize({ conditionals: true });

**Spare**
###### Spare

@@ -188,3 +206,3 @@ Spare attributes are of type boolean of which the value can be omitted in HTML5.

```javascript
```js
var Minimize = require('minimize')

@@ -201,3 +219,3 @@ , minimize = new Minimize({ spare: true });

**Quotes**
###### Quotes

@@ -208,3 +226,3 @@ Quotes are always added around attributes that have spaces or an equal sign in

```javascript
```js
var Minimize = require('minimize')

@@ -221,3 +239,3 @@ , minimize = new Minimize({ quotes: true });

**Loose**
###### Loose

@@ -229,3 +247,3 @@ Minimize will only keep whitespaces in structural elements and remove all other

```javascript
```js
var Minimize = require('minimize')

@@ -242,7 +260,7 @@ , minimize = new Minimize({ loose: true });

**dom**
###### dom
Minimize use !(htmlparser2)[https://github.com/fb55/htmlparser2] to parse the dom. The `dom` option permit to customize htmlparser2.
```javascript
```js
var Minimize = require('minimize')

@@ -265,7 +283,7 @@ , minimize = new Minimize({ dom: { lowerCaseAttributeNames: false }});

```javascript
```js
var Minimize = require('minimize')
, minimize = new Minimize({ plugins: [{
id: 'remove',
element: function element(node, next) {
element: function element(node, next) { // callback is optional
if (node.type === 'text') delete node.data;

@@ -272,0 +290,0 @@ next();

@@ -52,3 +52,3 @@ 'use strict';

function err () {
minimize.minifier('some error', []);
minimize.minifier('id', false, 'some error', []);
}

@@ -66,4 +66,16 @@

it('can emit the parsed content to `minimize.read`');
it('emits the parsed content to `minimize.read`', function (done) {
minimize.once('read', function (error, dom) {
expect(error).to.equal(null);
expect(dom).to.be.an('array');
done();
});
minimize.parse(html.interpunction, function (error, result) {
expect(error).to.equal(null);
expect(result).to.be.an('string');
});
});
it('should start traversing the DOM as soon as HTML parser is ready', function (done) {

@@ -447,3 +459,3 @@ var emit = sinon.spy(minimize, 'emit');

it('should traverse the DOM object and return string', function (done) {
minimize.traverse([html.element], '', function(error, result) {
minimize.traverse([html.element], '', false, function(error, result) {
expect(result).to.be.a('string');

@@ -459,11 +471,26 @@ expect(result).to.be.equal(

describe('#parse', function () {
it('should throw an error if no callback is provided', function () {
function err () {
minimize.parse(html.content, null);
it('should parse the content synchronously without callback', function () {
var result = minimize.parse(html.content);
expect(result).to.be.a('string');
expect(result).to.be.equal(
'<div class="slide nodejs"><h3>100% Node.js</h3><p>We are Node.js experts and the first hosting platform to build our full stack in node. We understand your node application better than anyone.</p></div>'
);
});
it('has the ability to use synchronous plugins to alter elements', function () {
var pluggable = new Minimize({ plugins: [{
id: 'test',
name: 'em',
element: function element(node) {
if (node.name === 'em') {
delete node.children;
}
}
}]});
expect(err).throws('No callback provided');
});
expect(pluggable.parse(html.br)).to.equal("<p class=slide><span><em></em></span><br><br><span>Your private npm registry makes managing them simple by giving you the power to work with a blacklist and a whitelist of public npm packages.</span></p>");
});
describe('#parse', function () {
it('applies callback after DOM is parsed', function () {

@@ -470,0 +497,0 @@ function fn () { }

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc