UNPKG

5.35 kBJavaScriptView Raw
1var jade = require('jade');
2var beautify = require('./lib/beautify');
3var simplifyTemplate = require('./lib/simplifyTemplate');
4var transformMixins = require('./lib/transformMixins');
5var renameJadeFn = require('./lib/renameJadeFn');
6var walkdir = require('walkdir');
7var path = require('path');
8var _ = require('underscore');
9var fs = require('fs');
10var uglifyjs = require('uglify-js');
11var namedTemplateFn = require('./lib/namedTemplateFn');
12var bracketedName = require('./lib/bracketedName');
13
14
15module.exports = function (templateDirectories, outputFile, options) {
16 options || (options = {});
17
18 var internalNamespace = 'templatizer';
19
20 _.defaults(options, {
21 dontTransformMixins: false,
22 jade: {},
23 namespace: '' // No namespace means 'window'
24 });
25
26 if (typeof templateDirectories === "string") {
27 templateDirectories = [templateDirectories];
28 }
29
30 var namespace = _.isString(options.namespace) ? options.namespace : '';
31 var folders = [];
32 var templates = [];
33 var _readTemplates = [];
34 var isWindows = process.platform === 'win32';
35 var pathSep = path.sep || (isWindows ? '\\' : '/');
36 var pathSepRegExp = /\/|\\/g;
37
38 // Split our namespace on '.' and use bracket syntax
39 if (namespace) {
40 namespace = bracketedName(namespace.split('.'));
41 }
42
43 // Find jade runtime and create minified code
44 // where it is assigned to the variable jade
45 var placesToLook = [
46 __dirname + '/node_modules/jade/lib/runtime.js',
47 __dirname + '/jaderuntime.js'
48 ];
49 var jadeRuntime = fs.readFileSync(_.find(placesToLook, fs.existsSync)).toString();
50 var wrappedJade = uglifyjs.minify('var jade = (function(){var exports={};' + jadeRuntime + 'return exports;})();', {fromString: true}).code;
51
52 var outputTemplate = fs.readFileSync(__dirname + '/output_template.js').toString();
53 var output = '';
54
55 var jadeCompileOptions = {
56 client: true,
57 compileDebug: false,
58 pretty: false
59 };
60 _.extend(jadeCompileOptions, options.jade);
61
62 templateDirectories = _.map(templateDirectories, function (templateDirectory) {
63 return templateDirectory.replace(pathSepRegExp, pathSep);
64 });
65
66 templateDirectories.forEach(function (templateDirectory) {
67 if (!fs.existsSync(templateDirectory)) {
68 throw new Error('Template directory ' + templateDirectory + ' does not exist.');
69 }
70
71 walkdir.sync(templateDirectory).forEach(function (file) {
72 var item = file.replace(path.resolve(templateDirectory), '').slice(1);
73 if (path.extname(item) === '' && path.basename(item).charAt(0) !== '.') {
74 if (folders.indexOf(item) === -1) folders.push(item);
75 } else if (path.extname(item) === '.jade') {
76 // Throw an err if we are about to override a template
77 if (_readTemplates.indexOf(item) > -1) {
78 throw new Error(item + ' from ' + templateDirectory + pathSep + item + ' already exists in ' + templates[_readTemplates.indexOf(item)]);
79 }
80 _readTemplates.push(item);
81 templates.push(templateDirectory + pathSep + item);
82 }
83 });
84
85 folders = _.sortBy(folders, function (folder) {
86 var arr = folder.split(pathSep);
87 return arr.length;
88 });
89 });
90
91 output += folders.map(function (folder) {
92 return internalNamespace + bracketedName(folder.split(pathSep)) + ' = {};';
93 }).join('\n') + '\n';
94
95 templates.forEach(function (item) {
96 var name = path.basename(item, '.jade');
97 var dirString = function () {
98 var itemTemplateDir = _.find(templateDirectories, function (templateDirectory) {
99 return item.indexOf(templateDirectory + pathSep) === 0;
100 });
101 var dirname = path.dirname(item).replace(itemTemplateDir, '');
102 if (dirname === '.') return name;
103 dirname += '.' + name;
104 return dirname.substring(1).replace(pathSepRegExp, '.');
105 }();
106
107 jadeCompileOptions.filename = item;
108 var template = beautify(jade.compileClient(fs.readFileSync(item, 'utf-8'), jadeCompileOptions).toString());
109
110 template = renameJadeFn(template, dirString);
111 template = simplifyTemplate(template);
112
113 var mixins = [];
114 if (!options.dontTransformMixins) {
115 var astResult = transformMixins({
116 template: template,
117 name: name,
118 dir: dirString,
119 rootName: internalNamespace
120 });
121 mixins = astResult.mixins;
122 template = astResult.template;
123 }
124
125 output += namedTemplateFn({
126 dir: dirString,
127 rootName: internalNamespace,
128 fn: template
129 });
130
131 output += mixins.join('\n');
132 });
133
134 var indentOutput = output.split('\n').map(function (l) { return l ? ' ' + l : l; }).join('\n');
135 var finalOutput = outputTemplate
136 .replace(/\{\{namespace\}\}/g, namespace)
137 .replace(/\{\{internalNamespace\}\}/g, internalNamespace)
138 .replace('{{jade}}', wrappedJade)
139 .replace('{{code}}', indentOutput);
140
141 if (outputFile) fs.writeFileSync(outputFile, finalOutput);
142
143 return finalOutput;
144};