From a7d733f7dae1038e6a52ecf1c65c13defcec349c Mon Sep 17 00:00:00 2001 From: Timothy Gu Date: Wed, 28 Jan 2015 19:19:03 -0800 Subject: [PATCH] Add rmWhitespace mode It is not a full-fledged HTML minifier, nor will it be. It is designed to be as "safe" as possible. Fixes #51. --- README.md | 1 + lib/ejs.js | 12 +++++++++++- test/ejs.js | 12 ++++++++++++ test/fixtures/no.semicolons.rmWhitespace.html | 2 ++ test/fixtures/rmWhitespace.ejs | 11 +++++++++++ test/fixtures/rmWhitespace.html | 7 +++++++ 6 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 test/fixtures/no.semicolons.rmWhitespace.html create mode 100644 test/fixtures/rmWhitespace.ejs create mode 100644 test/fixtures/rmWhitespace.html diff --git a/README.md b/README.md index cd0a9118..359ae5ab 100644 --- a/README.md +++ b/README.md @@ -57,6 +57,7 @@ for all the passed options. - `delimiter` Character to use with angle brackets for open/close - `debug` Output generated function body - `_with` Whether or not to use `with() {}` constructs. If `false` then the locals will be stored in the `locals` object. + - `rmWhitespace` Remove all safe-to-remove whitespace, including `\r`, leading and trailing whitespace. This also enables `-%>` new line slurping for all scriptlet tags. ## Tags diff --git a/lib/ejs.js b/lib/ejs.js index d0c4203e..efcd8643 100644 --- a/lib/ejs.js +++ b/lib/ejs.js @@ -31,6 +31,7 @@ var fs = require('fs') , _TRAILING_SEMCOL = /;\s*$/; exports.localsName = _DEFAULT_LOCALS_NAME; +exports.rmWhitespace = false; function resolveInclude(name, filename) { var path = require('path') @@ -223,6 +224,9 @@ function Template(text, opts) { options.delimiter = opts.delimiter || exports.delimiter || _DEFAULT_DELIMITER; options._with = typeof opts._with != 'undefined' ? opts._with : true; options.cache = opts.cache || false; + options.rmWhitespace = opts.rmWhitespace !== undefined + ? opts.rmWhitespace + : exports.rmWhitespace; this.opts = options; this.regex = this.createRegex(); @@ -250,6 +254,9 @@ Template.prototype = new function () { , opts = this.opts , escape = opts.escapeFunction; + if (opts.rmWhitespace) { + this.templateText = this.templateText.replace(/^\s+|\s+$|\r/gm, ''); + } if (!this.source) { this.generateSource(); var prepended = 'var __output = "";'; @@ -392,6 +399,9 @@ Template.prototype = new function () { function _addOutput() { if (self.truncate) { line = line.replace('\n', ''); + if (!line) { + return; + } } // Preserve literal slashes @@ -433,7 +443,7 @@ Template.prototype = new function () { } this.mode = null; - this.truncate = line.indexOf('-') === 0; + this.truncate = line.indexOf('-') === 0 || self.opts.rmWhitespace; break; default: // In script mode, depends on type of tag diff --git a/test/ejs.js b/test/ejs.js index 00c1cede..6ed37b53 100644 --- a/test/ejs.js +++ b/test/ejs.js @@ -520,6 +520,18 @@ suite('exceptions', function () { }); }); +suite('rmWhitespace', function () { + test('works', function () { + assert.equal(ejs.render(fixture('rmWhitespace.ejs'), {}, {rmWhitespace: true}), + fixture('rmWhitespace.html')); + }); + + test('works without semicolons', function () { + assert.equal(ejs.render(fixture('no.semicolons.ejs'), {}, {rmWhitespace: true}), + fixture('no.semicolons.rmWhitespace.html')); + }); +}); + suite('include()', function () { test('include ejs', function () { var file = 'test/fixtures/include-simple.ejs'; diff --git a/test/fixtures/no.semicolons.rmWhitespace.html b/test/fixtures/no.semicolons.rmWhitespace.html new file mode 100644 index 00000000..d9f92bee --- /dev/null +++ b/test/fixtures/no.semicolons.rmWhitespace.html @@ -0,0 +1,2 @@ +This document does not use semicolons in scriptlets. +The value of c is: c \ No newline at end of file diff --git a/test/fixtures/rmWhitespace.ejs b/test/fixtures/rmWhitespace.ejs new file mode 100644 index 00000000..7dd6b5d8 --- /dev/null +++ b/test/fixtures/rmWhitespace.ejs @@ -0,0 +1,11 @@ + + +A very long piece of text very long piece of text very long piece of text very +long piece of text very long piece of text very long piece of text very long +piece of text. +<% var a = 'a' %> +Text again. +<% var b = 'b' %> +<% var c = 'c' +var d = 'd' %> +Another text. diff --git a/test/fixtures/rmWhitespace.html b/test/fixtures/rmWhitespace.html new file mode 100644 index 00000000..4296ee2a --- /dev/null +++ b/test/fixtures/rmWhitespace.html @@ -0,0 +1,7 @@ + + +A very long piece of text very long piece of text very long piece of text very +long piece of text very long piece of text very long piece of text very long +piece of text. +Text again. +Another text. \ No newline at end of file