Skip to content

Commit

Permalink
Addressing issues olado#121, olado#106, olado#77. Also, added an exam…
Browse files Browse the repository at this point in the history
…ple for express in examples/express. And sporting new logo by @KevinKirchner
  • Loading branch information
olado committed Nov 24, 2014
1 parent daf27a4 commit 829bc7b
Show file tree
Hide file tree
Showing 13 changed files with 191 additions and 52 deletions.
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,3 +70,9 @@ Laura Doktorova @olado

## License
doT is licensed under the MIT License. (See LICENSE-DOT)

<p align="center">
<img src="http://olado.github.io/doT/[email protected]" alt="logo by Kevin Kirchner"/>
</p>


39 changes: 22 additions & 17 deletions benchmarks/templating/doT.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"use strict";

var doT = {
version: '1.0.1',
version: '1.0.2',
templateSettings: {
evaluate: /\{\{([\s\S]+?(\}?)+)\}\}/g,
interpolate: /\{\{=([\s\S]+?)\}\}/g,
Expand All @@ -20,32 +20,34 @@
varname: 'it',
strip: true,
append: true,
selfcontained: false
selfcontained: false,
doNotSkipEncoded: false
},
template: undefined, //fn, compile template
compile: undefined //fn, for express
}, _globals;

doT.encodeHTMLSource = function(doNotSkipEncoded) {
var encodeHTMLRules = { "&": "&#38;", "<": "&#60;", ">": "&#62;", '"': '&#34;', "'": '&#39;', "/": '&#47;' },
matchHTML = doNotSkipEncoded ? /&|<|>|"|'|\//g : /&(?!#?\w+;)|<|>|"|'|\//g;
return function(code) {
return code ? code.replace(matchHTML, function(m) {return encodeHTMLRules[m] || m;}) : "";
};
};

_globals = (function(){ return this || (0,eval)('this'); }());

if (typeof module !== 'undefined' && module.exports) {
module.exports = doT;
} else if (typeof define === 'function' && define.amd) {
define(function(){return doT;});
} else {
(function(){ return this || (0,eval)('this'); }()).doT = doT;
}

function encodeHTMLSource() {
var encodeHTMLRules = { "&": "&#38;", "<": "&#60;", ">": "&#62;", '"': '&#34;', "'": '&#39;', "/": '&#47;' },
matchHTML = /&(?!#?\w+;)|<|>|"|'|\//g;
return function() {
return this ? this.replace(matchHTML, function(m) {return encodeHTMLRules[m] || m;}) : this;
};
_globals.doT = doT;
}
String.prototype.encodeHTML = encodeHTMLSource();

var startend = {
append: { start: "'+(", end: ")+'", endencode: "||'').toString().encodeHTML()+'" },
split: { start: "';out+=(", end: ");out+='", endencode: "||'').toString().encodeHTML();out+='"}
append: { start: "'+(''+", end: ")+'", startencode: "'+encodeHTML(" },
split: { start: "';out+=(''+", end: ");out+='", startencode: "';out+=encodeHTML(" }
}, skip = /$^/;

function resolveDefs(c, block, def) {
Expand Down Expand Up @@ -97,7 +99,7 @@
})
.replace(c.encode || skip, function(m, code) {
needhtmlencode = true;
return cse.start + unescape(code) + cse.endencode;
return cse.startencode + unescape(code) + cse.end;
})
.replace(c.conditional || skip, function(m, elsecase, code) {
return elsecase ?
Expand All @@ -118,8 +120,11 @@
.replace(/(\s|;|\}|^|\{)out\+='';/g, '$1').replace(/\+''/g, '')
.replace(/(\s|;|\}|^|\{)out\+=''\+/g,'$1out+=');

if (needhtmlencode && c.selfcontained) {
str = "String.prototype.encodeHTML=(" + encodeHTMLSource.toString() + "());" + str;
if (needhtmlencode) {
if (!c.selfcontained && _globals && !_globals._encodeHTML) _globals._encodeHTML = doT.encodeHTMLSource(c.doNotSkipEncoded);
str = "var encodeHTML = typeof _encodeHTML !== 'undefined' ? _encodeHTML : ("
+ doT.encodeHTMLSource.toString() + "(" + (c.doNotSkipEncoded || '') + "));"
+ str;
}
try {
return new Function(c.varname, str);
Expand Down
42 changes: 23 additions & 19 deletions doT.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"use strict";

var doT = {
version: '1.0.1',
version: '1.0.2',
templateSettings: {
evaluate: /\{\{([\s\S]+?(\}?)+)\}\}/g,
interpolate: /\{\{=([\s\S]+?)\}\}/g,
Expand All @@ -20,33 +20,34 @@
varname: 'it',
strip: true,
append: true,
selfcontained: false
selfcontained: false,
doNotSkipEncoded: false
},
template: undefined, //fn, compile template
compile: undefined //fn, for express
}, global;
}, _globals;

doT.encodeHTMLSource = function(doNotSkipEncoded) {
var encodeHTMLRules = { "&": "&#38;", "<": "&#60;", ">": "&#62;", '"': '&#34;', "'": '&#39;', "/": '&#47;' },
matchHTML = doNotSkipEncoded ? /&|<|>|"|'|\//g : /&(?!#?\w+;)|<|>|"|'|\//g;
return function(code) {
return code ? code.replace(matchHTML, function(m) {return encodeHTMLRules[m] || m;}) : "";
};
};

_globals = (function(){ return this || (0,eval)('this'); }());

if (typeof module !== 'undefined' && module.exports) {
module.exports = doT;
} else if (typeof define === 'function' && define.amd) {
define(function(){return doT;});
} else {
global = (function(){ return this || (0,eval)('this'); }());
global.doT = doT;
}

function encodeHTMLSource() {
var encodeHTMLRules = { "&": "&#38;", "<": "&#60;", ">": "&#62;", '"': '&#34;', "'": '&#39;', "/": '&#47;' },
matchHTML = /&(?!#?\w+;)|<|>|"|'|\//g;
return function() {
return this ? this.replace(matchHTML, function(m) {return encodeHTMLRules[m] || m;}) : this;
};
_globals.doT = doT;
}
String.prototype.encodeHTML = encodeHTMLSource();

var startend = {
append: { start: "'+(", end: ")+'", endencode: "||'').toString().encodeHTML()+'" },
split: { start: "';out+=(", end: ");out+='", endencode: "||'').toString().encodeHTML();out+='"}
append: { start: "'+(''+", end: ")+'", startencode: "'+encodeHTML(" },
split: { start: "';out+=(''+", end: ");out+='", startencode: "';out+=encodeHTML(" }
}, skip = /$^/;

function resolveDefs(c, block, def) {
Expand Down Expand Up @@ -98,7 +99,7 @@
})
.replace(c.encode || skip, function(m, code) {
needhtmlencode = true;
return cse.start + unescape(code) + cse.endencode;
return cse.startencode + unescape(code) + cse.end;
})
.replace(c.conditional || skip, function(m, elsecase, code) {
return elsecase ?
Expand All @@ -119,8 +120,11 @@
.replace(/(\s|;|\}|^|\{)out\+='';/g, '$1').replace(/\+''/g, '')
.replace(/(\s|;|\}|^|\{)out\+=''\+/g,'$1out+=');

if (needhtmlencode && c.selfcontained) {
str = "String.prototype.encodeHTML=(" + encodeHTMLSource.toString() + "());" + str;
if (needhtmlencode) {
if (!c.selfcontained && _globals && !_globals._encodeHTML) _globals._encodeHTML = doT.encodeHTMLSource(c.doNotSkipEncoded);
str = "var encodeHTML = typeof _encodeHTML !== 'undefined' ? _encodeHTML : ("
+ doT.encodeHTMLSource.toString() + "(" + (c.doNotSkipEncoded || '') + "));"
+ str;
}
try {
return new Function(c.varname, str);
Expand Down
14 changes: 7 additions & 7 deletions doT.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions examples/express/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
require("./lib/app");
25 changes: 25 additions & 0 deletions examples/express/lib/app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
require("dot").process({
global: "_page.render"
, destination: __dirname + "/render/"
, path: (__dirname + "/../templates")
});

var express = require('express')
, http = require('http')
, app = express()
, render = require('./render')
;

app.get('/', function(req, res){
res.send(render.dashboard({text:"Good morning!"}));
});

app.use(function(err, req, res, next) {
console.error(err.stack);
res.status(500).send('Something broke!');
});

var httpServer = http.createServer(app);
httpServer.listen(3000, function() {
console.log('Listening on port %d', httpServer.address().port);
});
18 changes: 18 additions & 0 deletions examples/express/lib/render/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
var path = require('path')
, fs = require('fs');

function req(name) {
var module = require("./" + name);
delete exports[name];
return exports[name] = module;
}

fs.readdirSync(__dirname).forEach(function(file) {
if ((file === 'index.js') || (file[0] === '_')) { return; }
var ext = path.extname(file);
var stats = fs.statSync(__dirname + '/' + file);
if (stats.isFile() && !(ext in require.extensions)) { return; }
var basename = path.basename(file, '.js');
exports.__defineGetter__(basename, function(){ return req(basename); });
});

10 changes: 10 additions & 0 deletions examples/express/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"name": "dot-express-example",
"description": "doT express example",
"version": "0.0.1",
"private": true,
"dependencies": {
"express": "4.x",
"dot": "*"
}
}
5 changes: 5 additions & 0 deletions examples/express/templates/dashboard.jst
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{{##def.test:
{{=it.text}}
#}}

{{#def.test}}
34 changes: 34 additions & 0 deletions examples/express/templates/login.jst
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<html>
<body>
<div>Signin</div>
<form action="/login" method="post">
<div>
<label>Username:</label>
<input type="text" name="username" />
<br/>
</div>
<div>
<label>Password:</label>
<input type="password" name="password" />
</div>
<div>
<input type="submit" value="Sign in" />
</div>
</form>
<div>Signup</div>
<form action="/signup" method="post">
<div>
<label>Username:</label>
<input type="text" name="username" />
<br/>
</div>
<div>
<label>Password:</label>
<input type="password" name="password" />
</div>
<div>
<input type="submit" value="Sign up" />
</div>
</form>
</body>
</html>
2 changes: 1 addition & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ InstallDots.prototype.compileToFile = function(path, template, def) {
}
compiled += defaultcompiled.toString().replace('anonymous', modulename);
fs.writeFileSync(path, "(function(){" + compiled
+ "var itself=" + modulename + ";"
+ "var itself=" + modulename + ", _encodeHTML=(" + doT.encodeHTMLSource.toSource() + "(" + (settings.doNotSkipEncoded || '') + "));"
+ addexports(exports)
+ "if(typeof module!=='undefined' && module.exports) module.exports=itself;else if(typeof define==='function')define(function(){return itself;});else {"
+ this.__global + "=" + this.__global + "||{};" + this.__global + "['" + modulename + "']=itself;}}());");
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"simple",
"templating"
],
"version": "1.0.1",
"version": "1.0.2",
"main": "index",
"bin": {
"dottojs": "./bin/dot-packer"
Expand Down
45 changes: 38 additions & 7 deletions test/testdoT.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,54 @@ describe('doT', function(){

describe('#template()', function(){
it('should return a function', function(){
assert.equal("function", typeof basiccompiled);
assert.equal(typeof basiccompiled, "function");
});
});

describe('#()', function(){
it('should render the template', function(){
assert.equal("<div>http</div>", basiccompiled({foo:"http"}));
assert.equal("<div>http:&#47;&#47;abc.com</div>", basiccompiled({foo:"http://abc.com"}));
assert.equal("<div></div>", basiccompiled({}));
assert.equal(basiccompiled({foo:"http"}), "<div>http</div>");
assert.equal(basiccompiled({foo:"http://abc.com"}), "<div>http:&#47;&#47;abc.com</div>");
assert.equal(basiccompiled({}), "<div></div>");
});
});

describe('defines', function(){
it('should render define', function(){
assert.equal("<div>http</div>", definescompiled({foo:"http"}));
assert.equal("<div>http:&#47;&#47;abc.com</div>", definescompiled({foo:"http://abc.com"}));
assert.equal("<div></div>", definescompiled({}));
assert.equal(definescompiled({foo:"http"}), "<div>http</div>");
assert.equal(definescompiled({foo:"http://abc.com"}), "<div>http:&#47;&#47;abc.com</div>");
assert.equal(definescompiled({}), "<div></div>");
});
});

describe('encoding with doNotSkipEncoded=false', function() {
it('should not replace &', function() {
global._encodeHTML = undefined;
doT.templateSettings.doNotSkipEncoded = false;
assert.equal(doT.template(definestemplate)({foo:"&amp;"}), "<div>&amp;</div>");
});
});

describe('evaluate 2 numbers', function() {
it('should print numbers next to each other', function() {
var fn = doT.template("{{=it.one}}{{=it.two}}");
assert.equal(fn({one:1, two: 2}), "12");
});
});

describe('evaluate 2 numbers in the middle', function() {
it('should print numbers next to each other', function() {
var fn = doT.template("{{?it.one}}{{=it.one}}{{?}}{{=it.one}}{{=it.two}}");
assert.equal(fn({one:1, two: 2}), "112");
});
});

describe('encoding with doNotSkipEncoded=true', function() {
it('should replace &', function() {
global._encodeHTML = undefined;
doT.templateSettings.doNotSkipEncoded = true;
assert.equal(doT.template(definestemplate)({foo:"&amp;"}), "<div>&#38;amp;</div>");
});
});

});

0 comments on commit 829bc7b

Please sign in to comment.