1 | var jade = require('jade');
|
2 | var beautify = require('./lib/beautify');
|
3 | var simplifyTemplate = require('./lib/simplifyTemplate');
|
4 | var transformMixins = require('./lib/transformMixins');
|
5 | var renameJadeFn = require('./lib/renameJadeFn');
|
6 | var walkdir = require('walkdir');
|
7 | var path = require('path');
|
8 | var _ = require('underscore');
|
9 | var fs = require('fs');
|
10 | var uglifyjs = require('uglify-js');
|
11 | var namedTemplateFn = require('./lib/namedTemplateFn');
|
12 | var bracketedName = require('./lib/bracketedName');
|
13 |
|
14 |
|
15 | module.exports = function (templateDirectories, outputFile, options) {
|
16 | options || (options = {});
|
17 |
|
18 | var internalNamespace = 'templatizer';
|
19 |
|
20 | _.defaults(options, {
|
21 | dontTransformMixins: false,
|
22 | jade: {},
|
23 | namespace: ''
|
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 |
|
39 | if (namespace) {
|
40 | namespace = bracketedName(namespace.split('.'));
|
41 | }
|
42 |
|
43 |
|
44 |
|
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 |
|
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 | };
|