UNPKG

5.11 kBJavaScriptView Raw
1var async = require('async');
2var fs = require('fs');
3var minify = require('html-minifier').minify;
4var path = require('path');
5var cheerio = require('cheerio');
6var engine;
7
8function TemplateEngine() {
9
10 var self = this;
11 var _config = {};
12
13 function readAsync(file, callback) {
14 if (file)
15 fs.readFile(file, 'utf8', callback);
16 }
17
18 function embedIncludes(template, source) {
19
20 var $ = cheerio.load(template, {decodeEntities: false});
21 var ele = $('[ng-include]').first();
22 var src = path.dirname(source) + '/' + ($(ele).attr('ng-include') || $(ele).attr('src')).replace(/"/g, '').replace(/'/g, '').trim();
23 var include = fs.readFileSync(src, 'utf8');
24 $(ele).append(include);
25 return $.html();
26 }
27
28 self.config = {
29 get: function () {
30 return _config;
31 },
32 set: function (config) {
33 _config = config || {};
34 }
35 }
36
37 self.source = {
38 hash: function (raw, base) {
39 var source = {contents: raw, templates: []};
40 var parts = source.contents.split(/(?=templateUrl)/g);
41
42 parts.forEach(function (element, index) {
43
44 var match = (element.match(/(?!,)templateUrl(.*)$/gm));
45
46 if (match) {
47 var templateUrl = match[0].split(':')[1].split(',')[0].replace(/"/g, '').replace(/'/g, '').trim()
48 var relative = path.resolve(__dirname + base, '../' + templateUrl);
49 source.templates.push(relative);
50 }
51 });
52
53 return source;
54 },
55 read: function (target) {
56 var deferred = new Promise(function (resolve, reject) {
57 fs.readFile(__dirname + target, 'utf8', function (err, data) {
58 resolve(data);
59 });
60 });
61
62 return deferred;
63 }
64 }
65
66 self.templates = {
67 get: function (source) {
68
69 var deferred = new Promise(function (resolve, reject) {
70 async.map(source.templates, readAsync, function (err, results) {
71
72 results.forEach(function (element, index, arr) {
73
74 var t, $ = cheerio.load(element, {decodeEntities: false});
75
76 if ($($.html()).find('[ng-include]').length > 0 && _config.includes) {
77 t = embedIncludes($.html(), source.templates[index])
78 }
79
80 var template = minify((t || $.html()), {collapseWhitespace: true, removeComments: true}) // minify the markup
81 source.templates[index] = template
82 resolve(source);
83 });
84
85 resolve(source);
86 });
87 });
88
89 return deferred;
90 },
91 set: function (transformed) {
92 var deferred = new Promise(function (resolve, reject) {
93
94 var parts = transformed.contents.split(/(?=templateUrl)(?!,)/g);
95
96 parts.forEach(function (element, index, arr) {
97
98 var match = (element.match(/(?!,)templateUrl(.*)$/gm));
99
100 if (match)
101 arr[index] = arr[index].replace(/(?!,)templateUrl(.*),$/gm, 'template: \'' + transformed.templates.shift().replace(/'/g, "\\'") + '\',')
102 });
103
104 resolve(parts.join(''));
105 });
106
107 return deferred;
108 }
109 }
110}
111
112// TODO - solve pathing weirdness
113// TODO - refine poor regex check
114// TODO - relay options to html-minifier
115// TODO - identify failure points and return error through callbacks
116// TODO - refine templating for ng-include support
117// TODO - README
118// TODO - cli
119
120function TemplateManager() {
121
122 var self = this;
123
124 self.inline = function (input, config, done) { // -- in
125
126 engine = new TemplateEngine();
127 engine.config.set(config);
128
129 // more robust gulp check mayhaps?
130 if (input.contents) {
131 var base = '/' + path.dirname(path.relative(__dirname, config.target));
132 var source = engine.source.hash(input, base);
133
134 engine.templates.get(source).then(function (transformed) {
135 engine.templates.set(transformed).then(function (output) {
136 done(output); // -- out
137 });
138 });
139 } else {
140 engine.source.read(input).then(function (data) {
141
142 var base = path.dirname(input);
143 var source = engine.source.hash(data, base);
144
145 engine.templates.get(source).then(function (transformed) {
146 engine.templates.set(transformed).then(function (output) {
147 done(output); // -- out
148 });
149 });
150 });
151 }
152 }
153}
154
155module.exports = new TemplateManager();
156module.exports.engine = new TemplateEngine();
\No newline at end of file