-
Notifications
You must be signed in to change notification settings - Fork 15
/
cli.js
128 lines (114 loc) · 3.78 KB
/
cli.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
#!/usr/bin/env node
/*global require, process */
(function() {
"use strict";
var fs = require('fs');
var path = require('path');
var jinja = require('./jinja');
//if uglify-js is installed
try {
var uglifyjs = require('uglify-js');
} catch(e) {}
var cwd = process.cwd(), dir = cwd;
//path delimiter is platform-specific
var join = path.join;
var dirname = path.dirname;
var basename = path.basename;
//path delimiter is forward-slash
var urljoin = function() {
var path = join.apply(null, arguments);
return path.replace(/\\/g, '/');
};
var args = process.argv.slice(2);
var flags = {};
while (args.length && args[0].charAt(0) == '-') {
var flag = args.shift().replace(/^-+/, '');
flags[flag] = 1;
}
var paths = args;
if (!paths.length) {
console.log('No file specified');
process.exit(1);
}
var fileCache = {};
function register($name, $func) {
(function(name, func) {
var tmpl = {name: name, render: func};
var module = (typeof jinja != 'undefined') ? jinja : (typeof require == 'function') ? require('jinja') : null;
if (module && module.compiled) {
module.compiled[name] = tmpl;
}
return tmpl;
})($name, $func);
}
//allows includes and template inheritance to work
jinja.readTemplateFile = function(name) {
//include directives might leave out the file extension
var file = (~name.indexOf('.')) ? name : name + '.html';
if (file in fileCache) {
return fileCache[file];
}
return fileCache[file] = fs.readFileSync(join(dir, file), 'utf8');
};
//use uglifyjs to minify compiled template
var uglifyCode = function(code) {
if (!uglifyjs) return code;
var jsp = uglifyjs.parser;
var pro = uglifyjs.uglify;
var ast = jsp.parse(code); // parse code and get the initial AST
ast = pro.ast_mangle(ast); // get a new AST with mangled names
ast = pro.ast_squeeze(ast); // get an AST with compression optimizations
return pro.gen_code(ast); // compressed code here
};
//writes compiled template ./views/main.html -> /views/main.html.js
var compileFile = function(file) {
console.log('Compiling: ' + file);
var text = jinja.readTemplateFile(file);
var fn = jinja.compile(text).render;
var code = fn.toString().replace(/^([^(]*)/, 'function');
var compiled = register.toString();
compiled = compiled.replace(/^function(.*?)\{([\s\S]*)\}/, '$2').trim();
compiled = compiled.replace('$name', JSON.stringify(file));
compiled = compiled.replace('$func', code);
if (flags.min) {
compiled = uglifyCode(compiled);
}
fs.writeFileSync(join(dir, file + '.js'), compiled, 'utf8');
};
var compilePath = function(path) {
try {
var list = fs.readdirSync(join(dir, path));
} catch(e) {}
if (list) {
//handle directories recursively
list.forEach(function(name) {
//skip files that begin with a symbol
if (!name.match(/^[a-z]/i)) return;
compilePath(urljoin(path, name));
});
} else
if (path.match(/\.html$/)) {
compileFile(path);
}
};
var isDir = function(path) {
try {
var stat = fs.statSync(join(dir, path));
} catch(e) {}
return (stat && stat.isDirectory()) ? true : false;
};
//for each path, we set the working directory and process the file or directory contents
paths.forEach(function(path) {
//remove trailing slash
path = path.replace(/[\\\/]$/, '');
if (isDir(path)) {
dir = join(cwd, path);
fs.readdirSync(dir).forEach(function(path) {
compilePath(path);
});
} else {
dir = join(cwd, path);
compilePath(basename(path));
}
});
})();