/
compiler.js
103 lines (88 loc) · 3 KB
/
compiler.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
var fs = require("fs");
var path = require("path");
var UglifyJS = require("uglify-js");
require("./tweeg.js");
require("./runtime.js");
function compile(files, options) {
function option(name, def) {
var val = options && options[name];
return val === undefined ? def : val;
}
var paths = option("paths", {});
var base = option("base", null);
var beautify = option("beautify", false);
var extend = option("extend", null);
var runtime = option("runtime", TWEEG_RUNTIME());
var tweeg = option("tweeg", TWEEG(runtime).init());
var wrap_template = option("wrap_template", tmpl => tmpl);
var nodeps = option("nodeps", false);
var warnings = option("warnings", false);
var code = "";
var compiled = {};
files.forEach(function(file){
compileFile(file);
});
code = TWEEG.wrap_code(code);
if (beautify) {
var ast = UglifyJS.parse(code);
return ast.print_to_string({ beautify: true });
} else {
var ugly = UglifyJS.minify([ code ], {
fromString: true,
warnings: warnings,
compress: {
pure_getters : true,
unsafe : true,
unsafe_comps : true,
hoist_vars : true,
pure_funcs : ("$OUT,$ESC,$ESC_html,$ESC_js,$FILTER,$HASH,$MERGE,$NUMBER,$STR,$EMPTY,$SLICE,$GLOBAL").split(/,/)
}
});
return ugly.code;
}
function compileFile(template_name, source) {
template_name = template_name.replace(/\\/g, "/").replace(/\/\/+/g, "/");
var fullname = replacePaths(template_name);
if (source) {
fullname = path.resolve(path.dirname(source), fullname);
} else {
fullname = path.resolve(fullname);
}
if (compiled[fullname]) {
return;
}
compiled[fullname] = true;
var tmpl = fs.readFileSync(fullname, "utf8");
var ast, result;
if (base && !source) {
template_name = path.relative(base, template_name);
}
try {
ast = tweeg.parse(tmpl);
result = tweeg.compile(ast, {
autoescape: option("escape", "html")
});
} catch(ex) {
throw new Error(`Template: ${template_name}\n${ex}`);
}
if (!nodeps) result.dependencies.forEach(function(file){
if (typeof file == "string") {
compileFile(file, fullname);
} else {
warn(`Complex dependency in ${template_name}: ${JSON.stringify(file)}`);
}
});
code += wrap_template(`$REGISTER(${JSON.stringify(template_name)}, ${result.code});`, template_name);
}
function replacePaths(filename) {
return filename.replace(/@[a-z0-9_]+/ig, function(name){
return paths[name.substr(1)];
});
}
function warn(msg) {
if (warnings) {
console.error(msg);
}
}
}
exports.compile = compile;