-
Notifications
You must be signed in to change notification settings - Fork 1k
/
index.js
150 lines (137 loc) · 5.51 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
/* doT + auto-compilation of doT templates
*
* 2012, Laura Doktorova, https://github.com/olado/doT
* Licensed under the MIT license
*
* Compiles .def, .dot, .jst files found under the specified path.
* It ignores sub-directories.
* Template files can have multiple extensions at the same time.
* Files with .def extension can be included in other files via {{#def.name}}
* Files with .dot extension are compiled into functions with the same name and
* can be accessed as renderer.filename
* Files with .jst extension are compiled into .js files. Produced .js file can be
* loaded as a commonJS, AMD module, or just installed into a global variable
* (default is set to window.render).
* All inline defines defined in the .jst file are
* compiled into separate functions and are available via _render.filename.definename
*
* Basic usage:
* var dots = require("dot").process({path: "./views"});
* dots.mytemplate({foo:"hello world"});
*
* The above snippet will:
* 1. Compile all templates in views folder (.dot, .def, .jst)
* 2. Place .js files compiled from .jst templates into the same folder.
* These files can be used with require, i.e. require("./views/mytemplate").
* 3. Return an object with functions compiled from .dot templates as its properties.
* 4. Render mytemplate template.
*/
var fs = require("fs"),
doT = module.exports = require("./doT");
doT.process = function(options) {
//path, destination, global, rendermodule, templateSettings
return new InstallDots(options).compileAll();
};
function InstallDots(o) {
this.__path = o.path || "./";
if (this.__path[this.__path.length-1] !== '/') this.__path += '/';
this.__destination = o.destination || this.__path;
if (this.__destination[this.__destination.length-1] !== '/') this.__destination += '/';
this.__global = o.global || "window.render";
this.__rendermodule = o.rendermodule || {};
this.__settings = Object.prototype.hasOwnProperty.call(o,"templateSettings") ? copy(o.templateSettings, copy(doT.templateSettings)) : undefined;
this.__includes = {};
}
InstallDots.prototype.compileToFile = function(path, template, def) {
def = def || {};
var modulename = path.substring(path.lastIndexOf("/")+1, path.lastIndexOf("."))
, defs = copy(this.__includes, copy(def))
, settings = this.__settings || doT.templateSettings
, compileoptions = copy(settings)
, defaultcompiled = doT.template(template, settings, defs)
, exports = []
, compiled = ""
, fn;
for (var property in defs) {
// It looks like the code block inside "if" below can never be executed,
// because InstallDots constructor is private, compileToFile is only called from compileAll method
// and def parameter is never passed to it, so the condition in if will always fail.
// This code will be removed from the next major version.
// For now it is only excluded from coverage report
/* istanbul ignore if */
if (defs[property] !== def[property] && defs[property] !== this.__includes[property]) {
fn = undefined;
if (typeof defs[property] === 'string') {
fn = doT.template(defs[property], settings, defs);
} else if (typeof defs[property] === 'function') {
fn = defs[property];
} else if (defs[property].arg) {
compileoptions.varname = defs[property].arg;
fn = doT.template(defs[property].text, compileoptions, defs);
}
if (fn) {
compiled += fn.toString().replace('anonymous', property);
exports.push(property);
}
}
}
compiled += defaultcompiled.toString().replace('anonymous', modulename);
fs.writeFileSync(path, "(function(){" + compiled
+ "var itself=" + modulename + ", _encodeHTML=(" + doT.encodeHTMLSource.toString() + "(" + (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;}}());");
};
function addexports(exports) {
var ret = '';
for (var i=0; i< exports.length; i++) {
ret += "itself." + exports[i]+ "=" + exports[i]+";";
}
return ret;
}
function copy(o, to) {
to = to || {};
for (var property in o) {
to[property] = o[property];
}
return to;
}
function readdata(path) {
var data = fs.readFileSync(path);
if (data) return data.toString();
console.log("problems with " + path);
}
InstallDots.prototype.compilePath = function(path) {
var data = readdata(path);
if (data) {
return doT.template(data,
this.__settings || doT.templateSettings,
copy(this.__includes));
}
};
InstallDots.prototype.compileAll = function() {
if (doT.log) console.log("Compiling all doT templates...");
var defFolder = this.__path,
sources = fs.readdirSync(defFolder),
k, l, name;
for( k = 0, l = sources.length; k < l; k++) {
name = sources[k];
if (/\.def(\.dot|\.jst)?$/.test(name)) {
if (doT.log) console.log("Loaded def " + name);
this.__includes[name.substring(0, name.indexOf('.'))] = readdata(defFolder + name);
}
}
for( k = 0, l = sources.length; k < l; k++) {
name = sources[k];
if (/\.dot(\.def|\.jst)?$/.test(name)) {
if (doT.log) console.log("Compiling " + name + " to function");
this.__rendermodule[name.substring(0, name.indexOf('.'))] = this.compilePath(defFolder + name);
}
if (/\.jst(\.dot|\.def)?$/.test(name)) {
if (doT.log) console.log("Compiling " + name + " to file");
this.compileToFile(this.__destination + name.substring(0, name.indexOf('.')) + '.js',
readdata(defFolder + name));
}
}
return this.__rendermodule;
};