Permalink
Browse files

Improved support for compile-time defines and includes

  • Loading branch information...
1 parent dd371d6 commit f350f27e840810ce5e18690d6096e9d1cd93a996 @olado committed May 23, 2011
Showing with 84 additions and 34 deletions.
  1. +3 −2 README
  2. +24 −13 benchmarks/templating/doT.js
  3. +24 −13 doT.js
  4. +22 −0 examples/advancedsnippet.txt
  5. +4 −2 examples/snippet.txt
  6. +7 −4 examples/withdoT.js
View
5 README
@@ -44,9 +44,10 @@ Install doT:
Usage:
Default delimiters:
{{= }} for interpolation,
- {{ }} for evaluation,
+ {{ }} for evaluation,
{{! }} for interpolation with encoding,
- {{# }} for compile-time evaluation
+ {{# }} for compile-time evaluation/includes,
+ {{# #}} for compile-time defines
Other delimiters may be configured.
@@ -2,14 +2,15 @@
// 2011, Laura Doktorova
// https://github.com/olado/doT
//
-// doT is a blend of templating functions from jQote2.js
+// doT is a custom blend of templating functions from jQote2.js
// (jQuery plugin) by aefxx (http://aefxx.com/jquery-plugins/jqote2/)
// and underscore.js (http://documentcloud.github.com/underscore/)
+// plus extensions.
//
// Licensed under the MIT license.
//
(function() {
- var doT = { version : '0.1.3' };
+ var doT = { version : '0.1.4' };
if (typeof module !== 'undefined' && module.exports) {
module.exports = doT;
@@ -18,22 +19,32 @@
}
doT.templateSettings = {
- evaluate : /\{\{([\s\S]+?)\}\}/g,
- interpolate : /\{\{=([\s\S]+?)\}\}/g,
- encode : /\{\{!([\s\S]+?)\}\}/g,
- defines: /\{\{#([\s\S]+?)\}\}/g,
- varname : 'it',
+ evaluate: /\{\{([\s\S]+?)\}\}/g,
+ interpolate: /\{\{=([\s\S]+?)\}\}/g,
+ encode: /\{\{!([\s\S]+?)\}\}/g,
+ use: /\{\{#([\s\S]+?)\}\}/g, //compile time evaluation
+ define: /\{\{#\s*([\w$]+)\s*\:([\s\S]+?)#\}\}/g, //compile time defs
+ varname: 'it',
strip : true
};
+ function resolveDefs(define, use, str, defs) {
+ return str.replace(define, function (match, code, value) {
+ if (!(code in defs)) defs[code]=value;
+ return '';
+ })
+ .replace(use, function(match, code) {
+ var value;// todo: detect circular use and convert into compiled functions
+ with(defs) {try { value = eval(code);} catch(e) { value='';} }
+ return value ? resolveDefs(define, use, value.toString(), defs) : value;
+ });
+ }
+
doT.template = function(tmpl, c, defs) {
c = c || doT.templateSettings;
- var str = ("var out='" +
- ((c.strip) ? tmpl.replace(/\s*<!\[CDATA\[\s*|\s*\]\]>\s*|[\r\n\t]|(\/\*[\s\S]*?\*\/)/g, ''):
- tmpl)
- .replace(c.defines, function(match, code) {
- return eval(code.replace(/[\r\t\n]/g, ' '));
- })
+ var str = (c.use || c.define) ? resolveDefs(c.define, c.use, tmpl, defs || {}) : tmpl;
+ str = ("var out='" +
+ ((c.strip) ? str.replace(/\s*<!\[CDATA\[\s*|\s*\]\]>\s*|[\r\n\t]|(\/\*[\s\S]*?\*\/)/g, ''): str)
.replace(/\\/g, '\\\\')
.replace(/'/g, "\\'")
.replace(c.interpolate, function(match, code) {
View
37 doT.js
@@ -2,14 +2,15 @@
// 2011, Laura Doktorova
// https://github.com/olado/doT
//
-// doT is a blend of templating functions from jQote2.js
+// doT is a custom blend of templating functions from jQote2.js
// (jQuery plugin) by aefxx (http://aefxx.com/jquery-plugins/jqote2/)
// and underscore.js (http://documentcloud.github.com/underscore/)
+// plus extensions.
//
// Licensed under the MIT license.
//
(function() {
- var doT = { version : '0.1.3' };
+ var doT = { version : '0.1.4' };
if (typeof module !== 'undefined' && module.exports) {
module.exports = doT;
@@ -18,22 +19,32 @@
}
doT.templateSettings = {
- evaluate : /\{\{([\s\S]+?)\}\}/g,
- interpolate : /\{\{=([\s\S]+?)\}\}/g,
- encode : /\{\{!([\s\S]+?)\}\}/g,
- defines: /\{\{#([\s\S]+?)\}\}/g,
- varname : 'it',
+ evaluate: /\{\{([\s\S]+?)\}\}/g,
+ interpolate: /\{\{=([\s\S]+?)\}\}/g,
+ encode: /\{\{!([\s\S]+?)\}\}/g,
+ use: /\{\{#([\s\S]+?)\}\}/g, //compile time evaluation
+ define: /\{\{#\s*([\w$]+)\s*\:([\s\S]+?)#\}\}/g, //compile time defs
+ varname: 'it',
strip : true
};
+ function resolveDefs(define, use, str, defs) {
+ return str.replace(define, function (match, code, value) {
+ if (!(code in defs)) defs[code]=value;
+ return '';
+ })
+ .replace(use, function(match, code) {
+ var value;// todo: detect circular use and convert into compiled functions
+ with(defs) {try { value = eval(code);} catch(e) { value='';} }
+ return value ? resolveDefs(define, use, value.toString(), defs) : value;
+ });
+ }
+
doT.template = function(tmpl, c, defs) {
c = c || doT.templateSettings;
- var str = ("var out='" +
- ((c.strip) ? tmpl.replace(/\s*<!\[CDATA\[\s*|\s*\]\]>\s*|[\r\n\t]|(\/\*[\s\S]*?\*\/)/g, ''):
- tmpl)
- .replace(c.defines, function(match, code) {
- return eval(code.replace(/[\r\t\n]/g, ' '));
- })
+ var str = (c.use || c.define) ? resolveDefs(c.define, c.use, tmpl, defs || {}) : tmpl;
+ str = ("var out='" +
+ ((c.strip) ? str.replace(/\s*<!\[CDATA\[\s*|\s*\]\]>\s*|[\r\n\t]|(\/\*[\s\S]*?\*\/)/g, ''): str)
.replace(/\\/g, '\\\\')
.replace(/'/g, "\\'")
.replace(c.interpolate, function(match, code) {
@@ -0,0 +1,22 @@
+Advanced templating: illustrates defines and includes.
+
+Include external snippet:
+{{#externalsnippet}}
+
+Here is defs block that will be used later. This snippet can be used in external templates too:
+{{#snippet1:
+ Some snippet that will be included {{#a}} later {{=it.f1}}
+#}}
+
+First use of snippet1:
+{{#snippet1}}
+
+Second use of snippet1:
+{{#snippet1}}
+
+Include if true:
+{{# true && snippet1 }}
+
+Runtime and Compile time evaluation used together:
+{{= it.f3 + {{#a + b}} }}
+
View
@@ -1,11 +1,13 @@
+Core templating
+
<h1>Just static text</h1>
<p>Interpolation {{=it.f1 + it.f3}} </p>
<div> JavaScript block evaluation
{{ for(var i=0; i < it.f2; i++) {
- console.log("\nPass\t" + i);
+ console.log("Pass\t" + i);
}}
<div>{{=it.f3}}</div>
-{{ }; }}
+{{ } }}
</div>
<div> Encoding {{!'<a href="http://github.com"></a>'}}</div>
View
@@ -1,12 +1,15 @@
(function() {
var doT = require('../doT.js'),
- data = { f1: 1, f2: 2, f3: 3};
+ data = { f1: 1, f2: 2, f3: 3},
+ defs = { a: 100, b: 200};
- require('fs').readFile(process.argv[1].replace(/\/[^\/]*$/,'/snippet.txt'), function (err, snippet) {
+ var fs = require('fs');
+ defs.externalsnippet = fs.readFileSync(process.argv[1].replace(/\/[^\/]*$/,'/snippet.txt'));
+ fs.readFile(process.argv[1].replace(/\/[^\/]*$/,'/advancedsnippet.txt'), function (err, snippet) {
if (err) {
- console.log("Error reading snippet.txt " + err);
+ console.log("Error reading advancedsnippet.txt " + err);
} else {
- var doTCompiled = doT.template(snippet.toString());
+ var doTCompiled = doT.template(snippet.toString(), undefined, defs);
console.log("Generated function: \n" + doTCompiled.toString());
console.log("Result of calling with " + JSON.stringify(data) + " :\n" + doTCompiled(data));
}

0 comments on commit f350f27

Please sign in to comment.