diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..72921ab --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.DS_Store* +node_modules diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..a7ae8ee --- /dev/null +++ b/LICENSE @@ -0,0 +1,22 @@ + +The MIT License (MIT) + +Copyright (c) 2014 Jonathan Ong me@jongleberry.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..b3b02ca --- /dev/null +++ b/README.md @@ -0,0 +1,22 @@ + +# Koa HTML Minifier + +Middleware that minifies your HTML responses using [html-minifier](https://github.com/kangax/html-minifier). +It uses `html-minifier`'s default options which are all turned off by default, +so you __have__ to set the options otherwise it's not going to do anything. + +## API + +```js +// do compression stuff first +app.use(require('koa-compress')()); + +// then use this minifier +app.use(require('koa-html-minifier')({ + collapseWhitespace: true +})); +``` + +### Options + +See: https://github.com/kangax/html-minifier#options-quick-reference diff --git a/index.js b/index.js new file mode 100644 index 0000000..1cd5316 --- /dev/null +++ b/index.js @@ -0,0 +1,18 @@ + +var minify = require('html-minifier').minify + +module.exports = function (options) { + options = options || {} + return function* minifyHTML(next) { + yield* next + + if (!this.response.is('html')) return + var body = this.response.body + if (!body) return + // too lazy to handle streams + if (typeof body.pipe === 'function') return + if (Buffer.isBuffer(body)) body = body.toString('utf8') + else if (typeof body === 'object') return // wtf programming + this.response.body = minify(body, options) + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..4720413 --- /dev/null +++ b/package.json @@ -0,0 +1,24 @@ +{ + "name": "koa-html-minifier", + "description": "minify HTML responses like some crazy guy", + "version": "1.0.0", + "author": { + "name": "Jonathan Ong", + "email": "me@jongleberry.com", + "url": "http://jongleberry.com", + "twitter": "https://twitter.com/jongleberry" + }, + "license": "MIT", + "repository": "koajs/html-minifier", + "dependencies": { + "html-minifier": "*" + }, + "devDependencies": { + "koa": "0", + "mocha": "1", + "supertest": "0" + }, + "scripts": { + "test": "mocha --harmony-generators --reporter spec --bail" + } +} diff --git a/test.js b/test.js new file mode 100644 index 0000000..dffc406 --- /dev/null +++ b/test.js @@ -0,0 +1,111 @@ + +var koa = require('koa') +var request = require('supertest') +var PassThrough = require('stream').PassThrough + +var minifier = require('./') + +var options = { + collapseWhitespace: true +} + +describe('Koa HTML Minifier', function () { + describe('when the response is HTML', function () { + var input = '

foo

' + var output = '

foo

' + + describe('and the body is empty', function () { + it('should not crash', function (done) { + var app = koa() + app.use(minifier(options)) + app.use(function* () { + this.body = null + }) + + request(app.listen()) + .get('/') + .expect(204, done) + }) + }) + + describe('and the body is a string', function () { + it('should minify', function (done) { + var app = koa() + app.use(minifier(options)) + app.use(function* () { + this.body = input + }) + + request(app.listen()) + .get('/') + .expect(200) + .expect('Content-Type', /text\/html/) + .expect(output, done) + }) + }) + + describe('and the body is a buffer', function () { + it('should minify', function (done) { + var app = koa() + app.use(minifier(options)) + app.use(function* () { + this.response.type = 'html' + this.body = new Buffer(input, 'utf8') + }) + + request(app.listen()) + .get('/') + .expect(200) + .expect(output, done) + }) + }) + + describe('and the body is an object', function () { + it('should not crash', function (done) { + var app = koa() + app.use(minifier(options)) + app.use(function* () { + this.body = {} + this.response.type = 'html' + }) + + request(app.listen()) + .get('/') + .expect(200, done) + }) + }) + + describe('and the body is a stream', function () { + it('should not minify', function (done) { + var app = koa() + app.use(minifier(options)) + app.use(function* () { + this.response.type = 'html' + var stream = this.body = new PassThrough() + stream.end(input) + }) + + request(app.listen()) + .get('/') + .expect(200) + .expect(input, done) + }) + }) + }) + + describe('when the response is not HTML', function () { + it('should do nothing', function (done) { + var text = 'lol < > <3' + var app = koa() + app.use(minifier(options)) + app.use(function* () { + this.body = text + }) + + request(app.listen()) + .get('/') + .expect(200) + .expect(text, done) + }) + }) +})